1
1
/**
2
- * This file contains an implementation of an AVL tree. An AVL tree
2
+ * This file contains an implementation of a Red-Black tree. A RB tree
3
3
* is a special type of binary tree which self balances itself to keep
4
4
* operations logarithmic.
5
5
*
8
8
9
9
public class RedBlackTree <T extends Comparable <T >> {
10
10
11
+ static final boolean RED = true ;
12
+ static final boolean BLACK = false ;
13
+
11
14
class Node implements TreePrinter .PrintableNode {
12
15
13
- // 'bf' is short for Balance Factor
14
- int bf ;
16
+ // The color of the node. By default all nodes start red.
17
+ boolean color = RED ;
15
18
16
19
// The value/data contained within the node.
17
20
T value ;
18
21
19
- // The height of this node in the tree.
20
- int height ;
21
-
22
- // The left and the right children of this node.
23
- Node left , right ;
22
+ // The left, right and parent references for this node.
23
+ Node left , right , parent ;
24
24
25
- public Node (T value , Node left , Node right ) {
25
+ public Node (T value , Node parent ) {
26
26
this .value = value ;
27
- this .left = left ;
28
- this .right = right ;
27
+ this .parent = parent ;
29
28
}
30
29
31
30
@ Override
@@ -51,20 +50,6 @@ public String getText() {
51
50
// Tracks the number of nodes inside the tree.
52
51
private int nodeCount = 0 ;
53
52
54
- // Special token value used as an alternative to returning 'null'.
55
- // The TOKEN is used to indicate special return value signals. For example,
56
- // we can return the TOKEN instead of null when we're inserting a new item
57
- // and discover the value we were inserting already exists in the tree.
58
- private Node TOKEN = new Node (null , null , null );
59
-
60
- // The height of a rooted tree is the number of edges between the tree's
61
- // root and its furthest leaf. This means that a tree containing a single
62
- // node has a height of 0.
63
- public int height () {
64
- if (root == null ) return 0 ;
65
- return root .height ;
66
- }
67
-
68
53
// Returns the number of nodes in the tree.
69
54
public int size () {
70
55
return nodeCount ;
@@ -76,9 +61,9 @@ public boolean isEmpty() {
76
61
}
77
62
78
63
// Prints a visual representation of the tree to the console.
79
- // public void display() {
80
- // TreePrinter.print(root);
81
- // }
64
+ public void display () {
65
+ TreePrinter .print (root );
66
+ }
82
67
83
68
// Return true/false depending on whether a value exists in the tree.
84
69
public boolean contains (T value ) {
@@ -104,59 +89,96 @@ private boolean contains(Node node, T value) {
104
89
105
90
}
106
91
92
+ public boolean insert (T value ) {
93
+
94
+ if (value == null ) throw new IllegalArgumentException ();
95
+
96
+ // No root node.
97
+ if (root == null ) {
98
+ root = new Node (value , null );
99
+ return true ;
100
+ }
101
+
102
+ for (Node node = root ;;) {
103
+
104
+ int cmp = node .value .compareTo (value );
105
+
106
+ if (cmp < 0 ) {
107
+ if (node .left == null ) {
108
+ node .left = new Node (value , node );
109
+ // balance
110
+ return true ;
111
+ }
112
+ node = node .left ;
113
+
114
+ } else if (cmp > 0 ) {
115
+ if (node .right == null ) {
116
+ node .right = new Node (value , node );
117
+ // balance
118
+ return true ;
119
+ }
120
+ node = node .right ;
121
+
122
+ // Duplicate value.
123
+ } else return false ;
124
+
125
+ }
126
+
127
+ }
128
+
107
129
// Helper method to find the leftmost node (which has the smallest value)
108
- // private Node findMin(Node node) {
109
- // while(node.left != null)
110
- // node = node.left;
111
- // return node;
112
- // }
130
+ private Node findMin (Node node ) {
131
+ while (node .left != null )
132
+ node = node .left ;
133
+ return node ;
134
+ }
113
135
114
136
// Helper method to find the rightmost node (which has the largest value)
115
- // private Node findMax(Node node) {
116
- // while(node.right != null)
117
- // node = node.right;
118
- // return node;
119
- // }
137
+ private Node findMax (Node node ) {
138
+ while (node .right != null )
139
+ node = node .right ;
140
+ return node ;
141
+ }
120
142
121
143
// Returns as iterator to traverse the tree in order.
122
- // public java.util.Iterator<T> iterator () {
123
-
124
- // final int expectedNodeCount = nodeCount;
125
- // final java.util.Stack<Node> stack = new java.util.Stack<>();
126
- // stack.push(root);
127
-
128
- // return new java.util.Iterator<T> () {
129
- // Node trav = root;
130
- // @Override
131
- // public boolean hasNext() {
132
- // if (expectedNodeCount != nodeCount) throw new java.util.ConcurrentModificationException();
133
- // return root != null && !stack.isEmpty();
134
- // }
135
- // @Override
136
- // public T next () {
144
+ public java .util .Iterator <T > iterator () {
145
+
146
+ final int expectedNodeCount = nodeCount ;
147
+ final java .util .Stack <Node > stack = new java .util .Stack <>();
148
+ stack .push (root );
149
+
150
+ return new java .util .Iterator <T > () {
151
+ Node trav = root ;
152
+ @ Override
153
+ public boolean hasNext () {
154
+ if (expectedNodeCount != nodeCount ) throw new java .util .ConcurrentModificationException ();
155
+ return root != null && !stack .isEmpty ();
156
+ }
157
+ @ Override
158
+ public T next () {
137
159
138
- // if (expectedNodeCount != nodeCount) throw new java.util.ConcurrentModificationException();
160
+ if (expectedNodeCount != nodeCount ) throw new java .util .ConcurrentModificationException ();
139
161
140
- // while(trav != null && trav.left != null) {
141
- // stack.push(trav.left);
142
- // trav = trav.left;
143
- // }
162
+ while (trav != null && trav .left != null ) {
163
+ stack .push (trav .left );
164
+ trav = trav .left ;
165
+ }
144
166
145
- // Node node = stack.pop();
167
+ Node node = stack .pop ();
146
168
147
- // if (node.right != null) {
148
- // stack.push(node.right);
149
- // trav = node.right;
150
- // }
169
+ if (node .right != null ) {
170
+ stack .push (node .right );
171
+ trav = node .right ;
172
+ }
151
173
152
- // return node.value;
153
- // }
154
- // @Override
155
- // public void remove() {
156
- // throw new UnsupportedOperationException();
157
- // }
158
- // };
159
- // }
174
+ return node .value ;
175
+ }
176
+ @ Override
177
+ public void remove () {
178
+ throw new UnsupportedOperationException ();
179
+ }
180
+ };
181
+ }
160
182
161
183
// Make sure all left child nodes are smaller in value than their parent and
162
184
// make sure all right child nodes are greater in value than their parent.
0 commit comments