tree.scala

来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 407 行

SCALA
407
字号
/*                     __                                               *\**     ________ ___   / /  ___     Scala API                            ****    / __/ __// _ | / /  / _ |    (c) 2003-2007, LAMP/EPFL             ****  __\ \/ /__/ __ |/ /__/ __ |    http://scala-lang.org/               **** /____/\___/_/ |_/____/_/ | |                                         ****                          |/                                          **\*                                                                      */// $Id: Tree.scala 12246 2007-07-09 11:53:05Z moors $/* General Balanced Trees - highly efficient functional dictionaries.**** This is a scala version of gb_trees.erl which is** copyrighted (C) 1999-2001 by Sven-Olof Nystrom, and Richard Carlsson**** An efficient implementation of Prof. Arne Andersson's General** Balanced Trees. These have no storage overhead compared to plain** unbalanced binary trees, and their performance is in general better** than AVL trees.** ---------------------------------------------------------------------** This library is free software; you can redistribute it and/or modify** it under the terms of the GNU Lesser General Public License as** published by the Free Software Foundation; either version 2 of the** License, or (at your option) any later version.**** This library is distributed in the hope that it will be useful, but** WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU** Lesser General Public License for more details.**** You should have received a copy of the GNU Lesser General Public** License along with this library; if not, write to the Free Software** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307** USA**** Author contact: "erik"+"."+"stenman"+"@"+"epfl"+"."+"ch"** ---------------------------------------------------------------------*/package scala.collection.immutable//import Predef.NoSuchElementException/** <p> *    General Balanced Trees - highly efficient functional dictionaries. *  </p> *  <p> *    An efficient implementation of Prof. Arne Andersson's *    <a href="http://citeseer.ist.psu.edu/andersson99general.html" *    target="_top">General Balanced Trees</a>. These have no storage overhead *    compared to plain unbalanced binary trees, and their performance is in *    general better than AVL trees. *  </p> *  <p> *    This implementation does not balance the trees after deletions. *    Since deletions don't increase the height of a tree, this should *    be OK in most applications. A balance method is provided for those *    cases where rebalancing is needed. *  </p> *  <p> *    The tree consists of entries conatining a key with an order. *  </p> *  <p> *    When instanciating the tree an order for the keys has to be *    supplied. *  </p> * *  @author  Erik Stenman, Michel Schinz *  @version 1.1, 2005-01-20 */@serializableabstract class Tree[A <% Ordered[A], B]() extends AnyRef {  /* Data structure:  ** - size:Int - the number of elements in the tree.  ** - tree:T, which is composed of nodes of the form:  **   - GBNode(key: A, entry:B, smaller:T, bigger:T),  **   - and the "empty tree" node GBLeaf.  **  ** Original balance condition h(T) <= ceil(c * log(|T|)) has been  ** changed to the similar (but not quite equivalent) condition  ** 2 ^ h(T) <= |T| ^ c.  **  */  /** The type returned when creating a new tree.   *  This type should be defined by concrete implementations   *  e.g. <pre>   *  class C[T](...) extends Tree[A,B](...) {   *    type This = C[T];   *  </pre>   */  protected type This <: Tree[A,B]  protected def getThis: This  /**   *  The type of nodes that the tree is build from.   */  protected type aNode = GBTree[A,B]  /** The nodes in the tree.   */  protected def tree: aNode = GBLeaf[A,B]()  /** <p>   *    This abstract method should be defined by a concrete implementation   *    <code>C[T]</code> as something like:   *  </p>   *  <pre>   *    <b>override def</b> New(sz: Int, t: aNode): This {   *      <b>new</b> C[T](order) {   *        <b>override def</b> size = sz   *        <b>override protected def</b> tree: aNode = t   *    }   *  </pre>   *  <p>   *     The concrete implementation should also override the def of This   *     <code>override type This = C[T];</code>   *  </p>   */  protected def New(sz: Int, t: aNode): This  /** The size of the tree, returns 0 (zero) if the tree is empty.   *   *  @return The number of nodes in the tree as an integer.   */  def size: Int = 0  /** A new tree with the entry added is returned,   *  assuming that key is <em>not</em> in the tree.   *   *  @param key   ...   *  @param entry ...   *  @return      ...   */  protected def add(key: A, entry: B): This = {    val newSize = size + 1    New(newSize, tree.insert(key, entry, newSize * newSize).node)  }  /** A new tree with the entry added is returned,   *  if key is <em>not</em> in the tree, otherwise   *  the key is updated with the new entry.   */  protected def updateOrAdd(key: A, entry: B): This =    if (tree.isDefinedAt(key))      New(size,tree.update(key,entry))    else      add(key,entry)  /** Removes the key from the tree.   *   *  @param key ...   *  @return    ...   */  protected def deleteAny(key: A): This =    if (tree.isDefinedAt(key))      delete(key)    else      getThis  /** Removes the key from the tree, assumimg that key is present.   *   *  @param key ...   *  @return    ...   */  private def delete(key: A): This =    New(size - 1, tree.delete(key))  /** Check if this map maps <code>key</code> to a value and return the   *  value if it exists.   *   *  @param  key the key of the mapping of interest   *  @return     the value of the mapping, if it exists   */  protected def findValue(key: A): Option[B] =    tree.get(key)  /** Gives you an iterator over all elements in the tree.   *  The iterator structure corresponds to   *  the call stack of an in-order traversal.   *   *  Note: The iterator itself has a state, i.e., it is not functional.   */  protected def entries: Iterator[B] =    new Iterator[B] {      var iter = tree.mk_iter(scala.Nil)      def hasNext = !iter.isEmpty      def next = iter match {        case GBNode(_,v,_,t)::iter_tail =>          iter = t.mk_iter(iter_tail)          v        case scala.Nil =>          throw new NoSuchElementException("next on empty iterator")      }    }  /** Create a new balanced tree from the tree. Might be useful to call   *  after many deletions, since deletion does not rebalance the tree.   */  def balance: This =    New(size, tree.balance(size))}protected abstract class InsertTree[A <% Ordered[A],B]() extends AnyRef {  def insertLeft(k: A, v: B, t: GBTree[A,B]): InsertTree[A,B]  def insertRight(k: A, v: B, t: GBTree[A,B]): InsertTree[A,B]  def node: GBTree[A,B]}/** *  <code>ITree</code> is an internal class used by *  <a href="Tree.html" target="contentFrame"><code>Tree</code></a>. */private case class ITree[A <% Ordered[A],B](t: GBTree[A,B])             extends InsertTree[A,B] {  def insertLeft(key: A, value: B, bigger: GBTree[A,B]) =    ITree(GBNode(key, value, t, bigger))  def insertRight(key: A, value: B, smaller: GBTree[A,B]) =    ITree(GBNode(key, value, smaller, t))  def node = t}/** *  <code>INode</code> is an internal class used by *  <a href="Tree.html" target="contentFrame"><code>Tree</code></a>. */private case class INode[A <% Ordered[A],B](t1: GBTree[A,B],                                            height: Int,                                            size: Int)             extends InsertTree[A,B] {  def insertLeft(key: A, value: B, bigger: GBTree[A,B]) =    balance_p(GBNode(key, value, t1, bigger), bigger);  def insertRight(key: A, value: B, smaller: GBTree[A,B]) =    balance_p(GBNode(key, value, smaller, t1),smaller);  protected def balance_p(t:GBTree[A,B],subtree:GBTree[A,B]):InsertTree[A,B] = {    val (subHeight, subSize) = subtree.count    val totalHeight = 2 * Math.max(height, subHeight)    val totalSize = size + subSize + 1    val BalanceHeight = totalSize * totalSize    if (totalHeight > BalanceHeight) ITree(t.balance(totalSize))    else INode(t, totalHeight, totalSize)  }  def node = t1}/** *  <code>GBTree</code> is an internal class used by *  <a href="Tree.html" target="contentFrame"><code>Tree</code></a>. * *  @author  Erik Stenman *  @version 1.0, 2005-01-20 */@serializableprotected abstract class GBTree[A <% Ordered[A],B] extends AnyRef {  type aNode = GBTree[A,B]  type anInsertTree = InsertTree[A,B]  /** Calculates 2^h, and size, where h is the height of the tree  *   and size is the number of nodes in the tree.  */  def count: (Int,Int)  def isDefinedAt(Key: A): Boolean  def get(key: A): Option[B]  def apply(key: A): B  def update(key: A, value: B): aNode  def insert(key: A, value: B, size: Int): anInsertTree  def toList(acc: List[(A,B)]): List[(A,B)]  def mk_iter(iter_tail: List[aNode]): List[aNode]  def delete(key: A): aNode  def merge(t: aNode): aNode  def takeSmallest: (A,B,aNode)  def balance(s: Int): GBTree[A,B]}private case class GBLeaf[A <% Ordered[A],B]() extends GBTree[A,B] {  def count = (1, 0)  def isDefinedAt(key: A) = false  def get(_key: A) = None  def apply(key: A) = throw new NoSuchElementException("key " + key + " not found")  def update(key: A, value: B) = throw new NoSuchElementException("key " + key + " not found")  def insert(key: A, value: B, s: Int): anInsertTree = {    if (s == 0)      INode(GBNode(key, value, this, this), 1, 1)    else      ITree(GBNode(key, value, this, this))  }  def toList(acc: List[(A,B)]): List[(A,B)] = acc  def mk_iter(iter_tail: List[GBTree[A,B]]) = iter_tail  def merge(larger: GBTree[A,B]) = larger  def takeSmallest: (A,B, GBTree[A,B]) =    throw new NoSuchElementException("takeSmallest on empty tree")  def delete(_key: A) = throw new NoSuchElementException("Delete on empty tree.")  def balance(s: Int) = this  override def hashCode() = 0}private case class GBNode[A <% Ordered[A],B](key: A,                                             value: B,                                             smaller: GBTree[A,B],                                             bigger: GBTree[A,B])             extends GBTree[A,B] {  def count: (Int,Int) = {    val (sHeight, sSize) = smaller.count    val (bHeight, bSize) = bigger.count    val mySize = sSize + bSize + 1    if (mySize == 1)      (1, mySize)    else      (2 * Math.max(sHeight, bHeight), mySize)  }  def isDefinedAt(sKey: A): Boolean =    if (sKey < key) smaller.isDefinedAt(sKey)    else if (sKey > key) bigger.isDefinedAt(sKey)    else true  def get(sKey: A): Option[B] =    if (sKey < key) smaller.get(sKey)    else if (sKey > key) bigger.get(sKey)    else Some(value)  def apply(sKey: A): B =    if (sKey < key) smaller.apply(sKey)    else if (sKey > key) bigger.apply(sKey)    else value  def update(newKey: A, newValue: B): aNode =    if (newKey < key)      GBNode(key, value, smaller.update(newKey,newValue), bigger)    else if (newKey > key)      GBNode(key, value, smaller, bigger.update(newKey,newValue))    else      GBNode(newKey, newValue, smaller, bigger)  def insert(newKey: A, newValue: B, s: Int): anInsertTree = {    if (newKey < key)      smaller.insert(newKey, newValue, s / 2).insertLeft(key, value, bigger)    else if (newKey > key)      bigger.insert(newKey, newValue, s / 2).insertRight(key, value, smaller)    else      throw new NoSuchElementException("Key exists: " + newKey)  }  def toList(acc: List[(A,B)]): List[(A,B)] =    smaller.toList((key, value) :: bigger.toList(acc))  def mk_iter(iter_tail:List[aNode]):List[aNode] =    smaller.mk_iter(this :: iter_tail)  def delete(sKey:A):aNode = {    if (sKey < key)      GBNode(key, value, smaller.delete(sKey), bigger)    else if (sKey > key)      GBNode(key, value, smaller, bigger.delete(sKey))    else      smaller.merge(bigger)  }  def merge(larger: aNode): GBTree[A,B] = larger match {    case GBLeaf() =>      this    case _ =>      val (key1, value1, larger1) = larger.takeSmallest      GBNode(key1, value1, this, larger1)  }  def takeSmallest: (A, B, aNode) = smaller match {    case GBLeaf() =>      (key, value, bigger)    case _ =>      val (key1, value1, smaller1) = smaller.takeSmallest      (key1, value1, GBNode(key, value, smaller1, bigger))  }  /**   *  @param s ...   *  @return  ...   */  def balance(s: Int): GBTree[A,B] =    balance_list(toList(scala.Nil), s)  protected def balance_list(list: List[(A,B)], s: Int): GBTree[A,B] = {    val empty = GBLeaf[A,B]();    def bal(list: List[(A,B)], s: Int): (aNode, List[(A,B)]) = {      if (s > 1) {        val sm = s - 1        val s2 = sm / 2        val s1 = sm - s2        val (t1, (k, v) :: l1) = bal(list, s1)        val (t2, l2) = bal(l1, s2)        val t = GBNode(k, v, t1, t2)        (t, l2)      } else if (s == 1) {        val (k,v) :: rest = list        (GBNode(k, v, empty, empty), rest)      } else        (empty, list)    }    bal(list, s)._1  }  override def hashCode() =    value.hashCode() + smaller.hashCode() + bigger.hashCode()}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?