2009-05-02 57 views
1

我工作的這個功課是有點困惑我......Java的通用二叉搜索樹類型的問題

我提供了以下BinarySearchTree類

import java.util.NoSuchElementException; 

/** 
* 
* @param <T> The type of data stored in the nodes of the tree, must implement Comparable<T> with the compareTo method. 
*/ 
public class BinarySearchTree<T extends Comparable<T>> { 


    BinaryTree<T> tree; 

    int size; 
    public BinarySearchTree() { 
     tree = new BinaryTree<T>(); 
     size = 0; 
    } 

    public boolean isEmpty() { 
     return tree.isEmpty(); 
    } 

    protected BinaryTree<T> recursiveSearch(BinaryTree<T> root, T key) { 
     if (root == null) { 
      return null; 
     } 
     int c = key.compareTo(root.data); 
     if (c == 0) { 
      return root; 
     } 
     if (c < 0) { 
      return recursiveSearch(root.left, key); 
     } else { 
      return recursiveSearch(root.right, key); 
     } 
    } 

    public T search(T key) { 
     if (tree.isEmpty()) { 
      return null; 
     } 
     return recursiveSearch(tree, key).data; 
    } 

    public void insert(T item) { 

     if (tree.isEmpty()) { // insert here 
      tree.makeRoot(item); 
      size++; 
      return; 
     } 

     // do an iterative descent 
     BinaryTree<T> root = tree; 
     boolean done=false; 
     BinaryTree<T> newNode = null; 
     while (!done) { 
      int c = item.compareTo(root.data); 
      if (c == 0) { // duplicate found, cannot be inserted 
       throw new OrderViolationException(); 
      } 
      if (c < 0) { // insert in left subtree 
       if (root.left == null) { // insert here as left child 
        newNode = new BinaryTree<T>(); 
        root.left = newNode; 
        done=true; 
       } else { // go further down left subtree 
        root = root.left; 
       } 
      } else { // insert in right subtree 
       if (root.right == null) { // insert here as right child 
        newNode = new BinaryTree<T>(); 
        root.right = newNode; 
        done=true; 
       } else { // go further down right subtree 
        root = root.right; 
       } 
      } 
     } 
     // set fields of new node 
     newNode.data = item; 
     newNode.parent = root; 
     size++; 
    } 

    /** 
    * @param deleteNode Node whose parent will receive new node as right or left child, 
    *     depending on whether this node is its parent's right or left child. 
    * @param attach The node to be attached to parent of deleteNode. 
    */ 
    protected void deleteHere(BinaryTree<T> deleteNode, BinaryTree<T> attach) { 

     // deleteNode has only one subtree, attach 
     BinaryTree<T> parent = deleteNode.parent; 
     deleteNode.clear(); // clear the fields 
     if (parent == null) { 
      return; 
     } 
     if (deleteNode == parent.left) { 
      // left child of parent, attach as left subtree 
      parent.detachLeft(); 
      parent.attachLeft(attach); 
      return; 
     } 
     // attach as right subtree 
     parent.detachRight(); 
     parent.attachRight(attach); 
    } 


    protected BinaryTree<T> findPredecessor(BinaryTree<T> node) { 
     if (node.left == null) { 
      return null; 
     } 
     BinaryTree<T> pred = node.left; // turn left once 
     while (pred.right != null) { // keep turning right 
      pred = pred.right; 
     } 
     return pred; 
    } 


    public T delete(T key) { 
     if (tree.isEmpty()) { // can't delete from an empty tree 
      throw new NoSuchElementException(); 
     } 

     // find node containing key 
     BinaryTree<T> deleteNode = recursiveSearch(tree, key); 
     if (deleteNode == null) { // data not found, can't delete 
      throw new NoSuchElementException(); 
     } 

     BinaryTree<T> hold; 

     // case c: deleteNode has exactly two subtrees 
     if (deleteNode.right != null && deleteNode.left != null) { 
      hold = findPredecessor(deleteNode); 
      deleteNode.data = hold.data; 
      deleteNode = hold; // fall through to case a or b 
     } 

     // case a: deleteNode is a leaf 
     if (deleteNode.left == null && deleteNode.right == null) { 
      deleteHere(deleteNode, null); 
      size--; 
      return deleteNode.data; 
     }  

     // case b: deleteNode has exactly one subtree 
     if (deleteNode.right != null) { 
      hold = deleteNode.right; 
      deleteNode.right = null; 
     } else { 
      hold = deleteNode.left; 
      deleteNode.left = null; 
     } 

     deleteHere(deleteNode,hold); 
     if (tree == deleteNode) { // root deleted 
      tree = hold; 
     } 
     size--; 
     return deleteNode.data; 
    } 


    public T minKey() { 
     if (tree.data == null) { // tree empty, can't find min value 
      throw new NoSuchElementException(); 
     } 

     BinaryTree<T> root = tree; 
     T min=root.data; 
     root = root.left; // turn left once 
     while (root != null) { // keep going left to leftmost node 
      min = root.data; 
      root = root.left; 
     } 
     return min; 
    } 


    public T maxKey() { 
     if (tree.getData() == null) { // tree empty, can't find max value 
      throw new NoSuchElementException(); 
     } 

     BinaryTree<T> root=tree; 
     T max=root.data; 
     root = root.right; // turn right once 
     while (root != null) { // keep going to rightmost node 
      max = root.data; 
      root = root.right; 
     } 
     return max; 
    } 


    public int size() { 
     return size; 
    } 


    protected void recursivePreOrder(BinaryTree<T> root, Visitor<T> visitor) { 
     if (root != null) { 
      visitor.visit(root); 
      recursivePreOrder(root.left, visitor); 
      recursivePreOrder(root.right, visitor); 
     } 
    } 


    public void preOrder(Visitor<T> visitor) { 
     if (tree.isEmpty()) { 
      return; 
     } 
     recursivePreOrder(tree, visitor); 
    } 


    protected void recursiveInOrder(BinaryTree<T> root, Visitor<T> visitor) { 
     if (root != null) { 
      recursiveInOrder(root.left, visitor); 
      visitor.visit(root); 
      recursiveInOrder(root.right, visitor); 
     } 
    } 


    public void inOrder(Visitor<T> visitor) { 
     if (tree.isEmpty()) { 
      return; 
     } 
     recursiveInOrder(tree, visitor); 
    } 


    protected void recursivePostOrder(BinaryTree<T> root, Visitor<T> visitor) { 
     if (root != null) { 
      recursivePostOrder(root.left, visitor); 
      recursivePostOrder(root.right, visitor); 
      visitor.visit(root); 
     } 
    } 

    public void postOrder(Visitor<T> visitor) { 
     if (tree.isEmpty()) { 
      return; 
     } 
     recursivePostOrder(tree, visitor); 
    } 
} 

====== ================================================== ========================

現在我有另一班學生.... 我想創建一個Student對象的二叉查找樹..

BinarySearchTree<Student> tree = new BinarySearchTree<Student>(); 

然而,當我這樣做,我得到以下錯誤:

約束不匹配:類型學生是不是有界參數類型的有效替代品> BinarySearchTree

任何想法,這裏發生了什麼。 ..我無法弄清楚。

+0

通過我建議必將是「BinarySearchTree >「而不是」BinarySearchTree >「。你擁有它的方式比它需要的更具限制性,當你有實現Comparable的類的子類時會遇到問題。 – newacct 2009-05-02 05:59:29

回答

6
public class BinarySearchTree<T extends Comparable<T>> 

正式仿製藥的說法,你的情況T,列出了一類是一個有效的T.在你的情況下我們需要的,你說,「是一個有效的T,A類必須實現Comparable「(關鍵字是」extends「,但實際上這意味着」擴展或實現「。)

在您的實例中,T是Student。如果我們用T代替學生:

這是一個真實的陳述嗎?學生是否真的實施了Comparable?

如果是這樣,學生適合的是T的要求,所以你可以使用學生的實際參數的形式參數T.

如果沒有,你得到你所看到的編譯器的投訴。

其實,以涵蓋子類的實現可比由超類來完成更復雜的情況,更一般的形式是:

public class BinarySearchTree<T extends Comparable<? super T > > 

所以,你需要使學生實現可比<學生>。

請注意,我沒有說編譯器尋找Student.compareTo。它甚至沒有那麼遠。這是看看是否T(在你的情況下,學生)被宣佈爲實施可比較的< T>(在你的情況,比較<學生>)。

現在加入implements Comparable<Student>到學生將使編譯器保證有學生上一public int compareTo方法。但是如果沒有「implements Comparable」,即使編譯器知道有方法Student.compareTo,它也不知道compareToComparable.compareTo

(換句話說,我們正在尋找宣佈實施,不僅有恰好是用正確的名稱和簽名的方法。)

0

班級學生是否實施了Comparable?

+0

不,它不....這就是我想我應該做的,但我不太清楚如何實現compareTo方法。 – user69514 2009-05-02 05:44:56

+0

如果您沒有實現可比較的功能,則不符合>的要求。沒有比較,二分查找就沒有意義。 – 2009-05-02 05:51:09

0

but I'm not quite sure how to implement the compareTo method.

基本上它是類似於以下內容。如何訂購你需要決定的作品。

class Student implements Comparable<Student> { 

    //... 

    int compareTo(Student other) { 
     // return some negative number if this object is less than other 
     // return 0 if this object is equal to other 
     // return some positive number if this object is greater than other 
    } 
}