⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nodebinarytree.java

📁 Java数据结构开发包
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
  Copyright (c) 1999, 2000 Brown University, Providence, RI
  
                            All Rights Reserved
  
  Permission to use, copy, modify, and distribute this software and its
  documentation for any purpose other than its incorporation into a
  commercial product is hereby granted without fee, provided that the
  above copyright notice appear in all copies and that both that
  copyright notice and this permission notice appear in supporting
  documentation, and that the name of Brown University not be used in
  advertising or publicity pertaining to distribution of the software
  without specific, written prior permission.
  
  BROWN UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
  SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  FITNESS FOR ANY PARTICULAR PURPOSE.  IN NO EVENT SHALL BROWN
  UNIVERSITY BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
  DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  PERFORMANCE OF THIS SOFTWARE.
*/

package jdsl.core.ref;

import jdsl.core.api.*;



/**
 * A node-based Binary Tree. The Positions of the tree are
 * the nodes.<p>
 * 
 * contains() is O(1) time; so replaceSubtree, cut, and link are O(S), where S is the
 * number of positions in that subtree.
 * Positions() and elements() are O(N) -- where N is the number of positions
 * in the entire tree.
 * All other methods are O(1) time.
 * <p>
 * Elements can be stored at both internal and external (leaf) nodes.<p>
 *
 * The data structure stores a supernode which in turn stores the root.
 * (this supernode is invisible to the end user)
 *
 * You are only allowed to link in and replaceSubtree with other instances
 * of NodeBinaryTree (or subclasses thereof).
 *
 * @author Ryan Baker (rsb)
 * @author Mark Handy (mdh)
 * @author Benoit Hudson (bh)
 * @version JDSL 2.1.1 
 * @see AbstractPositionalContainer
 * @see BinaryTree
 */

public class NodeBinaryTree extends AbstractPositionalContainer 
implements BinaryTree {
    
  /**
    * The super node which stores the root.
    * (This should _never_ be null)
    */
    private NBTSuperNode _supernode;
    
  /**
    * The size of the tree
    * protected so that RestructurableNodeBinaryTree can access it
    */
  protected int _size;

   /** 
     * Create a tree.  The tree has a single external node
     * at its root, with element <code>null</code>.
     */
    public NodeBinaryTree() {
      _size = 1;
      _supernode = new NBTSuperNode (this, null);
      NBTNode root = new NBTNode (_supernode, (Object)null);
      _supernode.setRoot (root);
      root.setContainer(this);
    }
    
    /** 
     * Create a tree from a set of nodes.  The tree will
     * have as its root the given node.
     *
     * This constructor is protected in order to prevent it
     * from being used except as a result of operations on
     * one tree that create another tree
     *
     * It is assumed that the method calling this will take
     * responsibility for changing the container_ of the
     * various internal NBTNodes, as well as setting _size -- 
     * this way, we can allow
     * O(1) time access where appropriate
     * @param root Root of a tree of existing nodes.
     * @throws InvalidAccessorException when the given root has a parent.
     */
    protected NodeBinaryTree (NBTNode root)throws InvalidAccessorException {
      if (root.parent()!=null)	
	throw new InvalidAccessorException("Given root has a parent.");
        _supernode = new NBTSuperNode(this,root);
	root.setParent(_supernode);
	_size = 0;
    }
    


    /**
     *--------------------------------------------------------
     * From interface BinaryTree
     *--------------------------------------------------------
     */

  /**
    * Takes O(S) time, where S is the number of positions in the new
    * subtree to graft on
    * You are only allowed to link in and replaceSubtree with other instances
    * of NodeBinaryTree (or subclasses thereof)
    */
  public void graftOnLeft( Position subtree, Object eltOfParent, BinaryTree newSibling ){
    NBTNode NBTsubtree = checkPosition(subtree);

    NBTNode graftOnto = NBTsubtree.parent();
    NBTNode newSubtreeRoot = new NBTNode(graftOnto,eltOfParent);
    newSubtreeRoot.setContainer(this);

    if (graftOnto==_supernode)
      _supernode.setRoot(newSubtreeRoot);
    else
      graftOnto.setChild(NBTsubtree,newSubtreeRoot);

    _size+=2;
    newSubtreeRoot.expand();
    newSubtreeRoot.setRight(NBTsubtree);
    NBTsubtree.setParent(newSubtreeRoot);
    link(newSubtreeRoot.left(),newSibling);
  }

  /**
    * Takes O(S) time, where S is the number of positions in the new
    * subtree to graft on
    * You are only allowed to link in and replaceSubtree with other instances
    * of NodeBinaryTree (or subclasses thereof)
    */
  public void graftOnRight( Position subtree, Object eltOfParent, BinaryTree newSibling ){
    NBTNode NBTsubtree = checkPosition(subtree);

    NBTNode graftOnto = NBTsubtree.parent();
    NBTNode newSubtreeRoot = new NBTNode(graftOnto,eltOfParent);
    newSubtreeRoot.setContainer(this);

    if (graftOnto==_supernode)
      _supernode.setRoot(newSubtreeRoot);
    else
      graftOnto.setChild(NBTsubtree,newSubtreeRoot);

    _size+=2;
    newSubtreeRoot.expand();
    newSubtreeRoot.setLeft(NBTsubtree);
    NBTsubtree.setParent(newSubtreeRoot);
    link(newSubtreeRoot.right(),newSibling);
  }

  /**
    * O(1) time
    */
    public void expandExternal (Position mustBeExternal) throws
    InvalidAccessorException {
	NBTNode externalToExpand = checkPosition(mustBeExternal);
	if (externalToExpand.isInternal()) throw new InvalidAccessorException
					       ("You can't expand an internal node");
	externalToExpand.expand(); // now it's internal with two external children
	_size+=2;
    }

  /**
    * O(1) time
    */
    public void removeAboveExternal (Position mustBeExternal) throws
    InvalidAccessorException, BoundaryViolationException {
	NBTNode externalToRemove = checkPosition(mustBeExternal);
	if (isInternal(externalToRemove)) throw new InvalidAccessorException
		("You can't remove above an internal node");
	if (isRoot(externalToRemove)) throw new BoundaryViolationException
		("You can't remove above the root!");
	externalToRemove.removeSelfAndAbove();
	_size-=2;
    }
  
  /**
    * Takes O(S) time, where S is the number of positions in the subtree to cut
    */
    public BinaryTree cut (Position rootOfSubtree)throws InvalidAccessorException {
        // cutting means replacing the subtree with a leaf (i.e., with a newly
        // constructed tree)
        return replaceSubtree (rootOfSubtree,(BinaryTree)newContainer());
    }


  /**
    * Takes O(S) time, where S is the number of positions in this subtree
    * You are only allowed to link in and replaceSubtree with other instances
    * of NodeBinaryTree (or subclasses thereof)
    */
    public Object link (Position mustBeExternal, BinaryTree newSubtree)throws InvalidAccessorException, InvalidContainerException {
	NBTNode x = checkPosition (mustBeExternal);
        if (x.isInternal()) throw new InvalidAccessorException
					     ("You can't link at an internal node");
        replaceSubtree (mustBeExternal, newSubtree);
	return x.element();
    }


  /** 
    * Takes O(S1+S2) time, where S1 and S2 are the number of positions in each subtree
    * You are only allowed to link in and replaceSubtree with other instances
    * of NodeBinaryTree (or subclasses thereof)
    */
    public BinaryTree replaceSubtree (
            Position subtreeRoot,
            BinaryTree newSubtree)throws InvalidAccessorException, InvalidContainerException {
	if (newSubtree==this)
	  throw new InvalidContainerException("You can't link or replaceSubtree a tree into itself!");
	if ( ! (newSubtree instanceof NodeBinaryTree) || (newSubtree==null)) throw
					new InvalidContainerException
					("incompatible type of tree or null tree");

	

        NodeBinaryTree toSwapIn = (NodeBinaryTree) newSubtree;

	updateContainer((NBTNode)toSwapIn.root());

        // get the roots of the subtrees to be swapped
        NBTNode oldSubtreeRoot = checkPosition (subtreeRoot);
        NBTNode newSubtreeRoot = (NBTNode) toSwapIn.root();

	oldSubtreeRoot.replaceSelf (newSubtreeRoot);

        // make a new tree out of the nodes swapped out; the constructor
        // makes a new tree wrapper pointing to oldSubtreeRoot
        // and forces oldSubtreeRoot to point up to its new container
        NodeBinaryTree toReturn = new NodeBinaryTree
	    (oldSubtreeRoot);
	
	toReturn.updateContainer(toReturn.root());

        toSwapIn.resetToEmpty();

        return toReturn;
    }

  /**
    * Recursively changes the container of all nodes in the subtree
    * anchored at root to this container, adding to _size for each
    * node whose container we change
    * Takes O(S) time -- where S is the number of elements in the subtree
    * @param root The node to begin with
    */
  protected void updateContainer(Accessor root)throws InvalidAccessorException{
    NBTNode rootn = null;
    try{
      rootn = (NBTNode)root;
    }
    catch(ClassCastException cce){
      assert false : "Incompatible type of position";
    }
    _size++;
    if (rootn.container()!=null)
      rootn.container()._size--;
    rootn.setContainer(this);
    if (isInternal(rootn)){
      updateContainer(leftChild(rootn));
      updateContainer(rightChild(rootn));
    }
  }

    /**
     *--------------------------------------------------------
     * From interface InspectableBinaryTree
     *--------------------------------------------------------
     */

  /**
    * O(1) time
    */
    public Position leftChild (Position p) throws
    InvalidAccessorException, BoundaryViolationException {
	NBTNode check = checkPosition(p);
	if ( isExternal(check) ) throw new BoundaryViolationException
					("An external node has no children");
	return check.left(); 
    }
    
  /**
    * O(1) time
    */    
    public Position rightChild (Position p) throws
    InvalidAccessorException, BoundaryViolationException {
	NBTNode check = checkPosition(p);
	if ( isExternal(check) ) throw new BoundaryViolationException
					("An external node has no children");
	return check.right(); 
    }
    
  /**
   * O(1) time
   */    
  public Position sibling (Position p) throws
  InvalidAccessorException, BoundaryViolationException {
    PositionIterator pi = siblings(p);
    if (!pi.hasNext())
      throw new BoundaryViolationException("The root has no siblings");
    else
      return pi.nextPosition();
  }
    
    

    /**
     *--------------------------------------------------------  
     * From interface InspectableTree
     *--------------------------------------------------------
     */

  /**
    * O(1) time
    */ 
    public boolean isRoot (Position p) throws InvalidAccessorException {
        checkPosition (p);
        return ( p==root() );
    }

  /**
    * O(1) time
    */ 
    public boolean isInternal (Position p) throws InvalidAccessorException {
        NBTNode check = checkPosition(p);
        return check.isInternal();
    }

  /**
    * O(1) time
    */ 
    public boolean isExternal (Position p) throws InvalidAccessorException {
        return ! isInternal(p);
    }

  /**
    * O(1) time
    */ 
    public Position root() {
        return _supernode._root;
    }

  /**
    * O(1) time
    */ 
    public Position parent (Position p) throws
    InvalidAccessorException, BoundaryViolationException {
	NBTNode check = checkPosition(p);
	if (check==root()) throw new BoundaryViolationException
			       ("parent(root)");
	return check.parent();
    }
    
  /**
    * O(1) time
    */ 
    public PositionIterator children (Position p) throws
    InvalidAccessorException {
        NBTNode padre = checkPosition(p);
        if(isInternal(padre)) {
            Position [] kids = new Position[2];
            kids[0] = padre.left();
            kids[1] = padre.right();
            return new ArrayPositionIterator(kids);
        }
        else {
	  return new ArrayPositionIterator(null);//ext node has no children
        }
    }

  /**
    * O(1) time
    */ 
    public PositionIterator siblings (Position p) throws
    InvalidAccessorException {
      if (isRoot(p))
	throw new BoundaryViolationException("The root has no siblings");

      NBTNode n = checkPosition(p);
      Position [] sib = new Position[1];
      sib[0] = n.parent().otherChild(n);
      return new ArrayPositionIterator(sib);
    }

  /** 
    * O(1) time
    * Can be determined by the inherent nature of the type of node
    * rather than by counting
    */
  public int numChildren(Position node) throws InvalidAccessorException{
    checkPosition(node);
    if (isExternal(node))
      return 0;
    else
      return 2;
  }

  /**
    * O(1) time
    */ 
  public Position siblingAfter (Position node) throws
  BoundaryViolationException, InvalidAccessorException{
    
    NBTNode childnbt = checkPosition(node);

    if (childnbt.isLeftChild())
      return sibling(node);
    else
      if (isRoot(childnbt))
	throw new BoundaryViolationException("This is the root");
      else
	throw new BoundaryViolationException("This is the right child");
  }

  /**
    * O(1) time
    */ 
  public Position siblingBefore (Position node) throws
  BoundaryViolationException, InvalidAccessorException{
    
    NBTNode childnbt = checkPosition(node);

    if (!childnbt.isLeftChild())
      if (isRoot(childnbt))
	throw new BoundaryViolationException("This is the root");
      else
	return sibling(node);
    else
      throw new BoundaryViolationException("This is the left child");
  }
  
  /**
    * O(1) time
    */ 
  public Position firstChild (Position node) throws
  BoundaryViolationException, InvalidAccessorException{
    
    return childAtRank(node,0);
  }

  /**
    * O(1) time
    */ 
  public Position lastChild (Position node) throws
  BoundaryViolationException, InvalidAccessorException{
    
     return childAtRank(node,1);
  }
  
  /**
    * O(1) time
    */ 
  public int rankOfChild (Position child) throws
  BoundaryViolationException, InvalidAccessorException{
  
    NBTNode childnbt = checkPosition(child);

    if (childnbt.isLeftChild())
      return 0;
    else
      if (isRoot(childnbt))
	throw new BoundaryViolationException("This is the root");
      else
	return 1;
  }

  /**
    * O(1) time
    */ 
  public Position childAtRank (Position node, int rank) throws
  BoundaryViolationException, InvalidAccessorException{
  
    NBTNode parent = checkPosition(node);
    
    if (isExternal(parent))
      throw new BoundaryViolationException("This is an external node");

    if (rank == 0)
      return parent.left();
    if (rank == 1)
      return parent.right();

    throw new BoundaryViolationException("Rank "+rank+" is out of bounds -- Binary Trees only have children at ranks 0 and 1.");
      
  }

    /**
     *--------------------------------------------------------  
     * From interface [Inspectable]PositionalContainer
     *--------------------------------------------------------
     */


    /** 
      * Takes O(N) time from the need to iterate through the tree during 
      * snapshot, where N is the number of positions in the tree
     * @return PositionIterator of the container in preorder
     */
    public PositionIterator positions() {

⌨️ 快捷键说明

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