2009-05-02 40 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 
    } 
}