实现TreeSet的get方法的指导。 (家庭作业)

时间:2014-02-25 18:18:55

标签: java data-structures binary-search-tree treeset

好的,教授希望我为我的TreeSet类实现get方法。他给了我一个算法作为实现get方法的指南:

  

的get(k)的

     

从树根开始,让M为其左侧的节点数   子树。

     

(1)如果M等于k-1,则根是您正在寻找的节点。

     

(2)如果M小于k,那么您要查找的节点必须在   正确的子树。当我们移动到正确的子树时,我们必须这样做   从k中减去M + 1。现在正确的子树成为新的根,并且   你重复这个过程。

     

(3)如果M大于k,则必须检查左侧的节点   子树。

我尝试了两种方式,递归和迭代地实现该方法(我不知道如何拼写它)。以下是完整的类代码:

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.TreeSet;
import sun.misc.Queue;

/**
 * Binary Search Tree that inherits from the TreeSet class
 * The class is based on Weiss's non-generic implementation of BinarySearchTree
 * 
 * @author Daniel
 * @param <T> 
 */
public class BinarySearchTree<T extends Comparable<T>> extends TreeSet<T> implements Iterable<T> 
{
    /**
     * Construct the tree.
     */
    public BinarySearchTree( )
    {
        root = null;
    }

    @Override
    public boolean add(T e)
    {
        insert(e);
        return true;
    }



    /**
     * Insert into the tree; duplicates are ignored.
     * @param x the item to insert.
     */
    public void insert( Comparable x )
    {        
        {

            root = insert( x, root );   

        }

    }

    /**
     * Remove from the tree. Nothing is done if x is not found.
     * @param x the item to remove.
     */
    public void remove( Comparable<T> x )
    {

        root = remove( x, root );


    }

    /**
     * Find the smallest item in the tree.
     * @return smallest item or null if empty.
     */
    public Comparable findMin( )
    {
        return elementAt( findMin( root ) );
    }

    /**
     * Find the largest item in the tree.
     * @return the largest item of null if empty.
     */
    public Comparable findMax( )
    {
        return elementAt( findMax( root ) );
    }

    /**
     * Find an item in the tree.
     * @param x the item to search for.
     * @return the matching item or null if not found.
     */
    public Comparable find( Comparable x )
    {
        return elementAt( find( x, root ) );
    }

    /**
     * Make the tree logically empty.
     */
    public void makeEmpty( )
    {
        root = null;
    }

    /**
     * Test if the tree is logically empty.
     * @return true if empty, false otherwise.
     */
    public boolean isEmpty( )
    {
        return root == null;
    }

    /**
     * Print the tree contents in sorted order.
     */
    public void printTree( )
    {
        if( isEmpty( ) )
            System.out.println( "Empty tree" );
        else
            printTree( root );
    }

    /**
     * Internal method to get element field.
     * @param t the node.
     * @return the element field or null if t is null.
     */
    private Comparable elementAt( BinaryNode t )
    {
        return t == null ? null : t.element;
    }

    /**
     * Internal method to insert into a subtree.
     * @param x the item to insert.
     * @param t the node that roots the tree.
     * @return the new root.
     */
    private BinaryNode insert( Comparable<T> x, BinaryNode<T> t )
    {
/* 1*/      if( t == null )
            {
/* 2*/          t = new BinaryNode( x, null, null );

                t.parent = null;
                if (t.left != null)
                    t.left.parent = t;
                if (t.right != null)
                    t.right.parent = t;
            }
/* 3*/      else if( x.compareTo((T)t.element ) < 0 )
            {
/* 4*/          t.left = insert( x, t.left );
                t.left_count++;
                t.left.parent = t;

            }
/* 5*/      else if( x.compareTo((T) t.element ) > 0 )
            {
/* 6*/          t.right = insert( x, t.right );
                t.right.parent = t;

            }
/* 7*/      else
/* 8*/          ;  // Duplicate; do nothing
/* 9*/      return t;
    }

    /**
     * Internal method to remove from a subtree.
     * @param x the item to remove.
     * @param t the node that roots the tree.
     * @return the new root.
     */
    private BinaryNode remove( Comparable<T> x, BinaryNode<T> t )
    {
        if( t == null )
            return t;   // Item not found; do nothing
        if( x.compareTo( (T)t.element ) < 0 )
        {
            t.left = remove( x, t.left );

        }
        else if( x.compareTo( (T)t.element ) > 0 )
        {
            t.right = remove( x, t.right );


        }
        else if( t.left != null && t.right != null ) // Two children
        {
            t.element = findMin( t.right ).element;
            t.right = remove( t.element, t.right );


        }
        else
            t = ( t.left != null ) ? t.left : t.right;
        if (t != null)
        {
            if (t.left != null)
                t.left.parent = t;
            if (t.right != null)
                t.right.parent = t;
        }
        return t;
    }

    /**
     * Internal method to find the smallest item in a subtree.
     * @param t the node that roots the tree.
     * @return node containing the smallest item.
     */
    private BinaryNode<T> findMin( BinaryNode<T> t )
    {
        if( t == null )
            return null;
        else if( t.left == null )
            return t;
        return findMin( t.left );
    }

    /**
     * Internal method to find the largest item in a subtree.
     * @param t the node that roots the tree.
     * @return node containing the largest item.
     */
    private BinaryNode<T> findMax( BinaryNode<T> t )
    {
        if( t != null )
            while( t.right != null )
                t = t.right;

        return t;
    }

    /**
     * Internal method to find an item in a subtree.
     * @param x is item to search for.
     * @param t the node that roots the tree.
     * @return node containing the matched item.
     */
    private BinaryNode find( Comparable<T> x, BinaryNode<T> t )
    {
        if( t == null )
            return null;
        if( x.compareTo( (T)t.element ) < 0 )
            return find( x, t.left );
        else if( x.compareTo( (T)t.element ) > 0 )
            return find( x, t.right );
        else
            return t;    // Match
    }

    /**
     * Internal method to print a subtree in sorted order.
     * @param t the node that roots the tree.
     */
    private void printTree( BinaryNode<T> t )
    {
        if( t != null )
        {
            printTree( t.left );
            System.out.println( t.element );
            printTree( t.right );
        }
    }


  @Deprecated
 //Updates nodes current parent
 // Unfortunaetly to expensive as it is O(N) algorithm. 
 // Therefore it sadly didn't make the final cut and is a deprecated method can be removed in the near future.
 private void update(BinaryNode<T> t) 
 {
     if (t != null)
     {
         if (t.left != null)
            t.left.parent = t;
         if (t.right != null)
            t.right.parent = t;
         update(t.left);
         update(t.right);
     }
 }


 /** 
 * Returns an iterator pointing just before the 
 * item in the tree with the lowest value. 
 * 
 **/

 public Iterator<T> iterator() 
 {
     return new MyIterator();
 }


 /** 
 * Returns the element at a given index position. 
 * Throws an IndexOutOfBoundsException if the item is not found. 
 * Runs in average O(log N) time. 
 */ 
 public T get( int index ) 
 {
      return get(root, index);
 }

 private T get(BinaryNode<T> root, int index)
 {
     if (root == null) return null;
     if (root.left_count == index-1) return (T)root.element;
     if (root.left_count < index) return get(root.right, index - (root.left_count + 1));
     else
     {
         return get(root.left, index);
     }
 }


 /** 
 * Returns all elements falling within a range of indexes. 
 * The range is inclusive 
 */ 

 public Collection<T> getRange( int first, int last ) 
 {
     ArrayList<T> list = new ArrayList<>();
     for(int i = first; i <= last; i++)
     {
         list.add(get(i));
     }
     return list;
 }

 /** 
 * Prints the tree in level-order, which means the root is printed, 
 * then all nodes at level 2, then nodes at level 3, and so on. 
 */ 
 public void printLevelOrder( ) throws InterruptedException  
 {
     Queue Q = new Queue();
     Q.enqueue(root);
     while(!Q.isEmpty())
     {
        BinaryNode<T> node =  (BinaryNode<T>)Q.dequeue();
        System.out.print(node.element + ",");
        if (node.left != null)
            Q.enqueue(node.left);
        if (node.right != null)
            Q.enqueue(node.right);
     }
     System.out.println();
 }






 private class MyIterator implements Iterator<T>
 {

        private BinaryNode<T> nextNode = null;
        private boolean firstCall;
        public MyIterator()
        {
            nextNode = BinarySearchTree.this.findMin(root);
            firstCall = true;
        }
        @Override
        public boolean hasNext()
        {
            return !nextNode.equals(BinarySearchTree.this.findMax(root));
        }

        @Override
        public T next()
        {
            if (firstCall)
            {
                firstCall = false;
                return (T)nextNode.element;
            }
            if (!hasNext())
                   throw new IndexOutOfBoundsException("Cannot manke another next() call!!!!?!");
            BinaryNode<T> node = successor(nextNode); 
            nextNode = node;
            return (T)node.element;
        }

        @Override
        public void remove()
        {
            BinarySearchTree.this.remove(nextNode.element);
        }

        /** 
        * Returns the next value in the sequence, starting at the 
        * node pointed to by the input parameter. This method 
        * is used by the iterator. 
        */ 
        private BinaryNode<T> successor( BinaryNode<T> p )
        {
              BinaryNode<T> n = p.right;
              if (n != null)
              {
                  return BinarySearchTree.this.findMin(n);
              }
              else
              {
                 n = p.parent;
                 while(n != null && p == n.right)
                 {
                     p = n;
                     n = n.parent;
                 }
                 return n;
              }
        }


 }



      /** The tree root. */
    private BinaryNode<T> root;



    public static void main(String[] arguments) throws InterruptedException
    {

        BinarySearchTree<String> t = new BinarySearchTree<>();
        String[] array = { "Harry","Maria","Bob","Dan","Sue","Ann","Jose" }; 

        for(int i = 0; i < array.length; i++)
                t.insert(array[i]);
        print( t );

        System.out.print("Level order: ");
        t.printLevelOrder();
        System.out.println("\n");

        System.out.printf( "The value at index %d is %s\n", 0, t.get(0) );
        System.out.printf( "The value at index %d is %s\n", 2, t.get(2) );
        System.out.printf( "The value at index %d is %s\n", 6, t.get(6) );

        System.out.print("\nRemoving ");
        for( int i = 1; i < array.length; i+= 2 ) {
                System.out.print(array[i] + ", ");
                t.remove( array[i] );
        }
        System.out.println();   

        System.out.println("\nTree contents after removing elements:");
        print( t );

        // verify that the get method still works
        System.out.printf( "The value at index %d is %s\n", 0, t.get(0) );
        System.out.printf( "The value at index %d is %s\n", 2, t.get(2) );
        System.out.printf( "The value at index %d is %s\n", 3, t.get(3) );


    }

    public static void print( BinarySearchTree<? extends Comparable<?>> t ) 
    { 

        for(Object x : t) 
        System.out.print(x + ", "); 
        System.out.println("\n"); 
    } 

 private static void test1() throws InterruptedException 
 { 
        BinarySearchTree<Integer> t = new BinarySearchTree<>( ); 
        int[] array = { 20, 10, 11, 30, 2, 29, 33, 28, 17, 4 }; 
         for(int i = 0; i < array.length; i++) 
             t.add(array[i]);

        print( t ); // demonstrate the iterator 

        System.out.println("Level order"); 
        t.printLevelOrder(); 

        System.out.printf( "The value at index %d is %d\n", 0, t.get(0) ); 
        System.out.printf( "The value at index %d is %d\n", 1, t.get(1) ); 
        System.out.printf( "The value at index %d is %d\n", 2, t.get(2) ); 
        System.out.printf( "The value at index %d is %d\n", 3, t.get(3) ); 
        System.out.printf( "The value at index %d is %d\n", 8, t.get(8) ); 
        System.out.printf( "The value at index %d is %d\n", 9, t.get(9) ); 

        System.out.print("\nRemoving "); 
        for( int i = 1; i < array.length; i+= 2 ) { 
        System.out.print(array[i] + ", "); 
        t.remove( array[i] ); 
        } 
        System.out.println(); 

        System.out.println("\nTree contents after removing elements:"); 
        print( t ); 

        // verify that the get method still works 
        System.out.printf( "The value at index %d is %d\n", 0, t.get(0) ); 
        System.out.printf( "The value at index %d is %d\n", 1, t.get(1) ); 
        System.out.printf( "The value at index %d is %d\n", 2, t.get(2) ); 
        System.out.printf( "The value at index %d is %d\n", 3, t.get(3) ); 
        } 




}

以下是get方法的代码:

 /** 
 * Returns the element at a given index position. 
 * Throws an IndexOutOfBoundsException if the item is not found. 
 * Runs in average O(log N) time. 
 */ 
 public T get( int index ) 
 {
      return get(root, index);
 }

 private T get(BinaryNode<T> root, int index)
 {
     if (root == null) return null;
     if (root.left_count == index-1) return (T)root.element;
     if (root.left_count < index) return get(root.right, index - (root.left_count + 1));
     else
     {
         return get(root.left, index);
     }
 }

这是错误的输出:

  

Ann,Bob,Dan,Harry,Jose,Maria,Sue,

     

等级顺序:Harry,Bob,Maria,Ann,Dan,Jose,Sue,

     

索引0处的值为null   索引2处的值是Bob   索引6处的值是Maria

     

删除Maria,Dan,Ann,

     

删除元素后的树内容:Bob,Harry,Jose,Sue,

     

索引0处的值为null索引2处的值为Bob值为   index 3为null

正如你所看到的,index有一堆空值和无效元素。其他一切都正确输出。所以get是100%失败,因为我已经写过最初使用一个天真的方法。但教授希望它是O(log(N))。

由于这是一项家庭作业,对于我的数据结构课程,请不要提供完整的工作代码。我想要的只是一些指导,我明白这是错误的(从输出中判断)但我不明白为什么。我还是不完全理解使我更难调试代码的算法。我假设node.left_count是正确的(但它可能是错误的),所以我相信错误在get方法中。因为我可能误解了算法。

更新

如果我改变了这个if(root.left_count == index-1)return(T)root.element;对此 if(root.left_count == index)return(T)root.element;

我得到了这个输出:

Ann, Bob, Dan, Harry, Jose, Maria, Sue, 

Level order: Harry,Bob,Maria,Ann,Dan,Jose,Sue,


The value at index 0 is Ann
The value at index 2 is Dan
The value at index 6 is Sue

Removing Maria, Dan, Ann, 

Tree contents after removing elements:
Bob, Harry, Jose, Sue, 

The value at index 0 is null
The value at index 2 is null
The value at index 3 is Harry

1 个答案:

答案 0 :(得分:0)

if (root.left_count == index-1) return (T)root.element;

应该是

if (root.left_count == index) return (T)root.element;

正如您将立即看到的那样。 0个左项,索引0,3个左项,索引3。 这假设约定从0开始索引。

提示:绝不相信规范。