Skip to content

Commit

Permalink
feat(BinaryTreeNode): add BinaryTreeNode.from
Browse files Browse the repository at this point in the history
  • Loading branch information
amejiarosario committed Sep 2, 2020
1 parent 28346a4 commit bcb4c28
Show file tree
Hide file tree
Showing 3 changed files with 157 additions and 89 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
],
"scripts": {
"test": "jest --verbose",
"watch": "jest --watch --verbose --coverage",
"watch": "jest --watch --coverage",
"ci": "npx eslint src/ && jest --coverage",
"coverage": "jest --coverage && open coverage/lcov-report/index.html",
"coverage:win": "jest --coverage && cmd.exe /C start coverage/lcov-report/index.html",
Expand Down
15 changes: 15 additions & 0 deletions src/data-structures/trees/binary-tree-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,21 @@ class BinaryTreeNode {
this.meta.data = value;
return this;
}

/**
* Convert Binary tree from an iterable (e.g. array)
* @param {array|string} iterable - The iterable
*/
static from(iterable = []) {
const toBinaryTree = (array, index = 0) => {
if (index >= array.length) return null;
const node = new BinaryTreeNode(array[index]);
node.setLeftAndUpdateParent(toBinaryTree(array, index * 2 + 1));
node.setRightAndUpdateParent(toBinaryTree(array, index * 2 + 2));
return node;
};
return toBinaryTree(Array.from(iterable));
}
}

BinaryTreeNode.RIGHT = RIGHT;
Expand Down
229 changes: 141 additions & 88 deletions src/data-structures/trees/binary-tree-node.spec.js
Original file line number Diff line number Diff line change
@@ -1,114 +1,167 @@
const { BinaryTreeNode } = require('../../index');

const { LEFT, RIGHT } = BinaryTreeNode;

describe('Binary Tree Node', () => {
let treeNode;

beforeEach(() => {
treeNode = new BinaryTreeNode('hola');
});

it('should start with null parent', () => {
expect(treeNode.parent).toBe(null);
});

it('should start with empty metadata', () => {
expect(treeNode.meta).toEqual({});
});

it('should hold a value', () => {
expect(treeNode.value).toBe('hola');
});

it('should have a height 0', () => {
expect(treeNode.height).toBe(0);
});

it('should set/get left node', () => {
expect(treeNode.left).toBe(null);
const newNode = new BinaryTreeNode(1);
treeNode.setLeftAndUpdateParent(newNode);
expect(treeNode.left.value).toBe(1);

expect(newNode.parent).toBe(treeNode);
expect(treeNode.height).toBe(1);
expect(treeNode.balanceFactor).toBe(1);
});

it('should set/get right node', () => {
expect(treeNode.right).toBe(null);
const newNode = new BinaryTreeNode(1);
treeNode.setRightAndUpdateParent(newNode);

expect(treeNode.right.value).toBe(1);
expect(newNode.parent).toBe(treeNode);
expect(treeNode.height).toBe(1);
expect(treeNode.balanceFactor).toBe(-1);
});

describe('Family operations', () => {
let g;
let p;
let u;
let c;
let s;

describe('with instance', () => {
beforeEach(() => {
g = new BinaryTreeNode('grandparent');
p = new BinaryTreeNode('parent');
u = new BinaryTreeNode('uncle');
c = new BinaryTreeNode('child');
s = new BinaryTreeNode('sibling');

g.setRightAndUpdateParent(p);
g.setLeftAndUpdateParent(u);
p.setRightAndUpdateParent(c);
p.setLeftAndUpdateParent(s);
treeNode = new BinaryTreeNode('hola');
});

it('should set heights', () => {
expect(g.height).toBe(2);
expect(g.balanceFactor).toBe(-1);

expect(p.height).toBe(1);
expect(p.balanceFactor).toBe(0);
it('should start with null parent', () => {
expect(treeNode.parent).toBe(null);
});

expect(u.height).toBe(0);
expect(u.balanceFactor).toBe(0);
it('should start with empty metadata', () => {
expect(treeNode.meta).toEqual({});
});

it('should get the sibling', () => {
expect(c.sibling).toBe(s);
expect(p.sibling).toBe(u);
it('should hold a value', () => {
expect(treeNode.value).toBe('hola');
});

it('should set leaf correctly', () => {
expect(c.isLeaf).toBe(true);
expect(u.isLeaf).toBe(true);
expect(p.isLeaf).toBe(false);
expect(g.isLeaf).toBe(false);
it('should have a height 0', () => {
expect(treeNode.height).toBe(0);
});

it('should get null if no sibling', () => {
expect(g.sibling).toBe(null);
it('should set/get left node', () => {
expect(treeNode.left).toBe(null);
const newNode = new BinaryTreeNode(1);
treeNode.setLeftAndUpdateParent(newNode);
expect(treeNode.left.value).toBe(1);

expect(newNode.parent).toBe(treeNode);
expect(treeNode.height).toBe(1);
expect(treeNode.balanceFactor).toBe(1);
});

it('should get the uncle', () => {
expect(c.uncle).toBe(u);
it('should set/get right node', () => {
expect(treeNode.right).toBe(null);
const newNode = new BinaryTreeNode(1);
treeNode.setRightAndUpdateParent(newNode);

expect(treeNode.right.value).toBe(1);
expect(newNode.parent).toBe(treeNode);
expect(treeNode.height).toBe(1);
expect(treeNode.balanceFactor).toBe(-1);
});

it('should get null if no uncle', () => {
expect(g.uncle).toBe(null);
expect(p.uncle).toBe(null);
describe('Family operations', () => {
let g;
let p;
let u;
let c;
let s;

beforeEach(() => {
g = new BinaryTreeNode('grandparent');
p = new BinaryTreeNode('parent');
u = new BinaryTreeNode('uncle');
c = new BinaryTreeNode('child');
s = new BinaryTreeNode('sibling');

g.setRightAndUpdateParent(p);
g.setLeftAndUpdateParent(u);
p.setRightAndUpdateParent(c);
p.setLeftAndUpdateParent(s);
});

it('should set heights', () => {
expect(g.height).toBe(2);
expect(g.balanceFactor).toBe(-1);

expect(p.height).toBe(1);
expect(p.balanceFactor).toBe(0);

expect(u.height).toBe(0);
expect(u.balanceFactor).toBe(0);
});

it('should get the sibling', () => {
expect(c.sibling).toBe(s);
expect(p.sibling).toBe(u);
});

it('should set leaf correctly', () => {
expect(c.isLeaf).toBe(true);
expect(u.isLeaf).toBe(true);
expect(p.isLeaf).toBe(false);
expect(g.isLeaf).toBe(false);
});

it('should get null if no sibling', () => {
expect(g.sibling).toBe(null);
});

it('should get the uncle', () => {
expect(c.uncle).toBe(u);
});

it('should get null if no uncle', () => {
expect(g.uncle).toBe(null);
expect(p.uncle).toBe(null);
});

it('true if is parent left child', () => {
expect(s.isParentLeftChild).toBe(true);
expect(s.isParentRightChild).toBe(false);
});

it('true if is parent left child', () => {
expect(c.isParentLeftChild).toBe(false);
expect(c.isParentRightChild).toBe(true);
});
});
});

it('true if is parent left child', () => {
expect(s.isParentLeftChild).toBe(true);
expect(s.isParentRightChild).toBe(false);
describe('with static methods', () => {
it('should work with null', () => {
const tree = BinaryTreeNode.from();
expect(tree).toEqual(null);
});

it('true if is parent left child', () => {
expect(c.isParentLeftChild).toBe(false);
expect(c.isParentRightChild).toBe(true);
it('should build from array', () => {
/*
0
/ \
1 2
/ \ \
3 5 4
*/
const tree = BinaryTreeNode.from([0, 1, 2, 3, 5, null, 4]);
expect(tree.toValues()).toEqual({
value: 0,
left: 1,
right: 2,
parent: null,
parentSide: null,
});

expect(tree.left.toValues()).toEqual({
value: 1,
left: 3,
right: 5,
parent: 0,
parentSide: LEFT,
});

expect(tree.right.toValues()).toEqual({
value: 2,
left: null,
right: 4,
parent: 0,
parentSide: RIGHT,
});

expect(tree.right.right.toValues()).toEqual({
value: 4,
left: null,
right: null,
parent: 2,
parentSide: RIGHT,
});
});
});
});

0 comments on commit bcb4c28

Please sign in to comment.