initial commit
This commit is contained in:
95
data-structures/binary-tree.js
Normal file
95
data-structures/binary-tree.js
Normal file
@ -0,0 +1,95 @@
|
||||
'use strict';
|
||||
|
||||
import _ from '../utils';
|
||||
|
||||
class Node {
|
||||
constructor(value) {
|
||||
this.value = value;
|
||||
this.right = null;
|
||||
this.left = null;
|
||||
}
|
||||
}
|
||||
|
||||
class BinaryTree {
|
||||
constructor(value) {
|
||||
this.root = new Node(value);
|
||||
this.length = 1;
|
||||
}
|
||||
|
||||
search(key, node = this.root) {
|
||||
if (!node || node.value === key) {
|
||||
return node;
|
||||
} else if (node.value > key) {
|
||||
return this.search(key, node.left);
|
||||
} else {
|
||||
return this.search(key, node.right);
|
||||
}
|
||||
}
|
||||
|
||||
insert(value, node = this.root, parent = null, dir) {
|
||||
if (!node) {
|
||||
parent[dir] = new Node(value);
|
||||
} else if (node.value > value) {
|
||||
this.insert(value, node.left, node, 'left');
|
||||
} else {
|
||||
this.insert(value, node.right, node, 'right');
|
||||
}
|
||||
}
|
||||
|
||||
remove(value, node = this.root, parent = null) {
|
||||
if (!node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// specified parent means we're recursing to delete, and
|
||||
// checking has been already done
|
||||
if (node.value === value || parent) {
|
||||
|
||||
// number of children, !! converts to boolean, + converts to number
|
||||
// false yields 0, true yields 1
|
||||
const children = +!!node.left + +!!node.right;
|
||||
if (!children) {
|
||||
parent.right = null;
|
||||
} else if (children === 1) {
|
||||
node = node.left || node.right;
|
||||
} else {
|
||||
node.value = node.right.value;
|
||||
return this.remove(value, node.right, node, true);
|
||||
}
|
||||
} else if (node.value > value) {
|
||||
return this.remove(value, node.left);
|
||||
} else {
|
||||
return this.remove(value, node.right);
|
||||
}
|
||||
}
|
||||
// in-order
|
||||
traverse(cb, node = this.root) {
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
|
||||
// left
|
||||
this.traverse(cb, node.left);
|
||||
// parent
|
||||
cb(node.value);
|
||||
// right
|
||||
this.traverse(cb, node.right);
|
||||
}
|
||||
}
|
||||
|
||||
let test = new BinaryTree(10);
|
||||
|
||||
test.insert(6);
|
||||
test.insert(18);
|
||||
test.insert(4);
|
||||
test.insert(8);
|
||||
test.insert(15);
|
||||
test.insert(21);
|
||||
|
||||
_.inspect(test);
|
||||
|
||||
_.log('Traverse: ');
|
||||
|
||||
test.traverse(value => {
|
||||
_.print(value + ' ');
|
||||
});
|
144
data-structures/linked-lists.js
Normal file
144
data-structures/linked-lists.js
Normal file
@ -0,0 +1,144 @@
|
||||
'use strict';
|
||||
|
||||
import _ from '../utils';
|
||||
|
||||
export class Node {
|
||||
constructor(value, next = null) {
|
||||
this.value = value;
|
||||
this.next = next;
|
||||
}
|
||||
}
|
||||
|
||||
export class List {
|
||||
constructor(root) {
|
||||
this.root = root;
|
||||
this.length = 1;
|
||||
}
|
||||
|
||||
append(value) {
|
||||
let node = this.root;
|
||||
|
||||
while (node.next !== null) {
|
||||
node = node.next;
|
||||
}
|
||||
|
||||
this.length++;
|
||||
let newNode = new Node(value);
|
||||
node.next = newNode;
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
||||
delete(value, node = this.root) {
|
||||
if (node === this.root && node.value === value) {
|
||||
this.root = this.root.next;
|
||||
return;
|
||||
}
|
||||
|
||||
while (node.next) {
|
||||
if (node.next.value === value) {
|
||||
node.next = node.next.next;
|
||||
this.length--;
|
||||
}
|
||||
node = node.next;
|
||||
}
|
||||
}
|
||||
|
||||
// Cracking the Coding Interview challenges
|
||||
deleteDuplicates() {
|
||||
let node = this.root;
|
||||
|
||||
do {
|
||||
this.delete(node.value, node.next);
|
||||
node = node.next;
|
||||
} while (node.next !== null)
|
||||
}
|
||||
|
||||
last(n) {
|
||||
let target = this.length - n;
|
||||
|
||||
let i = 0;
|
||||
let node = this.root;
|
||||
|
||||
while (i < target && node.next !== null) {
|
||||
node = node.next;
|
||||
i++;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
partition(x) {
|
||||
let less = [],
|
||||
greater = [];
|
||||
|
||||
let node = this.root;
|
||||
|
||||
while (node !== null) {
|
||||
if (node.value < x) {
|
||||
less.push(node.value);
|
||||
} else {
|
||||
greater.push(node.value);
|
||||
}
|
||||
|
||||
node = node.next;
|
||||
}
|
||||
|
||||
this.root = new Node(less[0]);
|
||||
less.slice(1).concat(greater).reduce((a, b) => {
|
||||
a.next = new Node(b);
|
||||
return a.next;
|
||||
}, this.root);
|
||||
}
|
||||
}
|
||||
|
||||
// Cracking the Coding Interview 2.5
|
||||
// Numbers are reversed (617 == 7 -> 1 -> 6 )
|
||||
const addLists = (first, last) => {
|
||||
let num = 0;
|
||||
|
||||
let nodes = [first.root, last.root];
|
||||
let place = 1;
|
||||
while (nodes[0] !== null) {
|
||||
let currentSum = (nodes[0].value + nodes[1].value) * place;
|
||||
place *= 10;
|
||||
|
||||
num += currentSum;
|
||||
|
||||
nodes = [nodes[0].next, nodes[1].next];
|
||||
}
|
||||
|
||||
return num;
|
||||
};
|
||||
|
||||
let test = new List(new Node(10, new Node(5)));
|
||||
|
||||
test.append(20);
|
||||
test.append(8);
|
||||
|
||||
test.delete(10);
|
||||
test.delete(20);
|
||||
|
||||
// Test deleteDuplicates
|
||||
test.append(21);
|
||||
let testNode = test.append(32);
|
||||
test.append(21);
|
||||
test.append(42);
|
||||
test.append(21);
|
||||
test.append(7);
|
||||
|
||||
test.deleteDuplicates();
|
||||
|
||||
// Test last-nth
|
||||
_.log(test.last(2).value === 42);
|
||||
|
||||
// Test partition
|
||||
_.log('Partition around 8');
|
||||
test.partition(8);
|
||||
|
||||
_.log('Sum 7 -> 1 -> 6 AND 5 -> 9 -> 2');
|
||||
let n1 = new List(new Node(7, new Node(1, new Node(6))));
|
||||
let n2 = new List(new Node(5, new Node(9, new Node(2))));
|
||||
_.log(addLists(n1, n2) === 912);
|
||||
|
||||
_.inspect(test);
|
11
data-structures/tests/linked-lists.js
Normal file
11
data-structures/tests/linked-lists.js
Normal file
@ -0,0 +1,11 @@
|
||||
import chai from 'chai';
|
||||
import {Node, List} from '../linked-lists';
|
||||
|
||||
chai.should();
|
||||
|
||||
test('Constructing new Lists', () => {
|
||||
let list = new List(new Node(10, new Node(5)));
|
||||
|
||||
list.root.value.should.equal(10);
|
||||
list.root.next.value.should.equal(5);
|
||||
});
|
38
data-structures/tests/trie.js
Normal file
38
data-structures/tests/trie.js
Normal file
@ -0,0 +1,38 @@
|
||||
import chai from 'chai';
|
||||
import {Node, Trie} from '../trie';
|
||||
|
||||
chai.should();
|
||||
|
||||
test('Construct new Trie', () => {
|
||||
let trie = new Trie();
|
||||
|
||||
trie.root.children.length.should.equal(0);
|
||||
});
|
||||
|
||||
test('Add new parent values', () => {
|
||||
let trie = new Trie();
|
||||
|
||||
trie.add('a');
|
||||
trie.add('b');
|
||||
trie.add('c');
|
||||
trie.add('t');
|
||||
|
||||
trie.root.children.length.should.equal(4);
|
||||
});
|
||||
|
||||
test('Adding values with existing parents', () => {
|
||||
let trie = new Trie();
|
||||
|
||||
trie.add('a');
|
||||
trie.add('ab');
|
||||
trie.add('aba');
|
||||
trie.add('abas');
|
||||
|
||||
let parent = trie.root;
|
||||
for (let i = 0; i < 3; i++) {
|
||||
parent.children.length.should.equal(1);
|
||||
parent = parent.children[0];
|
||||
}
|
||||
|
||||
parent.children.length.should.equal(0);
|
||||
});
|
28
data-structures/trie.js
Normal file
28
data-structures/trie.js
Normal file
@ -0,0 +1,28 @@
|
||||
'use strict';
|
||||
|
||||
import _ from '../utils';
|
||||
|
||||
export class Node {
|
||||
constructor(value) {
|
||||
this.value = value;
|
||||
this.children = [];
|
||||
}
|
||||
}
|
||||
|
||||
export class Trie {
|
||||
constructor() {
|
||||
this.root = new Node();
|
||||
}
|
||||
|
||||
add(value, node = this.root, iteration = 0) {
|
||||
let parent = node.children.find(n => {
|
||||
return n.value[iteration] === value[iteration];
|
||||
});
|
||||
|
||||
if (parent) {
|
||||
this.add(value, parent, iteration + 1);
|
||||
} else {
|
||||
node.children.push(new Node(value));
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user