137public class BinarySearchTree<Key
extends Comparable<Key>,Value>
138 implements Iterable<BinarySearchTree<Key,Value>.Cursor>,
159 public void setValue(Value value) { value_=value; }
164 (value_!=
null?
"=>"+value_.toString():
"")) :
"head";
176 BinarySearchTree<Key,Value> tree_ =
null;
179 Node(BinarySearchTree<Key,Value> tree,Key key,Value value) {
180 super(
new Entry(key,value));
192 return tree_.getDecorator();
216 while (node!=
head_ && compareKeys(node.getKey(),
getKey())<0) {
217 Node right=(Node) node.getRight();
218 if (right!=
null && right!=
this &&
219 compareKeys(right.getKey(),
getKey())>=0) {
221 while (node.getLeft()!=
null) { node=(Node) node.getLeft(); }
224 node=(Node) node.getParent();
226 return node!=
head_ ? node :
null;
230 protected Node createNode(Key key,Value value) {
231 return new Node(
this,key,value);
237 public BinarySearchTree() {
238 head_ = createNode(
null,
null);
242 public boolean isEmpty() {
250 protected int compareKeys(Key a,Key b) {
251 if (a==
null)
return -1;
252 if (b==
null)
return +1;
253 else return a.compareTo(b);
308 protected LowerBound findLowerBound(Key key) {
313 (cmp=compareKeys(key,node.getKey()))!=0) {
318 node=(Node) node.getRight();
320 return new LowerBound(node,parent,cmp);
326 public Value find(Key key) {
327 return findLowerBound(key).getValue();
347 public Cursor findEntry(Key key) {
348 Node node=findLowerBound(key).node;
349 return node!=
null ?
new Cursor(node) : null;
355 public Cursor getMinimum() {
361 return parent!=
head_ ?
new Cursor(parent) : null;
367 public Cursor getMaximum() {
373 return parent!=
head_ ?
new Cursor(parent) : null;
377 public static abstract class Visitor {
378 abstract public void visit(String state,
379 String key, String value, String tikz);
383 public void visitPreorder(Visitor visitor) {
387 void visitPreorder(Visitor visitor, Node node) {
388 visitor.visit(
"node-pre",
null,
null,
null);
391 Value val = node.getValue();
392 visitor.visit(
"node", node.getKey().toString(),
393 val !=
null ? val.toString() :
null,
394 node.tikzNodeStyle());
396 visitor.visit(
"left-down",
null,
null,
null);
397 visitPreorder(visitor, (Node) node.getLeft());
398 visitor.visit(
"left-up",
null,
null,
null);
400 visitor.visit(
"right-down",
null,
null,
null);
401 visitPreorder(visitor, (Node) node.getRight());
402 visitor.visit(
"right-up",
null,
null,
null);
405 visitor.visit(
"node-post",
null,
null,
null);
420 return iter_!=
null && iter_.hasNext();
430 @Override
public void remove() {
431 throw new UnsupportedOperationException();
436 @Override
public Iterator iterator() {
459 public Range range(Key begin,Key end) {
460 if (isEmpty() || (end!=
null && compareKeys(begin,end)>=0))
461 return new Range(
null,
null);
463 LowerBound lower=findLowerBound(begin);
464 Node start=lower.node!=
null ? lower.node : lower.parent;
467 lower=findLowerBound(end);
468 stop=lower.node!=
null ? lower.node : lower.parent;
470 return new Range(start,stop);
474 public class Range implements Iterable<Cursor> {
501 return node_!=range_.end_;
513 @Override
public void remove() {
514 throw new UnsupportedOperationException();
534 public Value insert(Key key,Value value) {
535 LowerBound r=findLowerBound(key);
538 Value old=r.node.getValue();
539 r.node.setValue(value);
543 assert(r.parent!=
null);
545 Node node=createNode(key,value);
549 old=(Node) r.parent.setLeft(node);
551 old=(Node) r.parent.setRight(node);
573 protected void onInsert(Node node) {}
582 public Value
remove(Key key) {
583 LowerBound r=findLowerBound(key);
589 Value value=node.getValue();
599 protected void removeNode(Node node) {
603 assert(parent!=
null);
604 assert(parent.getLeft()==node || parent.getRight()==node);
608 else if (node.getLeft()==
null)
609 child=(Node) node.getRight();
610 else if (node.getRight()==
null)
611 child=(Node) node.getLeft();
613 child=(Node) node.getRight();
614 while (child.getLeft()!=
null)
615 child=(Node) child.getLeft();
617 child.setLeft(node.getLeft());
620 Node p=(Node) child.getParent();
622 p.setLeft(child.getRight());
624 child.setRight(node.getRight());
628 if (parent.getLeft()==node)
629 parent.setLeft(child);
631 parent.setRight(child);
640 protected void onRemove() {}
652 protected Node restructure(Node grandchild) {
653 assert(grandchild.getParent()!=
head_);
654 assert(grandchild.getParent().getParent()!=
head_);
656 Node child=(Node) grandchild.getParent();
657 Node parent=(Node) child.getParent();
661 Node x=grandchild, y=child, z=parent;
662 boolean xLeft=(x==y.getLeft());
663 boolean yLeft=(y==z.getLeft());
668 if (xLeft && yLeft) {
670 t0=(Node) a.getLeft();
671 t1=(Node) a.getRight();
672 t2=(Node) b.getRight();
673 t3=(Node) c.getRight();
675 else if (!xLeft && yLeft) {
677 t0=(Node) a.getLeft();
678 t1=(Node) b.getLeft();
679 t2=(Node) b.getRight();
680 t3=(Node) c.getRight();
682 else if (xLeft && !yLeft) {
684 t0=(Node) a.getLeft();
685 t1=(Node) b.getLeft();
686 t2=(Node) b.getRight();
687 t3=(Node) c.getRight();
691 t0=(Node) a.getLeft();
692 t1=(Node) b.getLeft();
693 t2=(Node) c.getLeft();
694 t3=(Node) c.getRight();
697 return setupBalancedSubtree(z,a,b,c,t0,t1,t2,t3);
711 protected Node setupBalancedSubtree
712 (Node z,Node a,Node b,Node c,Node t0,Node t1,Node t2,Node t3) {
714 Node root=(Node) z.getParent();
717 if (root.getLeft()==z)
722 a.left_=a.right_=
null;
726 c.left_=c.right_=
null;
730 b.left_=b.right_=
null;
751 protected Node rotateLeft(Node node) {
753 Node b=(Node) node.getRight(); assert(b!=
null);
754 Node c=(Node) b.getRight(); assert(c!=
null);
756 Node t0=(Node) a.getLeft();
757 Node t1=(Node) b.getLeft();
758 Node t2=(Node) c.getLeft();
759 Node t3=(Node) c.getRight();
763 return setupBalancedSubtree(z, a,b,c, t0,t1,t2,t3);
780 protected Node rotateRightLeft(Node node) {
782 Node c=(Node) node.getRight(); assert(c!=
null);
783 Node b=(Node) c.getLeft(); assert(b!=
null);
785 Node t0=(Node) a.getLeft();
786 Node t1=(Node) b.getLeft();
787 Node t2=(Node) b.getRight();
788 Node t3=(Node) c.getRight();
792 return setupBalancedSubtree(z, a,b,c, t0,t1,t2,t3);
809 protected Node rotateRight(Node node) {
811 Node b=(Node) node.getLeft(); assert(b!=
null);
812 Node a=(Node) b.getLeft(); assert(a!=
null);
814 Node t0=(Node) a.getLeft();
815 Node t1=(Node) a.getRight();
816 Node t2=(Node) b.getRight();
817 Node t3=(Node) c.getRight();
821 return setupBalancedSubtree(z, a,b,c, t0,t1,t2,t3);
838 protected Node rotateLeftRight(Node node) {
840 Node a=(Node) node.getLeft(); assert(a!=
null);
841 Node b=(Node) a.getRight(); assert(b!=
null);
843 Node t0=(Node) a.getLeft();
844 Node t1=(Node) b.getLeft();
845 Node t2=(Node) b.getRight();
846 Node t3=(Node) c.getRight();
850 return setupBalancedSubtree(z, a,b,c, t0,t1,t2,t3);
865 public void restructure(
char action,Key key) {
867 throw new RuntimeException(
"invalid key 'null'");
869 Node node=findLowerBound(key).node;
871 throw new RuntimeException(
"no such node '"+key+
"'");
875 if (node.getLeft()==
null || node.getLeft().getLeft()==
null)
876 throw new RuntimeException(
"missing node->left>left");
880 if (node.getRight()==
null || node.getRight().getRight()==
null)
881 throw new RuntimeException(
"missing node->left->right");
885 if (node.getRight()==
null || node.getRight().getLeft()==
null)
886 throw new RuntimeException(
"missing node->right->left");
890 if (node.getLeft()==
null || node.getLeft().getRight()==
null)
891 throw new RuntimeException(
"missing node->left->right");
896 throw new RuntimeException(
"missing node->parent->parent");
904 return object==
head_ ?
"shape=ellipse" : super.getNodeDecoration(
object);
917 Decorator decorator_ =
new Decorator();
923 @Override
public String toDot() {
927 @Override
public String toString() {
930 java.util.Iterator<?> ii=
head_.
getRight().inorder().iterator();
931 while (ii.hasNext()) {
941 public String toText() {
946 public String toTikZ() {
953 public void checkConsistency() {
957 protected void checkConsistency(Node node) {
958 Node parent=(Node) node.getParent();
959 assert(parent!=
null);
960 assert((Node) parent.getLeft()==node || (Node) parent.getRight()==node);
963 throw new RuntimeException(
"parent!=null");
964 if ((Node) parent.getLeft()!=node && (Node) parent.getRight()!=node)
965 throw new RuntimeException(
"invalid parent");
967 if (node.getLeft()!=
null)
968 checkConsistency((Node) node.getLeft());
969 if (node.getRight()!=
null)
970 checkConsistency((Node) node.getRight());
974 public static void main(String[] args) {
975 BinarySearchTree<String,Object> tree=
976 new BinarySearchTree<String,Object> ();
977 System.out.println(tree);
981 String[] keys={
"a",
"b",
"d",
"c",
"g",
"f",
"e"};
984 for (String key : keys)
985 tree.insert(key,
null);
987 System.out.println(tree);
988 System.out.println(tree.toText()); tree.checkConsistency();
990 for (BinarySearchTree<String,Object>.Cursor c : tree)
991 System.out.print(c.getKey());
992 System.out.println();
994 for (BinarySearchTree<String,Object>.Cursor c : tree.range(
"b",
"f"))
995 System.out.print(c.getKey());
996 System.out.println();
998 keys=
new String[]{
"a",
"c",
"e",
"g"};
1000 for (String key : keys)
1003 System.out.println(tree);
1004 System.out.println(tree.toText());
Reference to a key-value pair in a BinarySearchTree.
void setValue(Value value)
set value
enables decoration "by key"
String getNodeDecoration(GraphvizDecorable object)
get node decoration
Key-value pair as entry (= node data) in a search tree.
void setValue(Value value)
set value
Value getValue()
get value
Entry(Key key, Value value)
construct node
Node node
the node found or null for failed search
Node parent
node's parent (always !=null)
int cmp
result of the last call to compareKeys
Node in a BinarySearchTree.
Value getValue()
get value (short for getData().getValue())
void setValue(Value value)
set value (short for getData().setValue(value))
GraphvizDecorator getDecorator()
Key getKey()
get key (short for getData().getKey())
iterable range (subsequence)
String toDot()
Get dot representation.
BinaryTree< T > getLeft()
get left child or null
BinaryTree< T > getRight()
get right child or null)
BinaryTree< T > getParent()
get node's parent or null for root
Decorator for items of Graphvizable objects.
void markNode(GraphvizDecorable object)
void unmarkNode(GraphvizDecorable object)
unmark node object
void highlightNode(GraphvizDecorable object)
Set highlighted node.
Interface for decorating items of Graphvizable objects.
Interface for GraphViz rendering.
utilities (not related to AuD lecture)
AuD lecture: Data structures, algorithms, examples.