2009-05-02 8 views
1
나는 종류의 나를 혼란이 숙제에서 일하고 있어요

...자바 일반 이진 검색 트리 형 문제

나는 다음과 같은 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); 
    } 
} 

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

이제 다른 클래스 학생이 있습니다 .... 학생 개체의 이진 검색 트리를 만들고 싶습니다. ..

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

그러나 나는 다음과 같은 오류를 얻을 수행 할 때

바운드 불일치 : 유형의 학생이 유형의 경계 매개 변수에 대한 올바른 대체>하지 ​​BinarySearchTree

여기에 무슨 일이 일어나고 있는지 어떤 아이디어가. .. 나는 그것을 이해할 수 없다.

+0

"BinarySearchTree >"대신 "Comparable >"을 확장합니다. 당신이 가지고있는 방식은 Comparable을 구현하는 클래스의 서브 클래스가있을 때 필요로하는 것보다 더 제한적이며 문제를 일으킬 것이다. – newacct

답변

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

이 공식적인 제네릭 인수는, 귀하의 경우 T에서, 유효한 T, 클래스로 ", 말한 클래스는 경우 유효한 T.을 할 필요 무슨 나열 Comparable "을 구현해야합니다 (키워드는"확장 "이지만 실제는"확장 또는 구현 "을 의미합니다.)

인스턴스에서 T는 학생입니다. 우리가 T를 T로 대체하면 :

이 사실입니까? 학생은 Comparable을 실제로 구현합니까? 만약 그렇다면

는 학생이 T 인의 요구에 맞는, 그래서 당신은

공식 매개 변수 T.의 실제 매개 변수로 학생을 사용할 수없는 경우, 당신은 당신이 본 컴파일러의 불만을 얻을.

사실, 대등의 서브 클래스의 구현은 슈퍼 클래스에 의해 행해진 다 더 복잡한 상황을 충당하기 위해, 더 일반적인 형태는 다음과 같습니다

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

그래서 당신은 학생이 대등 < 학생을 구현해야>.

이 아니기 때문에 컴파일러가 Student.compareTo을 찾고 있다고 가정합니다. 그것은 심지어 그렇게까지 얻지 못합니다. T (귀하의 경우 Student)가 T => (귀하의 경우, Comparable < Student>)를 구현하는 것으로 선언되었는지 살펴볼 것입니다.

지금 컴파일러는 학생의 public int compareTo 방법이있을 수 있도록 할 것입니다 학생에 implements Comparable<Student>를 추가.그러나 "comparable"을 구현하지 않고 컴파일러가 Student.compareTo 메서드를 알고 있다고하더라도 compareToComparable.compareTo이라는 것을 알지 못합니다. 나는 "BinarySearchTree

(즉, 우리가 올바른 이름과 서명을하는 방법이있을 일이 아닌 것을 선언 이행을위한 찾고 있습니다.)

+0

당신의 도움에 감사드립니다 ... 그것은 일했습니다 ... 나는 T를 Student로 변경하고 Comparable을 구현하고 compareTo 메소드를 추가했습니다. – user69514

+0

Whoa - BinarySearchTree에서 T 학생을 변경하지 마십시오. tpdi는 새로운 BinarySearchTree 을 호출 할 때 어떤 일이 일어날지를 생각한 것입니다. 컴파일러는 T 용 Student를 연결합니다. 귀하의 선언은 여전히 ​​public class BinarySearchTree >. –

+0

예, Scott이 옳습니다. T는 공식적인 인수이고, Student는 실제 인수입니다. – tpdi

0

학생 클래스가 Comparable을 구현합니까?

+0

아니요 .... 그게 내가해야한다고 생각했는데 compareTo 메소드를 구현하는 방법을 잘 모르겠습니다. – user69514

+0

comparable을 구현하지 않으면 >에 대한 요구 사항을 충족하지 못합니다. 비교하지 않으면 이진 검색은 의미가 없습니다. –

+0

가 좋아 내가 학생 클래스에서의 Comparable 구현 ... 내 compareTo와는 다음과 같습니다 \t 공공 INT은 compareTo (객체 O) { \t \t 학생 CR = (학생) ㅇ; \t \t int cn1 = Integer.parseInt (this.id); \t \t int cn2 = Integer.parseInt (cr.id); \t \t if (cn1> cn2) \t \t \t return 1; \t \t else if (cn1 user69514

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 
    } 
}