annotate agent/src/share/classes/sun/jvm/hotspot/utilities/RBTree.java @ 1913:3b2dea75431e

6984311: JSR 292 needs optional bootstrap method parameters Summary: Allow CONSTANT_InvokeDynamic nodes to have any number of extra operands. Reviewed-by: twisti
author jrose
date Sat, 30 Oct 2010 13:08:23 -0700
parents c18cbe5936b8
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 0
diff changeset
2 * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 0
diff changeset
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 0
diff changeset
20 * or visit www.oracle.com if you need additional information or have any
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 0
diff changeset
21 * questions.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25 package sun.jvm.hotspot.utilities;
a61af66fc99e Initial load
duke
parents:
diff changeset
26
a61af66fc99e Initial load
duke
parents:
diff changeset
27 /** <P> This class implements a Red-Black tree as described in Cormen,
a61af66fc99e Initial load
duke
parents:
diff changeset
28 Leiserson, Rivest, <I>Introduction to Algorithms</I>, MIT Press:
a61af66fc99e Initial load
duke
parents:
diff changeset
29 Cambridge, MA, 1990. </P>
a61af66fc99e Initial load
duke
parents:
diff changeset
30
a61af66fc99e Initial load
duke
parents:
diff changeset
31 <P> A property of this implementation is that it is designed to
a61af66fc99e Initial load
duke
parents:
diff changeset
32 allow straightforward augmentation of the data structure. A valid
a61af66fc99e Initial load
duke
parents:
diff changeset
33 augmentation is one in which a node contains auxiliary information
a61af66fc99e Initial load
duke
parents:
diff changeset
34 that can be computed by examining only this node and its left and
a61af66fc99e Initial load
duke
parents:
diff changeset
35 right children (see CLR, section 15.2). </P>
a61af66fc99e Initial load
duke
parents:
diff changeset
36
a61af66fc99e Initial load
duke
parents:
diff changeset
37 <P> An RBTree is a structure of RBNodes, each of which contains a
a61af66fc99e Initial load
duke
parents:
diff changeset
38 user data element. When the user inserts a piece of data into the
a61af66fc99e Initial load
duke
parents:
diff changeset
39 tree, a new RBNode is constructed around it. </P>
a61af66fc99e Initial load
duke
parents:
diff changeset
40
a61af66fc99e Initial load
duke
parents:
diff changeset
41 <P> An RBTree takes a Comparator as argument to its constructor
a61af66fc99e Initial load
duke
parents:
diff changeset
42 which is used internally to order the nodes in the tree. The
a61af66fc99e Initial load
duke
parents:
diff changeset
43 comparator's arguments are obtained by calling the routine
a61af66fc99e Initial load
duke
parents:
diff changeset
44 "getNodeData" on two nodes; the default implementaion returns the
a61af66fc99e Initial load
duke
parents:
diff changeset
45 node data. This Comparator is also used to perform the generic
a61af66fc99e Initial load
duke
parents:
diff changeset
46 "find" operation, which returns the RBNode containing user data
a61af66fc99e Initial load
duke
parents:
diff changeset
47 precisely equalling the query data. Different types of user data
a61af66fc99e Initial load
duke
parents:
diff changeset
48 will typically require different types of traversals as well as
a61af66fc99e Initial load
duke
parents:
diff changeset
49 additional comparison operations; these are left to the RBTree
a61af66fc99e Initial load
duke
parents:
diff changeset
50 subclass. </P>
a61af66fc99e Initial load
duke
parents:
diff changeset
51
a61af66fc99e Initial load
duke
parents:
diff changeset
52 */
a61af66fc99e Initial load
duke
parents:
diff changeset
53
a61af66fc99e Initial load
duke
parents:
diff changeset
54 import java.io.PrintStream;
a61af66fc99e Initial load
duke
parents:
diff changeset
55 import java.util.Comparator;
a61af66fc99e Initial load
duke
parents:
diff changeset
56 import java.util.Random;
a61af66fc99e Initial load
duke
parents:
diff changeset
57
a61af66fc99e Initial load
duke
parents:
diff changeset
58 public class RBTree {
a61af66fc99e Initial load
duke
parents:
diff changeset
59 private RBNode root;
a61af66fc99e Initial load
duke
parents:
diff changeset
60 private Comparator comparator;
a61af66fc99e Initial load
duke
parents:
diff changeset
61 protected static final boolean DEBUGGING = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
62 protected static final boolean VERBOSE = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
63 protected static final boolean REALLY_VERBOSE = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
64
a61af66fc99e Initial load
duke
parents:
diff changeset
65 public RBTree(Comparator comparator) {
a61af66fc99e Initial load
duke
parents:
diff changeset
66 this.comparator = comparator;
a61af66fc99e Initial load
duke
parents:
diff changeset
67 }
a61af66fc99e Initial load
duke
parents:
diff changeset
68
a61af66fc99e Initial load
duke
parents:
diff changeset
69 public RBNode getRoot() {
a61af66fc99e Initial load
duke
parents:
diff changeset
70 return root;
a61af66fc99e Initial load
duke
parents:
diff changeset
71 }
a61af66fc99e Initial load
duke
parents:
diff changeset
72
a61af66fc99e Initial load
duke
parents:
diff changeset
73 public void insertNode(RBNode x) {
a61af66fc99e Initial load
duke
parents:
diff changeset
74 treeInsert(x);
a61af66fc99e Initial load
duke
parents:
diff changeset
75
a61af66fc99e Initial load
duke
parents:
diff changeset
76 x.setColor(RBColor.RED);
a61af66fc99e Initial load
duke
parents:
diff changeset
77 boolean shouldPropagate = x.update();
a61af66fc99e Initial load
duke
parents:
diff changeset
78
a61af66fc99e Initial load
duke
parents:
diff changeset
79 if (DEBUGGING && REALLY_VERBOSE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
80 System.err.println("RBTree.insertNode");
a61af66fc99e Initial load
duke
parents:
diff changeset
81 }
a61af66fc99e Initial load
duke
parents:
diff changeset
82
a61af66fc99e Initial load
duke
parents:
diff changeset
83 RBNode propagateStart = x;
a61af66fc99e Initial load
duke
parents:
diff changeset
84
a61af66fc99e Initial load
duke
parents:
diff changeset
85 // Loop invariant: x has been updated.
a61af66fc99e Initial load
duke
parents:
diff changeset
86 while ((x != root) && (x.getParent().getColor() == RBColor.RED)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
87 if (x.getParent() == x.getParent().getParent().getLeft()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
88 RBNode y = x.getParent().getParent().getRight();
a61af66fc99e Initial load
duke
parents:
diff changeset
89 if ((y != null) && (y.getColor() == RBColor.RED)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
90 // Case 1
a61af66fc99e Initial load
duke
parents:
diff changeset
91 if (DEBUGGING && REALLY_VERBOSE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
92 System.err.println(" Case 1/1");
a61af66fc99e Initial load
duke
parents:
diff changeset
93 }
a61af66fc99e Initial load
duke
parents:
diff changeset
94 x.getParent().setColor(RBColor.BLACK);
a61af66fc99e Initial load
duke
parents:
diff changeset
95 y.setColor(RBColor.BLACK);
a61af66fc99e Initial load
duke
parents:
diff changeset
96 x.getParent().getParent().setColor(RBColor.RED);
a61af66fc99e Initial load
duke
parents:
diff changeset
97 x.getParent().update();
a61af66fc99e Initial load
duke
parents:
diff changeset
98 x = x.getParent().getParent();
a61af66fc99e Initial load
duke
parents:
diff changeset
99 shouldPropagate = x.update();
a61af66fc99e Initial load
duke
parents:
diff changeset
100 propagateStart = x;
a61af66fc99e Initial load
duke
parents:
diff changeset
101 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
102 if (x == x.getParent().getRight()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
103 // Case 2
a61af66fc99e Initial load
duke
parents:
diff changeset
104 if (DEBUGGING && REALLY_VERBOSE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
105 System.err.println(" Case 1/2");
a61af66fc99e Initial load
duke
parents:
diff changeset
106 }
a61af66fc99e Initial load
duke
parents:
diff changeset
107 x = x.getParent();
a61af66fc99e Initial load
duke
parents:
diff changeset
108 leftRotate(x);
a61af66fc99e Initial load
duke
parents:
diff changeset
109 }
a61af66fc99e Initial load
duke
parents:
diff changeset
110 // Case 3
a61af66fc99e Initial load
duke
parents:
diff changeset
111 if (DEBUGGING && REALLY_VERBOSE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
112 System.err.println(" Case 1/3");
a61af66fc99e Initial load
duke
parents:
diff changeset
113 }
a61af66fc99e Initial load
duke
parents:
diff changeset
114 x.getParent().setColor(RBColor.BLACK);
a61af66fc99e Initial load
duke
parents:
diff changeset
115 x.getParent().getParent().setColor(RBColor.RED);
a61af66fc99e Initial load
duke
parents:
diff changeset
116 shouldPropagate = rightRotate(x.getParent().getParent());
a61af66fc99e Initial load
duke
parents:
diff changeset
117 propagateStart = x.getParent();
a61af66fc99e Initial load
duke
parents:
diff changeset
118 }
a61af66fc99e Initial load
duke
parents:
diff changeset
119 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
120 // Same as then clause with "right" and "left" exchanged
a61af66fc99e Initial load
duke
parents:
diff changeset
121 RBNode y = x.getParent().getParent().getLeft();
a61af66fc99e Initial load
duke
parents:
diff changeset
122 if ((y != null) && (y.getColor() == RBColor.RED)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
123 // Case 1
a61af66fc99e Initial load
duke
parents:
diff changeset
124 if (DEBUGGING && REALLY_VERBOSE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
125 System.err.println(" Case 2/1");
a61af66fc99e Initial load
duke
parents:
diff changeset
126 }
a61af66fc99e Initial load
duke
parents:
diff changeset
127 x.getParent().setColor(RBColor.BLACK);
a61af66fc99e Initial load
duke
parents:
diff changeset
128 y.setColor(RBColor.BLACK);
a61af66fc99e Initial load
duke
parents:
diff changeset
129 x.getParent().getParent().setColor(RBColor.RED);
a61af66fc99e Initial load
duke
parents:
diff changeset
130 x.getParent().update();
a61af66fc99e Initial load
duke
parents:
diff changeset
131 x = x.getParent().getParent();
a61af66fc99e Initial load
duke
parents:
diff changeset
132 shouldPropagate = x.update();
a61af66fc99e Initial load
duke
parents:
diff changeset
133 propagateStart = x;
a61af66fc99e Initial load
duke
parents:
diff changeset
134 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
135 if (x == x.getParent().getLeft()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
136 // Case 2
a61af66fc99e Initial load
duke
parents:
diff changeset
137 if (DEBUGGING && REALLY_VERBOSE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
138 System.err.println(" Case 2/2");
a61af66fc99e Initial load
duke
parents:
diff changeset
139 }
a61af66fc99e Initial load
duke
parents:
diff changeset
140 x = x.getParent();
a61af66fc99e Initial load
duke
parents:
diff changeset
141 rightRotate(x);
a61af66fc99e Initial load
duke
parents:
diff changeset
142 }
a61af66fc99e Initial load
duke
parents:
diff changeset
143 // Case 3
a61af66fc99e Initial load
duke
parents:
diff changeset
144 if (DEBUGGING && REALLY_VERBOSE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
145 System.err.println(" Case 2/3");
a61af66fc99e Initial load
duke
parents:
diff changeset
146 }
a61af66fc99e Initial load
duke
parents:
diff changeset
147 x.getParent().setColor(RBColor.BLACK);
a61af66fc99e Initial load
duke
parents:
diff changeset
148 x.getParent().getParent().setColor(RBColor.RED);
a61af66fc99e Initial load
duke
parents:
diff changeset
149 shouldPropagate = leftRotate(x.getParent().getParent());
a61af66fc99e Initial load
duke
parents:
diff changeset
150 propagateStart = x.getParent();
a61af66fc99e Initial load
duke
parents:
diff changeset
151 }
a61af66fc99e Initial load
duke
parents:
diff changeset
152 }
a61af66fc99e Initial load
duke
parents:
diff changeset
153 }
a61af66fc99e Initial load
duke
parents:
diff changeset
154
a61af66fc99e Initial load
duke
parents:
diff changeset
155 while (shouldPropagate && (propagateStart != root)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
156 if (DEBUGGING && REALLY_VERBOSE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
157 System.err.println(" Propagating");
a61af66fc99e Initial load
duke
parents:
diff changeset
158 }
a61af66fc99e Initial load
duke
parents:
diff changeset
159 propagateStart = propagateStart.getParent();
a61af66fc99e Initial load
duke
parents:
diff changeset
160 shouldPropagate = propagateStart.update();
a61af66fc99e Initial load
duke
parents:
diff changeset
161 }
a61af66fc99e Initial load
duke
parents:
diff changeset
162
a61af66fc99e Initial load
duke
parents:
diff changeset
163 root.setColor(RBColor.BLACK);
a61af66fc99e Initial load
duke
parents:
diff changeset
164
a61af66fc99e Initial load
duke
parents:
diff changeset
165 if (DEBUGGING) {
a61af66fc99e Initial load
duke
parents:
diff changeset
166 verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
167 }
a61af66fc99e Initial load
duke
parents:
diff changeset
168 }
a61af66fc99e Initial load
duke
parents:
diff changeset
169
a61af66fc99e Initial load
duke
parents:
diff changeset
170 /** FIXME: this does not work properly yet for augmented red-black
a61af66fc99e Initial load
duke
parents:
diff changeset
171 trees since it doesn't update nodes. Need to figure out exactly
a61af66fc99e Initial load
duke
parents:
diff changeset
172 from which points we need to propagate updates upwards. */
a61af66fc99e Initial load
duke
parents:
diff changeset
173 public void deleteNode(RBNode z) {
a61af66fc99e Initial load
duke
parents:
diff changeset
174 // This routine splices out a node. Note that we may not actually
a61af66fc99e Initial load
duke
parents:
diff changeset
175 // delete the RBNode z from the tree, but may instead remove
a61af66fc99e Initial load
duke
parents:
diff changeset
176 // another node from the tree, copying its contents into z.
a61af66fc99e Initial load
duke
parents:
diff changeset
177
a61af66fc99e Initial load
duke
parents:
diff changeset
178 // y is the node to be unlinked from the tree
a61af66fc99e Initial load
duke
parents:
diff changeset
179 RBNode y;
a61af66fc99e Initial load
duke
parents:
diff changeset
180 if ((z.getLeft() == null) || (z.getRight() == null)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
181 y = z;
a61af66fc99e Initial load
duke
parents:
diff changeset
182 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
183 y = treeSuccessor(z);
a61af66fc99e Initial load
duke
parents:
diff changeset
184 }
a61af66fc99e Initial load
duke
parents:
diff changeset
185 // y is guaranteed to be non-null at this point
a61af66fc99e Initial load
duke
parents:
diff changeset
186 RBNode x;
a61af66fc99e Initial load
duke
parents:
diff changeset
187 if (y.getLeft() != null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
188 x = y.getLeft();
a61af66fc99e Initial load
duke
parents:
diff changeset
189 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
190 x = y.getRight();
a61af66fc99e Initial load
duke
parents:
diff changeset
191 }
a61af66fc99e Initial load
duke
parents:
diff changeset
192 // x is the potential child of y to replace it in the tree.
a61af66fc99e Initial load
duke
parents:
diff changeset
193 // x may be null at this point
a61af66fc99e Initial load
duke
parents:
diff changeset
194 RBNode xParent;
a61af66fc99e Initial load
duke
parents:
diff changeset
195 if (x != null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
196 x.setParent(y.getParent());
a61af66fc99e Initial load
duke
parents:
diff changeset
197 xParent = x.getParent();
a61af66fc99e Initial load
duke
parents:
diff changeset
198 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
199 xParent = y.getParent();
a61af66fc99e Initial load
duke
parents:
diff changeset
200 }
a61af66fc99e Initial load
duke
parents:
diff changeset
201 if (y.getParent() == null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
202 root = x;
a61af66fc99e Initial load
duke
parents:
diff changeset
203 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
204 if (y == y.getParent().getLeft()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
205 y.getParent().setLeft(x);
a61af66fc99e Initial load
duke
parents:
diff changeset
206 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
207 y.getParent().setRight(x);
a61af66fc99e Initial load
duke
parents:
diff changeset
208 }
a61af66fc99e Initial load
duke
parents:
diff changeset
209 }
a61af66fc99e Initial load
duke
parents:
diff changeset
210 if (y != z) {
a61af66fc99e Initial load
duke
parents:
diff changeset
211 z.copyFrom(y);
a61af66fc99e Initial load
duke
parents:
diff changeset
212 }
a61af66fc99e Initial load
duke
parents:
diff changeset
213 if (y.getColor() == RBColor.BLACK) {
a61af66fc99e Initial load
duke
parents:
diff changeset
214 deleteFixup(x, xParent);
a61af66fc99e Initial load
duke
parents:
diff changeset
215 }
a61af66fc99e Initial load
duke
parents:
diff changeset
216
a61af66fc99e Initial load
duke
parents:
diff changeset
217 if (DEBUGGING) {
a61af66fc99e Initial load
duke
parents:
diff changeset
218 verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
219 }
a61af66fc99e Initial load
duke
parents:
diff changeset
220 }
a61af66fc99e Initial load
duke
parents:
diff changeset
221
a61af66fc99e Initial load
duke
parents:
diff changeset
222 public void print() {
a61af66fc99e Initial load
duke
parents:
diff changeset
223 printOn(System.out);
a61af66fc99e Initial load
duke
parents:
diff changeset
224 }
a61af66fc99e Initial load
duke
parents:
diff changeset
225
a61af66fc99e Initial load
duke
parents:
diff changeset
226 public void printOn(PrintStream tty) {
a61af66fc99e Initial load
duke
parents:
diff changeset
227 printFromNode(root, tty, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
228 }
a61af66fc99e Initial load
duke
parents:
diff changeset
229
a61af66fc99e Initial load
duke
parents:
diff changeset
230 //----------------------------------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
231 // Functionality overridable by subclass
a61af66fc99e Initial load
duke
parents:
diff changeset
232 //
a61af66fc99e Initial load
duke
parents:
diff changeset
233
a61af66fc99e Initial load
duke
parents:
diff changeset
234 protected Object getNodeValue(RBNode node) {
a61af66fc99e Initial load
duke
parents:
diff changeset
235 return node.getData();
a61af66fc99e Initial load
duke
parents:
diff changeset
236 }
a61af66fc99e Initial load
duke
parents:
diff changeset
237
a61af66fc99e Initial load
duke
parents:
diff changeset
238 /** Verify invariants are preserved */
a61af66fc99e Initial load
duke
parents:
diff changeset
239 protected void verify() {
a61af66fc99e Initial load
duke
parents:
diff changeset
240 verifyFromNode(root);
a61af66fc99e Initial load
duke
parents:
diff changeset
241 }
a61af66fc99e Initial load
duke
parents:
diff changeset
242
a61af66fc99e Initial load
duke
parents:
diff changeset
243 //----------------------------------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
244 // Internals only below this point
a61af66fc99e Initial load
duke
parents:
diff changeset
245 //
a61af66fc99e Initial load
duke
parents:
diff changeset
246
a61af66fc99e Initial load
duke
parents:
diff changeset
247 //
a61af66fc99e Initial load
duke
parents:
diff changeset
248 // Vanilla binary search tree operations
a61af66fc99e Initial load
duke
parents:
diff changeset
249 //
a61af66fc99e Initial load
duke
parents:
diff changeset
250
a61af66fc99e Initial load
duke
parents:
diff changeset
251 private void treeInsert(RBNode z) {
a61af66fc99e Initial load
duke
parents:
diff changeset
252 RBNode y = null;
a61af66fc99e Initial load
duke
parents:
diff changeset
253 RBNode x = root;
a61af66fc99e Initial load
duke
parents:
diff changeset
254
a61af66fc99e Initial load
duke
parents:
diff changeset
255 while (x != null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
256 y = x;
a61af66fc99e Initial load
duke
parents:
diff changeset
257 if (comparator.compare(getNodeValue(z), getNodeValue(x)) < 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
258 x = x.getLeft();
a61af66fc99e Initial load
duke
parents:
diff changeset
259 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
260 x = x.getRight();
a61af66fc99e Initial load
duke
parents:
diff changeset
261 }
a61af66fc99e Initial load
duke
parents:
diff changeset
262 }
a61af66fc99e Initial load
duke
parents:
diff changeset
263 z.setParent(y);
a61af66fc99e Initial load
duke
parents:
diff changeset
264 if (y == null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
265 root = z;
a61af66fc99e Initial load
duke
parents:
diff changeset
266 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
267 if (comparator.compare(getNodeValue(z), getNodeValue(y)) < 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
268 y.setLeft(z);
a61af66fc99e Initial load
duke
parents:
diff changeset
269 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
270 y.setRight(z);
a61af66fc99e Initial load
duke
parents:
diff changeset
271 }
a61af66fc99e Initial load
duke
parents:
diff changeset
272 }
a61af66fc99e Initial load
duke
parents:
diff changeset
273 }
a61af66fc99e Initial load
duke
parents:
diff changeset
274
a61af66fc99e Initial load
duke
parents:
diff changeset
275 private RBNode treeSuccessor(RBNode x) {
a61af66fc99e Initial load
duke
parents:
diff changeset
276 if (x.getRight() != null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
277 return treeMinimum(x.getRight());
a61af66fc99e Initial load
duke
parents:
diff changeset
278 }
a61af66fc99e Initial load
duke
parents:
diff changeset
279 RBNode y = x.getParent();
a61af66fc99e Initial load
duke
parents:
diff changeset
280 while ((y != null) && (x == y.getRight())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
281 x = y;
a61af66fc99e Initial load
duke
parents:
diff changeset
282 y = y.getParent();
a61af66fc99e Initial load
duke
parents:
diff changeset
283 }
a61af66fc99e Initial load
duke
parents:
diff changeset
284 return y;
a61af66fc99e Initial load
duke
parents:
diff changeset
285 }
a61af66fc99e Initial load
duke
parents:
diff changeset
286
a61af66fc99e Initial load
duke
parents:
diff changeset
287 private RBNode treeMinimum(RBNode x) {
a61af66fc99e Initial load
duke
parents:
diff changeset
288 while (x.getLeft() != null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
289 x = x.getLeft();
a61af66fc99e Initial load
duke
parents:
diff changeset
290 }
a61af66fc99e Initial load
duke
parents:
diff changeset
291 return x;
a61af66fc99e Initial load
duke
parents:
diff changeset
292 }
a61af66fc99e Initial load
duke
parents:
diff changeset
293
a61af66fc99e Initial load
duke
parents:
diff changeset
294 //
a61af66fc99e Initial load
duke
parents:
diff changeset
295 // Insertion and deletion helpers
a61af66fc99e Initial load
duke
parents:
diff changeset
296 //
a61af66fc99e Initial load
duke
parents:
diff changeset
297
a61af66fc99e Initial load
duke
parents:
diff changeset
298 /** Returns true if updates must continue propagating up the tree */
a61af66fc99e Initial load
duke
parents:
diff changeset
299 private boolean leftRotate(RBNode x) {
a61af66fc99e Initial load
duke
parents:
diff changeset
300 // Set y.
a61af66fc99e Initial load
duke
parents:
diff changeset
301 RBNode y = x.getRight();
a61af66fc99e Initial load
duke
parents:
diff changeset
302 // Turn y's left subtree into x's right subtree.
a61af66fc99e Initial load
duke
parents:
diff changeset
303 x.setRight(y.getLeft());
a61af66fc99e Initial load
duke
parents:
diff changeset
304 if (y.getLeft() != null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
305 y.getLeft().setParent(x);
a61af66fc99e Initial load
duke
parents:
diff changeset
306 }
a61af66fc99e Initial load
duke
parents:
diff changeset
307 // Link x's parent to y.
a61af66fc99e Initial load
duke
parents:
diff changeset
308 y.setParent(x.getParent());
a61af66fc99e Initial load
duke
parents:
diff changeset
309 if (x.getParent() == null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
310 root = y;
a61af66fc99e Initial load
duke
parents:
diff changeset
311 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
312 if (x == x.getParent().getLeft()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
313 x.getParent().setLeft(y);
a61af66fc99e Initial load
duke
parents:
diff changeset
314 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
315 x.getParent().setRight(y);
a61af66fc99e Initial load
duke
parents:
diff changeset
316 }
a61af66fc99e Initial load
duke
parents:
diff changeset
317 }
a61af66fc99e Initial load
duke
parents:
diff changeset
318 // Put x on y's left.
a61af66fc99e Initial load
duke
parents:
diff changeset
319 y.setLeft(x);
a61af66fc99e Initial load
duke
parents:
diff changeset
320 x.setParent(y);
a61af66fc99e Initial load
duke
parents:
diff changeset
321 // Update nodes in appropriate order (lowest to highest)
a61af66fc99e Initial load
duke
parents:
diff changeset
322 boolean res = x.update();
a61af66fc99e Initial load
duke
parents:
diff changeset
323 res = y.update() || res;
a61af66fc99e Initial load
duke
parents:
diff changeset
324 return res;
a61af66fc99e Initial load
duke
parents:
diff changeset
325 }
a61af66fc99e Initial load
duke
parents:
diff changeset
326
a61af66fc99e Initial load
duke
parents:
diff changeset
327 /** Returns true if updates must continue propagating up the tree */
a61af66fc99e Initial load
duke
parents:
diff changeset
328 private boolean rightRotate(RBNode y) {
a61af66fc99e Initial load
duke
parents:
diff changeset
329 // Set x.
a61af66fc99e Initial load
duke
parents:
diff changeset
330 RBNode x = y.getLeft();
a61af66fc99e Initial load
duke
parents:
diff changeset
331 // Turn x's right subtree into y's left subtree.
a61af66fc99e Initial load
duke
parents:
diff changeset
332 y.setLeft(x.getRight());
a61af66fc99e Initial load
duke
parents:
diff changeset
333 if (x.getRight() != null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
334 x.getRight().setParent(y);
a61af66fc99e Initial load
duke
parents:
diff changeset
335 }
a61af66fc99e Initial load
duke
parents:
diff changeset
336 // Link y's parent into x.
a61af66fc99e Initial load
duke
parents:
diff changeset
337 x.setParent(y.getParent());
a61af66fc99e Initial load
duke
parents:
diff changeset
338 if (y.getParent() == null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
339 root = x;
a61af66fc99e Initial load
duke
parents:
diff changeset
340 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
341 if (y == y.getParent().getLeft()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
342 y.getParent().setLeft(x);
a61af66fc99e Initial load
duke
parents:
diff changeset
343 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
344 y.getParent().setRight(x);
a61af66fc99e Initial load
duke
parents:
diff changeset
345 }
a61af66fc99e Initial load
duke
parents:
diff changeset
346 }
a61af66fc99e Initial load
duke
parents:
diff changeset
347 // Put y on x's right.
a61af66fc99e Initial load
duke
parents:
diff changeset
348 x.setRight(y);
a61af66fc99e Initial load
duke
parents:
diff changeset
349 y.setParent(x);
a61af66fc99e Initial load
duke
parents:
diff changeset
350 // Update nodes in appropriate order (lowest to highest)
a61af66fc99e Initial load
duke
parents:
diff changeset
351 boolean res = y.update();
a61af66fc99e Initial load
duke
parents:
diff changeset
352 res = x.update() || res;
a61af66fc99e Initial load
duke
parents:
diff changeset
353 return res;
a61af66fc99e Initial load
duke
parents:
diff changeset
354 }
a61af66fc99e Initial load
duke
parents:
diff changeset
355
a61af66fc99e Initial load
duke
parents:
diff changeset
356 /** Restores red-black property to tree after splicing out node
a61af66fc99e Initial load
duke
parents:
diff changeset
357 during deletion. Note that x may be null, which is why xParent
a61af66fc99e Initial load
duke
parents:
diff changeset
358 must be specified. */
a61af66fc99e Initial load
duke
parents:
diff changeset
359 private void deleteFixup(RBNode x, RBNode xParent) {
a61af66fc99e Initial load
duke
parents:
diff changeset
360 while ((x != root) && ((x == null) || (x.getColor() == RBColor.BLACK))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
361 if (x == xParent.getLeft()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
362 // NOTE: the text points out that w can not be null. The
a61af66fc99e Initial load
duke
parents:
diff changeset
363 // reason is not obvious from simply examining the code; it
a61af66fc99e Initial load
duke
parents:
diff changeset
364 // comes about because of properties of the red-black tree.
a61af66fc99e Initial load
duke
parents:
diff changeset
365 RBNode w = xParent.getRight();
a61af66fc99e Initial load
duke
parents:
diff changeset
366 if (DEBUGGING) {
a61af66fc99e Initial load
duke
parents:
diff changeset
367 if (w == null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
368 throw new RuntimeException("x's sibling should not be null");
a61af66fc99e Initial load
duke
parents:
diff changeset
369 }
a61af66fc99e Initial load
duke
parents:
diff changeset
370 }
a61af66fc99e Initial load
duke
parents:
diff changeset
371 if (w.getColor() == RBColor.RED) {
a61af66fc99e Initial load
duke
parents:
diff changeset
372 // Case 1
a61af66fc99e Initial load
duke
parents:
diff changeset
373 w.setColor(RBColor.BLACK);
a61af66fc99e Initial load
duke
parents:
diff changeset
374 xParent.setColor(RBColor.RED);
a61af66fc99e Initial load
duke
parents:
diff changeset
375 leftRotate(xParent);
a61af66fc99e Initial load
duke
parents:
diff changeset
376 w = xParent.getRight();
a61af66fc99e Initial load
duke
parents:
diff changeset
377 }
a61af66fc99e Initial load
duke
parents:
diff changeset
378 if (((w.getLeft() == null) || (w.getLeft().getColor() == RBColor.BLACK)) &&
a61af66fc99e Initial load
duke
parents:
diff changeset
379 ((w.getRight() == null) || (w.getRight().getColor() == RBColor.BLACK))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
380 // Case 2
a61af66fc99e Initial load
duke
parents:
diff changeset
381 w.setColor(RBColor.RED);
a61af66fc99e Initial load
duke
parents:
diff changeset
382 x = xParent;
a61af66fc99e Initial load
duke
parents:
diff changeset
383 xParent = x.getParent();
a61af66fc99e Initial load
duke
parents:
diff changeset
384 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
385 if ((w.getRight() == null) || (w.getRight().getColor() == RBColor.BLACK)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
386 // Case 3
a61af66fc99e Initial load
duke
parents:
diff changeset
387 w.getLeft().setColor(RBColor.BLACK);
a61af66fc99e Initial load
duke
parents:
diff changeset
388 w.setColor(RBColor.RED);
a61af66fc99e Initial load
duke
parents:
diff changeset
389 rightRotate(w);
a61af66fc99e Initial load
duke
parents:
diff changeset
390 w = xParent.getRight();
a61af66fc99e Initial load
duke
parents:
diff changeset
391 }
a61af66fc99e Initial load
duke
parents:
diff changeset
392 // Case 4
a61af66fc99e Initial load
duke
parents:
diff changeset
393 w.setColor(xParent.getColor());
a61af66fc99e Initial load
duke
parents:
diff changeset
394 xParent.setColor(RBColor.BLACK);
a61af66fc99e Initial load
duke
parents:
diff changeset
395 if (w.getRight() != null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
396 w.getRight().setColor(RBColor.BLACK);
a61af66fc99e Initial load
duke
parents:
diff changeset
397 }
a61af66fc99e Initial load
duke
parents:
diff changeset
398 leftRotate(xParent);
a61af66fc99e Initial load
duke
parents:
diff changeset
399 x = root;
a61af66fc99e Initial load
duke
parents:
diff changeset
400 xParent = x.getParent();
a61af66fc99e Initial load
duke
parents:
diff changeset
401 }
a61af66fc99e Initial load
duke
parents:
diff changeset
402 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
403 // Same as clause above with "right" and "left"
a61af66fc99e Initial load
duke
parents:
diff changeset
404 // exchanged
a61af66fc99e Initial load
duke
parents:
diff changeset
405
a61af66fc99e Initial load
duke
parents:
diff changeset
406 // NOTE: the text points out that w can not be null. The
a61af66fc99e Initial load
duke
parents:
diff changeset
407 // reason is not obvious from simply examining the code; it
a61af66fc99e Initial load
duke
parents:
diff changeset
408 // comes about because of properties of the red-black tree.
a61af66fc99e Initial load
duke
parents:
diff changeset
409 RBNode w = xParent.getLeft();
a61af66fc99e Initial load
duke
parents:
diff changeset
410 if (DEBUGGING) {
a61af66fc99e Initial load
duke
parents:
diff changeset
411 if (w == null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
412 throw new RuntimeException("x's sibling should not be null");
a61af66fc99e Initial load
duke
parents:
diff changeset
413 }
a61af66fc99e Initial load
duke
parents:
diff changeset
414 }
a61af66fc99e Initial load
duke
parents:
diff changeset
415 if (w.getColor() == RBColor.RED) {
a61af66fc99e Initial load
duke
parents:
diff changeset
416 // Case 1
a61af66fc99e Initial load
duke
parents:
diff changeset
417 w.setColor(RBColor.BLACK);
a61af66fc99e Initial load
duke
parents:
diff changeset
418 xParent.setColor(RBColor.RED);
a61af66fc99e Initial load
duke
parents:
diff changeset
419 rightRotate(xParent);
a61af66fc99e Initial load
duke
parents:
diff changeset
420 w = xParent.getLeft();
a61af66fc99e Initial load
duke
parents:
diff changeset
421 }
a61af66fc99e Initial load
duke
parents:
diff changeset
422 if (((w.getRight() == null) || (w.getRight().getColor() == RBColor.BLACK)) &&
a61af66fc99e Initial load
duke
parents:
diff changeset
423 ((w.getLeft() == null) || (w.getLeft().getColor() == RBColor.BLACK))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
424 // Case 2
a61af66fc99e Initial load
duke
parents:
diff changeset
425 w.setColor(RBColor.RED);
a61af66fc99e Initial load
duke
parents:
diff changeset
426 x = xParent;
a61af66fc99e Initial load
duke
parents:
diff changeset
427 xParent = x.getParent();
a61af66fc99e Initial load
duke
parents:
diff changeset
428 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
429 if ((w.getLeft() == null) || (w.getLeft().getColor() == RBColor.BLACK)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
430 // Case 3
a61af66fc99e Initial load
duke
parents:
diff changeset
431 w.getRight().setColor(RBColor.BLACK);
a61af66fc99e Initial load
duke
parents:
diff changeset
432 w.setColor(RBColor.RED);
a61af66fc99e Initial load
duke
parents:
diff changeset
433 leftRotate(w);
a61af66fc99e Initial load
duke
parents:
diff changeset
434 w = xParent.getLeft();
a61af66fc99e Initial load
duke
parents:
diff changeset
435 }
a61af66fc99e Initial load
duke
parents:
diff changeset
436 // Case 4
a61af66fc99e Initial load
duke
parents:
diff changeset
437 w.setColor(xParent.getColor());
a61af66fc99e Initial load
duke
parents:
diff changeset
438 xParent.setColor(RBColor.BLACK);
a61af66fc99e Initial load
duke
parents:
diff changeset
439 if (w.getLeft() != null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
440 w.getLeft().setColor(RBColor.BLACK);
a61af66fc99e Initial load
duke
parents:
diff changeset
441 }
a61af66fc99e Initial load
duke
parents:
diff changeset
442 rightRotate(xParent);
a61af66fc99e Initial load
duke
parents:
diff changeset
443 x = root;
a61af66fc99e Initial load
duke
parents:
diff changeset
444 xParent = x.getParent();
a61af66fc99e Initial load
duke
parents:
diff changeset
445 }
a61af66fc99e Initial load
duke
parents:
diff changeset
446 }
a61af66fc99e Initial load
duke
parents:
diff changeset
447 }
a61af66fc99e Initial load
duke
parents:
diff changeset
448 if (x != null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
449 x.setColor(RBColor.BLACK);
a61af66fc99e Initial load
duke
parents:
diff changeset
450 }
a61af66fc99e Initial load
duke
parents:
diff changeset
451 }
a61af66fc99e Initial load
duke
parents:
diff changeset
452
a61af66fc99e Initial load
duke
parents:
diff changeset
453 // Returns the number of black children along all paths to all
a61af66fc99e Initial load
duke
parents:
diff changeset
454 // leaves of the given node
a61af66fc99e Initial load
duke
parents:
diff changeset
455 private int verifyFromNode(RBNode node) {
a61af66fc99e Initial load
duke
parents:
diff changeset
456 // Bottoms out at leaf nodes
a61af66fc99e Initial load
duke
parents:
diff changeset
457 if (node == null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
458 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
459 }
a61af66fc99e Initial load
duke
parents:
diff changeset
460
a61af66fc99e Initial load
duke
parents:
diff changeset
461 // Each node is either red or black
a61af66fc99e Initial load
duke
parents:
diff changeset
462 if (!((node.getColor() == RBColor.RED) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
463 (node.getColor() == RBColor.BLACK))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
464 if (DEBUGGING) {
a61af66fc99e Initial load
duke
parents:
diff changeset
465 System.err.println("Verify failed:");
a61af66fc99e Initial load
duke
parents:
diff changeset
466 printOn(System.err);
a61af66fc99e Initial load
duke
parents:
diff changeset
467 }
a61af66fc99e Initial load
duke
parents:
diff changeset
468 throw new RuntimeException("Verify failed (1)");
a61af66fc99e Initial load
duke
parents:
diff changeset
469 }
a61af66fc99e Initial load
duke
parents:
diff changeset
470
a61af66fc99e Initial load
duke
parents:
diff changeset
471 // Every leaf (null) is black
a61af66fc99e Initial load
duke
parents:
diff changeset
472
a61af66fc99e Initial load
duke
parents:
diff changeset
473 if (node.getColor() == RBColor.RED) {
a61af66fc99e Initial load
duke
parents:
diff changeset
474 // Both its children are black
a61af66fc99e Initial load
duke
parents:
diff changeset
475 if (node.getLeft() != null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
476 if (node.getLeft().getColor() != RBColor.BLACK) {
a61af66fc99e Initial load
duke
parents:
diff changeset
477 if (DEBUGGING) {
a61af66fc99e Initial load
duke
parents:
diff changeset
478 System.err.println("Verify failed:");
a61af66fc99e Initial load
duke
parents:
diff changeset
479 printOn(System.err);
a61af66fc99e Initial load
duke
parents:
diff changeset
480 }
a61af66fc99e Initial load
duke
parents:
diff changeset
481 throw new RuntimeException("Verify failed (2)");
a61af66fc99e Initial load
duke
parents:
diff changeset
482 }
a61af66fc99e Initial load
duke
parents:
diff changeset
483 }
a61af66fc99e Initial load
duke
parents:
diff changeset
484 if (node.getRight() != null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
485 if (node.getRight().getColor() != RBColor.BLACK) {
a61af66fc99e Initial load
duke
parents:
diff changeset
486 if (DEBUGGING) {
a61af66fc99e Initial load
duke
parents:
diff changeset
487 System.err.println("Verify failed:");
a61af66fc99e Initial load
duke
parents:
diff changeset
488 printOn(System.err);
a61af66fc99e Initial load
duke
parents:
diff changeset
489 }
a61af66fc99e Initial load
duke
parents:
diff changeset
490 throw new RuntimeException("Verify failed (3)");
a61af66fc99e Initial load
duke
parents:
diff changeset
491 }
a61af66fc99e Initial load
duke
parents:
diff changeset
492 }
a61af66fc99e Initial load
duke
parents:
diff changeset
493 }
a61af66fc99e Initial load
duke
parents:
diff changeset
494
a61af66fc99e Initial load
duke
parents:
diff changeset
495 // Every simple path to a leaf contains the same number of black
a61af66fc99e Initial load
duke
parents:
diff changeset
496 // nodes
a61af66fc99e Initial load
duke
parents:
diff changeset
497 int i = verifyFromNode(node.getLeft());
a61af66fc99e Initial load
duke
parents:
diff changeset
498 int j = verifyFromNode(node.getRight());
a61af66fc99e Initial load
duke
parents:
diff changeset
499 if (i != j) {
a61af66fc99e Initial load
duke
parents:
diff changeset
500 if (DEBUGGING) {
a61af66fc99e Initial load
duke
parents:
diff changeset
501 System.err.println("Verify failed:");
a61af66fc99e Initial load
duke
parents:
diff changeset
502 printOn(System.err);
a61af66fc99e Initial load
duke
parents:
diff changeset
503 }
a61af66fc99e Initial load
duke
parents:
diff changeset
504 throw new RuntimeException("Verify failed (4) (left black count = " +
a61af66fc99e Initial load
duke
parents:
diff changeset
505 i + ", right black count = " + j + ")");
a61af66fc99e Initial load
duke
parents:
diff changeset
506 }
a61af66fc99e Initial load
duke
parents:
diff changeset
507
a61af66fc99e Initial load
duke
parents:
diff changeset
508 return i + ((node.getColor() == RBColor.RED) ? 0 : 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
509 }
a61af66fc99e Initial load
duke
parents:
diff changeset
510
a61af66fc99e Initial load
duke
parents:
diff changeset
511 /** Debugging */
a61af66fc99e Initial load
duke
parents:
diff changeset
512 private void printFromNode(RBNode node, PrintStream tty, int indentDepth) {
a61af66fc99e Initial load
duke
parents:
diff changeset
513 for (int i = 0; i < indentDepth; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
514 tty.print(" ");
a61af66fc99e Initial load
duke
parents:
diff changeset
515 }
a61af66fc99e Initial load
duke
parents:
diff changeset
516
a61af66fc99e Initial load
duke
parents:
diff changeset
517 tty.print("-");
a61af66fc99e Initial load
duke
parents:
diff changeset
518 if (node == null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
519 tty.println();
a61af66fc99e Initial load
duke
parents:
diff changeset
520 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
521 }
a61af66fc99e Initial load
duke
parents:
diff changeset
522
a61af66fc99e Initial load
duke
parents:
diff changeset
523 tty.println(" " + getNodeValue(node) +
a61af66fc99e Initial load
duke
parents:
diff changeset
524 ((node.getColor() == RBColor.RED) ? " (red)" : " (black)"));
a61af66fc99e Initial load
duke
parents:
diff changeset
525 printFromNode(node.getLeft(), tty, indentDepth + 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
526 printFromNode(node.getRight(), tty, indentDepth + 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
527 }
a61af66fc99e Initial load
duke
parents:
diff changeset
528
a61af66fc99e Initial load
duke
parents:
diff changeset
529 //----------------------------------------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
530 // Test harness
a61af66fc99e Initial load
duke
parents:
diff changeset
531 //
a61af66fc99e Initial load
duke
parents:
diff changeset
532
a61af66fc99e Initial load
duke
parents:
diff changeset
533 public static void main(String[] args) {
a61af66fc99e Initial load
duke
parents:
diff changeset
534 int treeSize = 10000;
a61af66fc99e Initial load
duke
parents:
diff changeset
535 int maxVal = treeSize;
a61af66fc99e Initial load
duke
parents:
diff changeset
536 System.err.println("Building tree...");
a61af66fc99e Initial load
duke
parents:
diff changeset
537 RBTree tree = new RBTree(new Comparator() {
a61af66fc99e Initial load
duke
parents:
diff changeset
538 public int compare(Object o1, Object o2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
539 Integer i1 = (Integer) o1;
a61af66fc99e Initial load
duke
parents:
diff changeset
540 Integer i2 = (Integer) o2;
a61af66fc99e Initial load
duke
parents:
diff changeset
541 if (i1.intValue() < i2.intValue()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
542 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
543 } else if (i1.intValue() == i2.intValue()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
544 return 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
545 }
a61af66fc99e Initial load
duke
parents:
diff changeset
546 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
547 }
a61af66fc99e Initial load
duke
parents:
diff changeset
548 });
a61af66fc99e Initial load
duke
parents:
diff changeset
549 Random rand = new Random(System.currentTimeMillis());
a61af66fc99e Initial load
duke
parents:
diff changeset
550 for (int i = 0; i < treeSize; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
551 Integer val = new Integer(rand.nextInt(maxVal) + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
552 try {
a61af66fc99e Initial load
duke
parents:
diff changeset
553 tree.insertNode(new RBNode(val));
a61af66fc99e Initial load
duke
parents:
diff changeset
554 if ((i > 0) && (i % 100 == 0)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
555 System.err.print(i + "...");
a61af66fc99e Initial load
duke
parents:
diff changeset
556 System.err.flush();
a61af66fc99e Initial load
duke
parents:
diff changeset
557 }
a61af66fc99e Initial load
duke
parents:
diff changeset
558 }
a61af66fc99e Initial load
duke
parents:
diff changeset
559 catch (Exception e) {
a61af66fc99e Initial load
duke
parents:
diff changeset
560 e.printStackTrace();
a61af66fc99e Initial load
duke
parents:
diff changeset
561 System.err.println("While inserting value " + val);
a61af66fc99e Initial load
duke
parents:
diff changeset
562 tree.printOn(System.err);
a61af66fc99e Initial load
duke
parents:
diff changeset
563 System.exit(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
564 }
a61af66fc99e Initial load
duke
parents:
diff changeset
565 }
a61af66fc99e Initial load
duke
parents:
diff changeset
566 // Now churn data in tree by deleting and inserting lots of nodes
a61af66fc99e Initial load
duke
parents:
diff changeset
567 System.err.println();
a61af66fc99e Initial load
duke
parents:
diff changeset
568 System.err.println("Churning tree...");
a61af66fc99e Initial load
duke
parents:
diff changeset
569 for (int i = 0; i < treeSize; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
570 if (DEBUGGING && VERBOSE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
571 System.err.println("Iteration " + i + ":");
a61af66fc99e Initial load
duke
parents:
diff changeset
572 tree.printOn(System.err);
a61af66fc99e Initial load
duke
parents:
diff changeset
573 }
a61af66fc99e Initial load
duke
parents:
diff changeset
574 // Pick a random value to remove (NOTE that this is not
a61af66fc99e Initial load
duke
parents:
diff changeset
575 // uniformly distributed)
a61af66fc99e Initial load
duke
parents:
diff changeset
576 RBNode xParent = null;
a61af66fc99e Initial load
duke
parents:
diff changeset
577 RBNode x = tree.getRoot();
a61af66fc99e Initial load
duke
parents:
diff changeset
578 int depth = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
579 while (x != null) {
a61af66fc99e Initial load
duke
parents:
diff changeset
580 // Traverse path down to leaf
a61af66fc99e Initial load
duke
parents:
diff changeset
581 xParent = x;
a61af66fc99e Initial load
duke
parents:
diff changeset
582 if (rand.nextBoolean()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
583 x = x.getLeft();
a61af66fc99e Initial load
duke
parents:
diff changeset
584 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
585 x = x.getRight();
a61af66fc99e Initial load
duke
parents:
diff changeset
586 }
a61af66fc99e Initial load
duke
parents:
diff changeset
587 ++depth;
a61af66fc99e Initial load
duke
parents:
diff changeset
588 }
a61af66fc99e Initial load
duke
parents:
diff changeset
589 // Pick a random height at which to remove value
a61af66fc99e Initial load
duke
parents:
diff changeset
590 int height = rand.nextInt(depth);
a61af66fc99e Initial load
duke
parents:
diff changeset
591 if (DEBUGGING) {
a61af66fc99e Initial load
duke
parents:
diff changeset
592 if (height >= depth) {
a61af66fc99e Initial load
duke
parents:
diff changeset
593 throw new RuntimeException("bug in java.util.Random");
a61af66fc99e Initial load
duke
parents:
diff changeset
594 }
a61af66fc99e Initial load
duke
parents:
diff changeset
595 }
a61af66fc99e Initial load
duke
parents:
diff changeset
596 // Walk that far back up (FIXME: off by one?)
a61af66fc99e Initial load
duke
parents:
diff changeset
597 while (height > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
598 xParent = xParent.getParent();
a61af66fc99e Initial load
duke
parents:
diff changeset
599 --height;
a61af66fc99e Initial load
duke
parents:
diff changeset
600 }
a61af66fc99e Initial load
duke
parents:
diff changeset
601 // Tell the tree to remove this node
a61af66fc99e Initial load
duke
parents:
diff changeset
602 if (DEBUGGING && VERBOSE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
603 System.err.println("(Removing value " + tree.getNodeValue(xParent) + ")");
a61af66fc99e Initial load
duke
parents:
diff changeset
604 }
a61af66fc99e Initial load
duke
parents:
diff changeset
605 tree.deleteNode(xParent);
a61af66fc99e Initial load
duke
parents:
diff changeset
606
a61af66fc99e Initial load
duke
parents:
diff changeset
607 // Now create and insert a new value
a61af66fc99e Initial load
duke
parents:
diff changeset
608 Integer newVal = new Integer(rand.nextInt(maxVal) + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
609 if (DEBUGGING && VERBOSE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
610 System.err.println("(Inserting value " + newVal + ")");
a61af66fc99e Initial load
duke
parents:
diff changeset
611 }
a61af66fc99e Initial load
duke
parents:
diff changeset
612 tree.insertNode(new RBNode(newVal));
a61af66fc99e Initial load
duke
parents:
diff changeset
613 }
a61af66fc99e Initial load
duke
parents:
diff changeset
614 System.err.println("All tests passed.");
a61af66fc99e Initial load
duke
parents:
diff changeset
615 }
a61af66fc99e Initial load
duke
parents:
diff changeset
616 }