Skip to content

Commit 6be1c4c

Browse files
committed
[Trees]
1 parent 8d07bc9 commit 6be1c4c

File tree

2 files changed

+76
-86
lines changed

2 files changed

+76
-86
lines changed

src/ts/data-structures/red-black-tree.ts

+49-85
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export default class RedBlackTree<T> extends BinarySearchTree<T> {
2323
private rotationLL(node: RedBlackNode<T>) {
2424
const tmp = node.left;
2525
node.left = tmp.right;
26-
if (typeof tmp.right.key !== 'undefined') {
26+
if (tmp.right && tmp.right.key) {
2727
tmp.right.parent = node;
2828
}
2929
tmp.parent = node.parent;
@@ -54,7 +54,7 @@ export default class RedBlackTree<T> extends BinarySearchTree<T> {
5454
private rotationRR(node: RedBlackNode<T>) {
5555
const tmp = node.right;
5656
node.right = tmp.left;
57-
if (typeof tmp.left.key !== 'undefined') {
57+
if (tmp.left && tmp.left.key) {
5858
tmp.left.parent = node;
5959
}
6060
tmp.parent = node.parent;
@@ -101,101 +101,65 @@ export default class RedBlackTree<T> extends BinarySearchTree<T> {
101101
}
102102

103103
private fixTreeProperties(node: RedBlackNode<T>) {
104-
let uncle: RedBlackNode<T>;
105-
let grandParent: RedBlackNode<T>;
106104
while (node && node.parent && node.parent.color === Colors.RED && node.color !== Colors.BLACK) {
107-
grandParent = node.parent.parent;
108-
if (grandParent && grandParent.left === node.parent) {
109-
if (grandParent.right != null) {
110-
uncle = grandParent.right;
111-
if (uncle.color === Colors.RED) {
112-
node.parent.color = Colors.BLACK;
113-
uncle.color = Colors.BLACK;
114-
grandParent.color = Colors.RED;
115-
node = grandParent;
116-
}
117-
} else {
118-
if (node.parent.right === node) {
119-
node = node.parent;
120-
this.leftRotate(node);
121-
}
122-
node.parent.color = Colors.BLACK;
105+
let parent = node.parent;
106+
const grandParent = parent.parent;
107+
108+
// case A
109+
if (grandParent && grandParent.left === parent) {
110+
111+
const uncle = grandParent.right;
112+
113+
// case 1: uncle of node is also red - only recoloring
114+
if (uncle && uncle.color === Colors.RED) {
123115
grandParent.color = Colors.RED;
124-
this.rightRotate(grandParent);
125-
}
126-
} else {
127-
if (grandParent.left != null) {
128-
uncle = grandParent.left;
129-
if (uncle.color === Colors.RED) {
130-
node.parent.color = Colors.BLACK;
131-
uncle.color = Colors.BLACK;
132-
grandParent.color = Colors.RED;
133-
node = grandParent;
134-
}
116+
parent.color = Colors.BLACK;
117+
uncle.color = Colors.BLACK;
118+
node = grandParent;
135119
} else {
136-
if (node.parent.left === node) {
137-
node = node.parent;
138-
this.rightRotate(node);
120+
// case 2: node is right child - left rotate
121+
if (node === parent.right) {
122+
this.rotationRR(parent);
123+
node = parent;
124+
parent = node.parent;
139125
}
140-
node.parent.color = Colors.BLACK;
126+
127+
// case 3: node is left child - right rotate
128+
this.rotationLL(grandParent);
129+
// swap color
130+
parent.color = Colors.BLACK;
141131
grandParent.color = Colors.RED;
142-
this.leftRotate(grandParent);
132+
node = parent;
143133
}
144-
}
145-
}
146-
this.root.color = Colors.BLACK;
147-
}
148134

149-
leftRotate(p: RedBlackNode<T>) {
150-
if (p.right != null) {
151-
const y = p.right;
152-
if (y.left != null) {
153-
p.right = y.left;
154-
y.left.parent = p;
155-
} else {
156-
p.right = null;
157-
}
158-
if (p.parent != null) {
159-
y.parent = p.parent;
160-
}
161-
if (p.parent == null) {
162-
this.root = y;
163-
} else {
164-
if (p === p.parent.left) {
165-
p.parent.left = y;
166-
} else {
167-
p.parent.right = y;
168-
}
169-
}
170-
y.left = p;
171-
p.parent = y;
172-
}
173-
}
135+
} else { // case B: parent is right child of grand parent
174136

175-
rightRotate(p: RedBlackNode<T>) {
176-
if (p.left != null) {
177-
const y = p.left;
178-
if (y.right != null) {
179-
p.left = y.right;
180-
y.right.parent = p;
181-
} else {
182-
p.left = null;
183-
}
184-
if (p.parent != null) {
185-
y.parent = p.parent;
186-
}
187-
if (p.parent == null) {
188-
this.root = y;
189-
} else {
190-
if (p === p.parent.left) {
191-
p.parent.left = y;
137+
const uncle = grandParent.left;
138+
139+
// case 1: uncle is read - only recoloring
140+
if (uncle && uncle.color === Colors.RED) {
141+
grandParent.color = Colors.RED;
142+
parent.color = Colors.BLACK;
143+
uncle.color = Colors.BLACK;
144+
node = grandParent;
192145
} else {
193-
p.parent.right = y;
146+
// case 2: node is left child - left rotate
147+
if (node === parent.left) {
148+
this.rotationLL(parent);
149+
node = parent;
150+
parent = node.parent;
151+
}
152+
153+
// case 3: node is right child - left rotate
154+
this.rotationRR(grandParent);
155+
// swap color
156+
parent.color = Colors.BLACK;
157+
grandParent.color = Colors.RED;
158+
node = parent;
194159
}
195160
}
196-
y.right = p;
197-
p.parent = y;
198161
}
162+
this.root.color = Colors.BLACK;
199163
}
200164

201165
getRoot() {

test/ts/data-structures/red-black-tree.spec.ts

+27-1
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,37 @@ describe('RedBlackTree', () => {
7171
assertNode(node.left, 1, Colors.BLACK);
7272
assertNode(node.right, 3, Colors.BLACK);
7373
node = tree.getRoot().right;
74-
assertNode(node, 5, Colors.RED);
74+
assertNode(node, 6, Colors.RED);
7575
assertNode(node.left, 5, Colors.BLACK);
7676
assertNode(node.right, 7, Colors.BLACK);
7777
assertNode(node.right.right, 8, Colors.RED);
7878

79+
tree.insert(9);
80+
assertNode(tree.getRoot(), 4, Colors.BLACK);
81+
node = tree.getRoot().left;
82+
assertNode(node, 2, Colors.RED);
83+
assertNode(node.left, 1, Colors.BLACK);
84+
assertNode(node.right, 3, Colors.BLACK);
85+
node = tree.getRoot().right;
86+
assertNode(node, 6, Colors.RED);
87+
assertNode(node.left, 5, Colors.BLACK);
88+
assertNode(node.right, 8, Colors.BLACK);
89+
assertNode(node.right.left, 7, Colors.RED);
90+
assertNode(node.right.right, 9, Colors.RED);
91+
92+
tree.insert(10);
93+
assertNode(tree.getRoot(), 4, Colors.BLACK);
94+
node = tree.getRoot().left;
95+
assertNode(node, 2, Colors.BLACK);
96+
assertNode(node.left, 1, Colors.BLACK);
97+
assertNode(node.right, 3, Colors.BLACK);
98+
node = tree.getRoot().right;
99+
assertNode(node, 6, Colors.BLACK);
100+
assertNode(node.left, 5, Colors.BLACK);
101+
assertNode(node.right, 8, Colors.RED);
102+
assertNode(node.right.left, 7, Colors.BLACK);
103+
assertNode(node.right.right, 9, Colors.BLACK);
104+
assertNode(node.right.right.right, 10, Colors.RED);
79105

80106
});
81107

0 commit comments

Comments
 (0)