Java Generic Binary Search Albero problema di tipo

voti
1

Sto lavorando a questo compito che è genere di confondere me ...

Sto fornito con la seguente classe di 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);
    }
}

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

Ora ho un altro studente di classe .... Voglio creare un albero binario di ricerca di oggetti Student ..

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

Tuttavia quando faccio che ottengo il seguente errore:

non corrispondente Bound: il tipo di studente non è un sostituto valido per il parametro limitata> del tipo BinarySearchTree

Tutte le idee che cosa sta succedendo qui ... non riesco a capirlo.

È pubblicato 02/05/2009 alle 06:31
fonte dall'utente
In altre lingue...                            


3 risposte

voti
0

Lo studente della classe implementare paragonabile?

Risposto il 02/05/2009 a 06:41
fonte dall'utente

voti
0

ma io non sono molto sicuro come implementare il metodo compareTo.

In sostanza si tratta di qualcosa di simile alla seguente. Come funziona l'ordinamento si deve decidere.

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
    }
}
Risposto il 02/05/2009 a 06:56
fonte dall'utente

voti
6

 public class BinarySearchTree<T extends Comparable<T>> 

Un argomento formale generici, nel tuo caso T, elenca ciò che è necessario per una classe di essere una valida T. In caso si, hai detto, "per essere una valida T, una classe deve implementare comparabile" (La parola chiave è "si estende ", ma in pratica che significa 'estende o implementa'.)

Nella tua esemplificazione, T è studente. Se sostituiamo Student per T:

public class BinarySearchTree<Student extends Comparable<Student>>

è che una vera e propria dichiarazione? Ha Student davvero implementare paragonabile?

Se lo fa, Studente si inserisce il requisito di essere un T, e così si può usare Student come parametro attuale per il parametro formale T.

In caso contrario, si ottiene il reclamo del compilatore che avete visto.

In realtà, per coprire le situazioni più complesse in cui l'attuazione di una sottoclasse di paragonabile è fatto da una classe super, la forma più generale sarebbe:

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

Quindi è necessario fare Student implementare Comparable <Student>.

Si noti che io non ho detto che il compilatore sta cercando una Student.compareTo. Non ha nemmeno arrivare così lontano. Sta cercando di vedere se T (nel tuo caso, Studente) è dichiarata come attuare Paragonabile <T> (nel tuo caso, paragonabile <Student>).

Ora l'aggiunta implements Comparable< Student >di studente sarà anche rendere il compilatore in modo che ci sia un public int compareTometodo su Studente. Ma senza la "implementa comparabile", anche se il compilatore sa che c'è un metodo Student.compareTo, che non sa che quello compareToè il Comparable.compareTo.

(In altre parole, stiamo cercando implementazione dichiarato, non solo che ci capita di essere un metodo con il nome giusto e la firma.)

Risposto il 02/05/2009 a 06:57
fonte dall'utente

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more