-
Notifications
You must be signed in to change notification settings - Fork 0
/
Red_Black_Tree.java
180 lines (179 loc) · 7.18 KB
/
Red_Black_Tree.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
public class Red_Black_Tree{
private Node root; // the properties of the tree
private Node median; //pointer to median
private int size;
// constructor. Complexity: theta(1)
public Red_Black_Tree(){
root = null;
median = null;
size=0;
}
// method which returns the root of the tree. Complexity: theta(1)
public Node getRoot(){
return root;
}
// method which returns the value of the median. Complexity: theta(1)
public double printMedian(){
if(median!=null)
return median.getValue();
System.out.println("It is empty!");
return 0.0;
}
// method which inserts values into the tree, the method was built according to algorithm in the book. Complexity: theta(log n). page 236
public void insert(double value){
Node z=new Node(value,null);
size++; // updates the size
if (root==null) {
z.setColor('b');
root = z;
median=z;
}
else{ // if the tree isn't empty
Node y = null;
Node x = root;
while (x != null) {//finds the place to z
y = x;
if (value < x.getValue())
x = x.getLeft();
else
x = x.getRight();
}
z.setParent(y);
if(value<y.getValue())
y.setLeft(z);
else
y.setRight(z); // saves the correct structure
fix_Median(value); //moves the median pointer to the right new median
insert_FixUp(z); // makes it RBT
}
}
//method which gets a new Value in the tree and updates the previous median to the current median. Complexity: O(log n)
private void fix_Median(double newValue){
// if the size is even and the new Value is smaller than the previous median so the current median would be the predecessor node of median
if(size%2==0 && median.getValue() > newValue)
median = tree_Predecessor(median);
// if the size is odd and the new Value is bigger than the previous median so the current median would be the successor node of median
else if(size%2==1 && median.getValue() < newValue)
median = tree_Successor(median);
// else, the median wouldn't change
}
// finds the minimum in the sub-tree of the node according to algorithm in the book. complexity: O(log n)
private Node tree_Min(Node x){
while(x.getLeft()!=null) // finds the most left leaf
x=x.getLeft();
return x;
}
// finds the maximum in the sub-tree of the node according to algorithm in the book. complexity: O(log n)
private Node tree_Max(Node x){
while(x.getRight()!=null) // finds the most right leaf
x=x.getRight();
return x;
}
//method which gets a node and returns the successor node according to algorithm in the book. complexity: O(log n). page 218
private Node tree_Successor(Node x){
if(x.getRight()!=null) // finds the most right leaf
return tree_Min(x.getRight());
Node y=x.getParent();
while(y!=null && x==y.getRight()){
x = y;
y = y.getParent();
}
return y;
}
// method which gets a node and returns the predecessor node. complexity: O(log n)
private Node tree_Predecessor(Node x){
if(x.getLeft()!=null) // finds the most left leaf.
return tree_Max(x.getLeft());
Node y=x.getParent();
while(y!=null && x==y.getLeft()){
x = y;
y = y.getParent();
}
return y;
}
public void preorder_Tree_Walk(){
preorder_Tree_Walk(root);
}
private void preorder_Tree_Walk(Node x){
if(x!=null) {
System.out.print(x+"\n");
preorder_Tree_Walk(x.getLeft());
preorder_Tree_Walk(x.getRight());
}
}
// method which rotates (to the left) part of the tree according to the book. complexity: theta(1) page 234
private void left_Rotate(Node x){
Node y=x.getRight();
x.setRight(y.getLeft()); // turns the left subtree of y into the right subtree of x
if(y.getLeft()!=null)
y.getLeft().setParent(x);
y.setParent(x.getParent()); // links
if(x.getParent()==null)
root=y;
else if (x==x.getParent().getLeft())
x.getParent().setLeft(y);
else
x.getParent().setRight(y);
y.setLeft(x); //sets the left son of y to be x
x.setParent(y);
}
// method which rotates (to the left) part of the tree according to the guide book. complexity: theta(1) page 186
private void right_Rotate(Node x){
Node y=x.getLeft();
x.setLeft(y.getRight()); // turns the right subtree of y into the left subtree of x
if(y.getRight()!=null)
y.getRight().setParent(x);
y.setParent(x.getParent()); // links
if(x.getParent()==null)
root=y;
else if (x==x.getParent().getRight())
x.getParent().setRight(y);
else
x.getParent().setLeft(y);
y.setRight(x); //sets the right son of y to be x
x.setParent(y);
}
// method which saves the attributes of RB-tree according to the algorithm in the book. complexity: O(log n). page 236
private void insert_FixUp(Node z){
Node y;
while (z!=root && z.getParent().getColor()=='r'){//while the parent is red and could be a problem
if(z.getParent()==z.getParent().getParent().getLeft()) { // if the parent of z is left son
y = z.getParent().getParent().getRight(); // the uncle
if (y!=null && y.getColor() == 'r') {
z.getParent().setColor('b'); //case 1
y.setColor('b');
z.getParent().getParent().setColor('r');
z = z.getParent().getParent();
}
else{ // case 2
if (z == z.getParent().getRight()) {
z = z.getParent();
left_Rotate(z);
}
z.getParent().setColor('b'); // case 3
z.getParent().getParent().setColor('r');
right_Rotate(z.getParent().getParent());
}
}
else{ // if the parent of z is right son
y = z.getParent().getParent().getLeft();// the uncle
if (y!=null && y.getColor() == 'r') {
z.getParent().setColor('b'); //case 1
y.setColor('b');
z.getParent().getParent().setColor('r');
z = z.getParent().getParent();
}
else{ // case 2
if (z == z.getParent().getLeft()) {
z = z.getParent();
right_Rotate(z);
}
z.getParent().setColor('b'); // case 3
z.getParent().getParent().setColor('r');
left_Rotate(z.getParent().getParent());
}
}
}
root.setColor('b'); // the root's color always should be black
}
}