/* * From C:\Dropbox\InClass15q3\cs2852_prep\class8_2_BinarySearchTree_051_prep * Yoder */ package class10_1_TreeRotations_start; import edu.msoe.se1010.winPlotter.WinPlotter; import java.util.Collection; import java.util.Iterator; import java.util.Set; import java.util.Spliterator; /** * This class is a super-cool combination * of a SortedArrayList and a LinkedList. * * Like the SortedArrayList, the elements are always sorted. * Like the LinkedList, once we find where something should be, * we can insert it in O(1) time just by editing a few links. * * @param the type of the contained obects */ public class BinarySearchTree> extends Object implements Set { private Node root; private class Node { private Node left; private Node right; private E value; private Node(Node left, Node right, E value) { this.left = left; this.right = right; this.value = value; } } public boolean isEmpty() { return root == null; } public int size() { return size(root); } private int size(Node current) { if(current == null) { return 0; } else { return 1 + size(current.left) + size(current.right); } } public boolean add(E e) { // E value = root.value; // if(value.compareTo(e) < 0) /*...*/; if(root == null) { root = new Node(null, null, e); } else { add(root, e); } return true; } /** * * @param subRoot root of sub-tree (MUST NOT BE NULL) * @param e objce t to add */ private void add(Node subRoot, E e) { if(e.compareTo(subRoot.value) < 0) { if(subRoot.left == null) { subRoot.left = new Node(null, null, e); } else { add(subRoot.left, e); } } else if(e.compareTo(subRoot.value) > 0) { if(subRoot.right == null) { subRoot.right = new Node(null, null, e); } else { add(subRoot.right, e); } } else { System.err.println("Warning: Replacing existing node"); System.err.println("(Duplicate add)"); subRoot.value = e; } } public E find(E e) { return find(root,e).value; } public boolean contains(Object o) { E e; try { e = (E) o; } catch (ClassCastException ex) { return false; // cannot be equal if wrong type given. } return find(root, e) != null; } /** * Rotate the tree around the given node. * If e is null, rotates around the root. * @param e */ public void rotateLeft(E e) { Node rootsParent; Node subRoot; if(e == null) { rootsParent = null; subRoot = root; } else { rootsParent = findParent(null, root, e); if (rootsParent == null) { subRoot = find(root, e); } else if (rootsParent.left != null && rootsParent.left.value.equals(e)) { subRoot = rootsParent.left; } else if (rootsParent.right != null && rootsParent.right.value.equals(e)) { subRoot = rootsParent.right; } else { throw new UnsupportedOperationException("Node could not be found: " + e); // TODO: Node could not be found? } } if(root == null || root.right == null) { throw new IllegalArgumentException("Must select a node in the tree that has a right " + "child."); } rotateLeft(subRoot,rootsParent); } private void rotateLeft(Node subRoot, Node rootsParent) { // 0. Save middle Node middle = subRoot.right.left; // 1. Root becomes right child's left child subRoot.right.left = subRoot; // 2. Former right child becomes root. if(rootsParent == null) { this.root = subRoot.right; } else if(rootsParent.left == subRoot) { rootsParent.left = subRoot.right; } else { // rootsParent.right == subRoot rootsParent.right = subRoot.right; } // 3. Former right child's left child // becomes former root's right child subRoot.right = middle; } private Node findParent(Node parent, Node subRoot, E e) { if(subRoot == null) { return null; } else if(e.compareTo(subRoot.value) == 0) { return parent; } if(e.compareTo(subRoot.value) < 0) { return findParent(subRoot, subRoot.left, e); } else { return findParent(subRoot, subRoot.right, e); } } /** * Note subtle change: * @param subRoot root of subtree to search * @param e element to search for * @return NOW RETURNS NODE, not VALUE */ private Node find(Node subRoot, E e) { if(subRoot == null) { return null; } else if(e.compareTo(subRoot.value) == 0) { return subRoot; } if(e.compareTo(subRoot.value) < 0) { return find(subRoot.left,e); } else { return find(subRoot.right,e); } } @Override public void clear() { root = null; } /** * Removes the specified element from this set if it is present * (optional operation). More formally, removes an element e * such that * (o==null ? e==null : o.equals(e)), if * this set contains such an element. Returns true if this set * contained the element (or equivalently, if this set changed as a * result of the call). (This set will not contain the element once the * call returns.) * * @param o object to be removed from this set, if present * @return true if this set contained the specified element * @throws ClassCastException if the type of the specified element * is incompatible with this set * (optional) * @throws NullPointerException if the specified element is null and this * set does not permit null elements * (optional) * @throws UnsupportedOperationException if the remove operation * is not supported by this set */ @Override public boolean remove(Object o) { E e; try { e = (E) o; } catch (ClassCastException ex) { return false; // cannot be equal if wrong type given. } return false; } // private boolean remove(Node curr, E e) { // if() // int direction = .compareTo() // if() // } //-------- BELOW THIS LINE ARE PRINTING/DISPLAYING methods ----- // useful for debugging //-------------------------------------------------------------- public void print() { printTree(root, 0); } private void printTree(Node current, int depth) { if(current != null) { printTree(current.left,depth+1); for(int i=0;i iterator() { return null; } @Override public Object[] toArray() { return new Object[0]; } @Override public T[] toArray(T[] a) { return null; } @Override public boolean containsAll(Collection c) { return false; } @Override public boolean addAll(Collection c) { return false; } @Override public boolean retainAll(Collection c) { return false; } @Override public boolean removeAll(Collection c) { return false; } @Override public Spliterator spliterator() { return null; } }