Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 70a87a0

Browse files
balance tree
1 parent b3bccf3 commit 70a87a0

File tree

4 files changed

+90
-11
lines changed

4 files changed

+90
-11
lines changed

‎book/book.adoc‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ include::chapters/tree.adoc[]
7979
// (g)
8080
include::chapters/tree--binary-search-tree.adoc[]
8181

82+
include::chapters/tree--self-balancing-bst.adoc[]
83+
8284
// (g)
8385
// include::chapters/map.adoc[]
8486
include::chapters/map-intro.adoc[]
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
= Self-balancing Binary Search Trees
2+
3+
Binary Search Trees (BST) are a great data structure to find elements very fast _O(n log n)_.
4+
However, when the BST branches has different branch sizes then the performance suffers.
5+
In the worst case, all nodes can go to one side (e.g. right) and then the search time would be linear.
6+
At this point searching element won't be any better on that tree than an array or linked list. Yikes!
7+
8+
Self-balanced trees will automatically balanced the tree when an element is inserted to keep search performace.
9+
We balance a tree by making the height (distance from a node to the root) of any leaf on the tree as similar as possible.
10+
11+
.From unbalanced BST to balanced BST
12+
[source, javascript]
13+
----
14+
1 2
15+
\ / \
16+
2 => 1 3
17+
\
18+
3
19+
----
20+
21+
In the example above:
22+
- Unbalanced BST: height node `3` is 2 and height node `2` is 1.
23+
- Balanced BST: height node `3` is 1 and height node `2` is 1. Much better!
24+
25+
As you might notice, we balanced the tree in the example by doing a rotation.
26+
To be more specific we rotated node `1` to the left to balance the tree.
27+
Let's examine all the possible rotation we can do to balance a tree.
28+
29+
== Tree Rotations
30+
31+
We can do single rotations left and right and also we can do double rotations.
32+
Let's go one by one.
33+
34+
=== Single Right Rotation
35+
36+
Right rotation moves a node on the right as a child of other node.
37+
38+
Take a look at the `@example` in the code below.
39+
As you can see we have an unbalanced tree `4-3-2-1`.
40+
We want to balance the tree, for that we need to do a right rotation of node 3.
41+
So, the node 3 is moved as the right child of the previous child.
42+
43+
.Single right rotation implementation
44+
[source, javascript]
45+
----
46+
include::{codedir}/data-structures/trees/tree-rotations.js[tag=rightRotation]
47+
----
48+
49+
.In the `rightRotation` we identify 3 nodes:
50+
- `node` this is the node we want to rotate to the right. E.g., `node 3`
51+
- `newParent` this is the new parent after the rotation. E.g., `node 2`
52+
- `grandparent` this the current's node parent. E.g. `node 4`.
53+
54+
The `swapParentChild` as it name says, swap the children.
55+
56+
.Swap Parent and Child Implementation
57+
[source, javascript]
58+
----
59+
include::{codedir}/data-structures/trees/tree-rotations.js[tag=swapParentChild]
60+
----
61+
62+

‎src/data-structures/trees/red-black-tree.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ class RedBlackTree extends BinarySearchTree {
8989
const grandParent = oldParent.parent;
9090

9191
if (grandParent) {
92-
// do something
92+
// do nothing
9393
} else {
9494
this.root = node;
9595
node.parent = null;

‎src/data-structures/trees/tree-rotations.js‎

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// tag::swapParentChild[]
12
/**
23
* Swap parent's child
34
*
@@ -26,7 +27,10 @@ function swapParentChild(oldChild, newChild, parent) {
2627
newChild.parent = null;
2728
}
2829
}
30+
// end::swapParentChild[]
2931

32+
33+
// tag::leftRotation[]
3034
/**
3135
* Single Left Rotation (LL Rotation)
3236
*
@@ -55,26 +59,28 @@ function leftRotation(node) {
5559

5660
return newParent;
5761
}
62+
// end::leftRotation[]
5863

64+
// tag::rightRotation[]
5965
/**
6066
* Single Right Rotation (RR Rotation)
6167
*
6268
* @example rotate node 3 to the right
6369
*
64-
* 4 4
65-
* / /
66-
* 3* 2
67-
* / / \
68-
* 2 ---| right-rotation(3) |--> 1 3*
70+
* 4 4
71+
* / /
72+
* 3* 2
73+
* / / \
74+
* 2 ---| right-rotation(3) |--> 1 3*
6975
* /
7076
* 1
7177
*
72-
* @param {TreeNode} node
73-
* @returns {TreeNode} new parent after the rotation
78+
* @param {TreeNode} node this is the node we want to rotate to the right. (E.g., node 3)
79+
* @returns {TreeNode} new parent after the rotation (E.g., node 2)
7480
*/
7581
function rightRotation(node) {
76-
const newParent = node.left;
77-
const grandparent = node.parent;
82+
const newParent = node.left;// E.g., node 2
83+
const grandparent = node.parent;// E.g., node 4
7884

7985
swapParentChild(node, newParent, grandparent);
8086

@@ -84,7 +90,9 @@ function rightRotation(node) {
8490

8591
return newParent;
8692
}
93+
// end::rightRotation[]
8794

95+
// tag::leftRightRotation[]
8896
/**
8997
* Left Right Rotation (LR Rotation)
9098
*
@@ -97,14 +105,16 @@ function rightRotation(node) {
97105
* \ / 1 3*
98106
* 2 1
99107
*
100-
* @param {TreeNode} node
108+
* @param {TreeNode} node this is the node we want to rotate to the right. E.g., node 3
101109
* @returns {TreeNode} new parent after the rotation
102110
*/
103111
function leftRightRotation(node) {
104112
leftRotation(node.left);
105113
return rightRotation(node);
106114
}
115+
// end::leftRightRotation[]
107116

117+
// tag::rightLeftRotation[]
108118
/**
109119
* Right Left Rotation (RL Rotation)
110120
*
@@ -123,7 +133,9 @@ function rightLeftRotation(node) {
123133
rightRotation(node.right);
124134
return leftRotation(node);
125135
}
136+
// end::rightLeftRotation[]
126137

138+
// tag::balance[]
127139
/**
128140
* Balance tree doing rotations based on balance factor.
129141
*
@@ -154,7 +166,9 @@ function balance(node) {
154166
}
155167
return node;
156168
}
169+
// end::balance[]
157170

171+
// tag::balanceUptream[]
158172
/**
159173
* Bubbles up balancing nodes a their parents
160174
*
@@ -169,6 +183,7 @@ function balanceUptream(node) {
169183
}
170184
return newParent;
171185
}
186+
// end::balanceUptream[]
172187

173188
module.exports = {
174189
leftRotation,

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /