Skip to content

Commit bcb4c28

Browse files
committed
feat(BinaryTreeNode): add BinaryTreeNode.from
1 parent 28346a4 commit bcb4c28

File tree

3 files changed

+157
-89
lines changed

3 files changed

+157
-89
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
],
1515
"scripts": {
1616
"test": "jest --verbose",
17-
"watch": "jest --watch --verbose --coverage",
17+
"watch": "jest --watch --coverage",
1818
"ci": "npx eslint src/ && jest --coverage",
1919
"coverage": "jest --coverage && open coverage/lcov-report/index.html",
2020
"coverage:win": "jest --coverage && cmd.exe /C start coverage/lcov-report/index.html",

src/data-structures/trees/binary-tree-node.js

+15
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,21 @@ class BinaryTreeNode {
172172
this.meta.data = value;
173173
return this;
174174
}
175+
176+
/**
177+
* Convert Binary tree from an iterable (e.g. array)
178+
* @param {array|string} iterable - The iterable
179+
*/
180+
static from(iterable = []) {
181+
const toBinaryTree = (array, index = 0) => {
182+
if (index >= array.length) return null;
183+
const node = new BinaryTreeNode(array[index]);
184+
node.setLeftAndUpdateParent(toBinaryTree(array, index * 2 + 1));
185+
node.setRightAndUpdateParent(toBinaryTree(array, index * 2 + 2));
186+
return node;
187+
};
188+
return toBinaryTree(Array.from(iterable));
189+
}
175190
}
176191

177192
BinaryTreeNode.RIGHT = RIGHT;
Original file line numberDiff line numberDiff line change
@@ -1,114 +1,167 @@
11
const { BinaryTreeNode } = require('../../index');
22

3+
const { LEFT, RIGHT } = BinaryTreeNode;
4+
35
describe('Binary Tree Node', () => {
46
let treeNode;
57

6-
beforeEach(() => {
7-
treeNode = new BinaryTreeNode('hola');
8-
});
9-
10-
it('should start with null parent', () => {
11-
expect(treeNode.parent).toBe(null);
12-
});
13-
14-
it('should start with empty metadata', () => {
15-
expect(treeNode.meta).toEqual({});
16-
});
17-
18-
it('should hold a value', () => {
19-
expect(treeNode.value).toBe('hola');
20-
});
21-
22-
it('should have a height 0', () => {
23-
expect(treeNode.height).toBe(0);
24-
});
25-
26-
it('should set/get left node', () => {
27-
expect(treeNode.left).toBe(null);
28-
const newNode = new BinaryTreeNode(1);
29-
treeNode.setLeftAndUpdateParent(newNode);
30-
expect(treeNode.left.value).toBe(1);
31-
32-
expect(newNode.parent).toBe(treeNode);
33-
expect(treeNode.height).toBe(1);
34-
expect(treeNode.balanceFactor).toBe(1);
35-
});
36-
37-
it('should set/get right node', () => {
38-
expect(treeNode.right).toBe(null);
39-
const newNode = new BinaryTreeNode(1);
40-
treeNode.setRightAndUpdateParent(newNode);
41-
42-
expect(treeNode.right.value).toBe(1);
43-
expect(newNode.parent).toBe(treeNode);
44-
expect(treeNode.height).toBe(1);
45-
expect(treeNode.balanceFactor).toBe(-1);
46-
});
47-
48-
describe('Family operations', () => {
49-
let g;
50-
let p;
51-
let u;
52-
let c;
53-
let s;
54-
8+
describe('with instance', () => {
559
beforeEach(() => {
56-
g = new BinaryTreeNode('grandparent');
57-
p = new BinaryTreeNode('parent');
58-
u = new BinaryTreeNode('uncle');
59-
c = new BinaryTreeNode('child');
60-
s = new BinaryTreeNode('sibling');
61-
62-
g.setRightAndUpdateParent(p);
63-
g.setLeftAndUpdateParent(u);
64-
p.setRightAndUpdateParent(c);
65-
p.setLeftAndUpdateParent(s);
10+
treeNode = new BinaryTreeNode('hola');
6611
});
6712

68-
it('should set heights', () => {
69-
expect(g.height).toBe(2);
70-
expect(g.balanceFactor).toBe(-1);
71-
72-
expect(p.height).toBe(1);
73-
expect(p.balanceFactor).toBe(0);
13+
it('should start with null parent', () => {
14+
expect(treeNode.parent).toBe(null);
15+
});
7416

75-
expect(u.height).toBe(0);
76-
expect(u.balanceFactor).toBe(0);
17+
it('should start with empty metadata', () => {
18+
expect(treeNode.meta).toEqual({});
7719
});
7820

79-
it('should get the sibling', () => {
80-
expect(c.sibling).toBe(s);
81-
expect(p.sibling).toBe(u);
21+
it('should hold a value', () => {
22+
expect(treeNode.value).toBe('hola');
8223
});
8324

84-
it('should set leaf correctly', () => {
85-
expect(c.isLeaf).toBe(true);
86-
expect(u.isLeaf).toBe(true);
87-
expect(p.isLeaf).toBe(false);
88-
expect(g.isLeaf).toBe(false);
25+
it('should have a height 0', () => {
26+
expect(treeNode.height).toBe(0);
8927
});
9028

91-
it('should get null if no sibling', () => {
92-
expect(g.sibling).toBe(null);
29+
it('should set/get left node', () => {
30+
expect(treeNode.left).toBe(null);
31+
const newNode = new BinaryTreeNode(1);
32+
treeNode.setLeftAndUpdateParent(newNode);
33+
expect(treeNode.left.value).toBe(1);
34+
35+
expect(newNode.parent).toBe(treeNode);
36+
expect(treeNode.height).toBe(1);
37+
expect(treeNode.balanceFactor).toBe(1);
9338
});
9439

95-
it('should get the uncle', () => {
96-
expect(c.uncle).toBe(u);
40+
it('should set/get right node', () => {
41+
expect(treeNode.right).toBe(null);
42+
const newNode = new BinaryTreeNode(1);
43+
treeNode.setRightAndUpdateParent(newNode);
44+
45+
expect(treeNode.right.value).toBe(1);
46+
expect(newNode.parent).toBe(treeNode);
47+
expect(treeNode.height).toBe(1);
48+
expect(treeNode.balanceFactor).toBe(-1);
9749
});
9850

99-
it('should get null if no uncle', () => {
100-
expect(g.uncle).toBe(null);
101-
expect(p.uncle).toBe(null);
51+
describe('Family operations', () => {
52+
let g;
53+
let p;
54+
let u;
55+
let c;
56+
let s;
57+
58+
beforeEach(() => {
59+
g = new BinaryTreeNode('grandparent');
60+
p = new BinaryTreeNode('parent');
61+
u = new BinaryTreeNode('uncle');
62+
c = new BinaryTreeNode('child');
63+
s = new BinaryTreeNode('sibling');
64+
65+
g.setRightAndUpdateParent(p);
66+
g.setLeftAndUpdateParent(u);
67+
p.setRightAndUpdateParent(c);
68+
p.setLeftAndUpdateParent(s);
69+
});
70+
71+
it('should set heights', () => {
72+
expect(g.height).toBe(2);
73+
expect(g.balanceFactor).toBe(-1);
74+
75+
expect(p.height).toBe(1);
76+
expect(p.balanceFactor).toBe(0);
77+
78+
expect(u.height).toBe(0);
79+
expect(u.balanceFactor).toBe(0);
80+
});
81+
82+
it('should get the sibling', () => {
83+
expect(c.sibling).toBe(s);
84+
expect(p.sibling).toBe(u);
85+
});
86+
87+
it('should set leaf correctly', () => {
88+
expect(c.isLeaf).toBe(true);
89+
expect(u.isLeaf).toBe(true);
90+
expect(p.isLeaf).toBe(false);
91+
expect(g.isLeaf).toBe(false);
92+
});
93+
94+
it('should get null if no sibling', () => {
95+
expect(g.sibling).toBe(null);
96+
});
97+
98+
it('should get the uncle', () => {
99+
expect(c.uncle).toBe(u);
100+
});
101+
102+
it('should get null if no uncle', () => {
103+
expect(g.uncle).toBe(null);
104+
expect(p.uncle).toBe(null);
105+
});
106+
107+
it('true if is parent left child', () => {
108+
expect(s.isParentLeftChild).toBe(true);
109+
expect(s.isParentRightChild).toBe(false);
110+
});
111+
112+
it('true if is parent left child', () => {
113+
expect(c.isParentLeftChild).toBe(false);
114+
expect(c.isParentRightChild).toBe(true);
115+
});
102116
});
117+
});
103118

104-
it('true if is parent left child', () => {
105-
expect(s.isParentLeftChild).toBe(true);
106-
expect(s.isParentRightChild).toBe(false);
119+
describe('with static methods', () => {
120+
it('should work with null', () => {
121+
const tree = BinaryTreeNode.from();
122+
expect(tree).toEqual(null);
107123
});
108124

109-
it('true if is parent left child', () => {
110-
expect(c.isParentLeftChild).toBe(false);
111-
expect(c.isParentRightChild).toBe(true);
125+
it('should build from array', () => {
126+
/*
127+
0
128+
/ \
129+
1 2
130+
/ \ \
131+
3 5 4
132+
*/
133+
const tree = BinaryTreeNode.from([0, 1, 2, 3, 5, null, 4]);
134+
expect(tree.toValues()).toEqual({
135+
value: 0,
136+
left: 1,
137+
right: 2,
138+
parent: null,
139+
parentSide: null,
140+
});
141+
142+
expect(tree.left.toValues()).toEqual({
143+
value: 1,
144+
left: 3,
145+
right: 5,
146+
parent: 0,
147+
parentSide: LEFT,
148+
});
149+
150+
expect(tree.right.toValues()).toEqual({
151+
value: 2,
152+
left: null,
153+
right: 4,
154+
parent: 0,
155+
parentSide: RIGHT,
156+
});
157+
158+
expect(tree.right.right.toValues()).toEqual({
159+
value: 4,
160+
left: null,
161+
right: null,
162+
parent: 2,
163+
parentSide: RIGHT,
164+
});
112165
});
113166
});
114167
});

0 commit comments

Comments
 (0)