Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
546 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
|
||
interface binaryTreeNode { | ||
minValue(): any, | ||
} | ||
|
||
interface binarySearchTree { | ||
root() : binaryTreeNode, | ||
add(item: any) : binarySearchTree, | ||
search(item: any) : boolean, | ||
remove(item: any) : binarySearchTree, | ||
preOrderTraversal(fn: (item: binaryTreeNode) => void) : void, | ||
inOrderTraversal(fn: (item: binaryTreeNode) => void) : void, | ||
postOrderTraversal(fn: (item: binaryTreeNode) => void) : void, | ||
size() : number, | ||
isEqual(node: binarySearchTree): boolean | ||
} | ||
|
||
const binaryTreeNode = (item, leftItem?, rightItem?) => { | ||
|
||
const prototype: binaryTreeNode = { | ||
minValue() { | ||
if (this.left === null) { | ||
return this._data | ||
} else { | ||
return this.left.minValue() | ||
} | ||
}, | ||
} | ||
|
||
return Object.assign(Object.create(prototype), { | ||
_data: item, | ||
left: leftItem || null, | ||
right: rightItem || null | ||
}) | ||
} | ||
|
||
const tree = () => { | ||
|
||
const prototype: binarySearchTree = { | ||
|
||
root() { | ||
return this._root | ||
}, | ||
|
||
add(item) { | ||
const node = binaryTreeNode(item) | ||
if (!this.root()) { | ||
this._root = node | ||
return this | ||
} | ||
|
||
let current = this.root() | ||
|
||
while (current) { | ||
if (node._data < current._data) { | ||
if (!current.left) { | ||
current.left = node | ||
break | ||
} | ||
current = current.left | ||
} else if (node._data > current._data) { | ||
if (!current.right) { | ||
current.right = node | ||
break | ||
} | ||
current = current.right | ||
} else { | ||
break | ||
} | ||
} | ||
return this | ||
}, | ||
|
||
search(item) { | ||
const node = binaryTreeNode(item) | ||
|
||
let current = this.root() | ||
while (current) { | ||
if (current._data === node._data) { | ||
return true | ||
} | ||
if (current._data < node._data) { | ||
current = current.right | ||
} else { | ||
current = current.left | ||
} | ||
} | ||
return false | ||
}, | ||
|
||
remove(item) { | ||
const _remove = (node, item) => { | ||
if (!node) { | ||
return null | ||
} | ||
if (node._data === item) { | ||
|
||
if (!node.left && !node.right) { | ||
return null | ||
} | ||
if (!node.left) { | ||
return node.right | ||
} | ||
if (!node.right) { | ||
return node.left | ||
} | ||
|
||
// if the node has 2 children | ||
const temp = node.right.minValue() | ||
node._data = temp._data | ||
node.right = _remove(node.right, temp) | ||
return node | ||
|
||
} else if (node._data < item) { | ||
node.right = _remove(node.right, item) | ||
return node | ||
} else { | ||
node.left = _remove(node.left, item) | ||
return node | ||
} | ||
} | ||
|
||
this._root = _remove(this.root(), item) | ||
return this | ||
}, | ||
|
||
preOrderTraversal(fn) { | ||
const _preOrderTraversal = (node, fn) => { | ||
if (node) { | ||
fn(node) | ||
_preOrderTraversal(node.left, fn) | ||
_preOrderTraversal(node.right, fn) | ||
} | ||
} | ||
_preOrderTraversal(this.root(), fn) | ||
}, | ||
|
||
inOrderTraversal(fn) { | ||
const _inOrderTraversal = (node, fn) => { | ||
if (node) { | ||
_inOrderTraversal(node.left, fn) | ||
fn(node) | ||
_inOrderTraversal(node.right, fn) | ||
} | ||
} | ||
_inOrderTraversal(this.root(), fn) | ||
}, | ||
|
||
postOrderTraversal(fn) { | ||
const _postOrderTraversal = (node, fn) => { | ||
if (node) { | ||
_postOrderTraversal(node.left, fn) | ||
_postOrderTraversal(node.right, fn) | ||
fn(node) | ||
} | ||
} | ||
_postOrderTraversal(this.root(), fn) | ||
}, | ||
|
||
size() { | ||
let size = 0 | ||
this.preOrderTraversal(() => { size++ }) | ||
return size | ||
}, | ||
|
||
isEqual(other) { | ||
const _equal = (x, y) => { | ||
if (!x || !y) { | ||
return false | ||
} | ||
if (x._data === y._data) { | ||
if (!x.left && !y.left && !x.right && !y.right) { | ||
return true | ||
} else if (x.left && y.left && x.right && y.right) { | ||
return _equal(x.left, y.left) && _equal(x.right, y.right) | ||
} else if (x.left && y.left && !x.right && !y.right) { | ||
return _equal(x.left, y.left) | ||
} else if (!x.left && !y.left && x.right && y.right) { | ||
return _equal(x.right, y.right) | ||
} else { | ||
return false | ||
} | ||
} else { | ||
return false | ||
} | ||
} | ||
return _equal(this.root(), other.root()) | ||
} | ||
} | ||
|
||
return Object.assign(Object.create(prototype), { _root: null }) | ||
|
||
} | ||
|
||
export default tree |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
|
||
import * as _ from 'lodash' | ||
|
||
interface graphType { | ||
addNode(item: any): void | ||
removeNode(item: any): void | ||
addEdge(n1: any, n2: any): void | ||
removeEdge(n1: any, n2: any): void | ||
traverseDFS(node: any, fn: (item: any) => void ): void | ||
traverseBFS(node: any, fn: (item: any) => void ): void | ||
} | ||
|
||
const graph = () => { | ||
const prototype: graphType = { | ||
|
||
addNode(item) { | ||
this.nodes.push(item) | ||
this.edges[item] = [] | ||
}, | ||
|
||
removeNode(item) { | ||
this.nodes = this.nodes.filter(node => { | ||
return node != item | ||
}) | ||
|
||
while (this.edges[item].length) { | ||
let adjacentNode = this.edges[item].pop() | ||
this.removeEdge(item, adjacentNode) | ||
} | ||
}, | ||
|
||
addEdge(n1, n2) { | ||
this.edges[n1].push(n2) | ||
this.edges[n2].push(n1) | ||
this.numberOfEdges++ | ||
}, | ||
|
||
removeEdge(n1, n2) { | ||
if (this.edges[n1]) { | ||
this.edges[n1] = this.edges[n1].filter(node => { | ||
return node != n2 | ||
}) | ||
} | ||
if (this.edges[n2]) { | ||
this.edges[n2] = this.edges[n2].filter(node => { | ||
return node != n1 | ||
}) | ||
} | ||
}, | ||
|
||
traverseDFS(node, fn) { | ||
|
||
if (this.nodes.indexOf(node) === -1) { | ||
throw new Error('Node not in graph') | ||
} | ||
|
||
const _dfs = (node, visitedNodes, fn) => { | ||
visitedNodes[node] = true | ||
if (this.edges[node] !== undefined) { | ||
fn(node) | ||
} | ||
this.edges[node].forEach(adjNode => { | ||
if (!visitedNodes[adjNode]) { | ||
this._dfs(adjNode, visitedNodes, fn) | ||
} | ||
}) | ||
} | ||
|
||
_dfs(node, {}, fn) | ||
|
||
}, | ||
|
||
traverseBFS(node, fn) { | ||
|
||
if (this.nodes.indexOf(node) === -1) { | ||
throw new Error('Node not in graph') | ||
} | ||
|
||
const queue = [node] | ||
const visitedNodes = {} | ||
visitedNodes[node] = true | ||
|
||
while (queue.length) { | ||
let currNode = queue.shift() | ||
fn(currNode) | ||
this.edges[currNode].forEach(adjNode => { | ||
if (!visitedNodes[adjNode]) { | ||
visitedNodes[adjNode] = true | ||
queue.push(adjNode) | ||
} | ||
}) | ||
} | ||
} | ||
} | ||
|
||
return Object.assign(Object.create(prototype), { | ||
nodes: [], | ||
edges: {}, | ||
numberOfEdges: 0 | ||
}) | ||
} | ||
|
||
export default graph |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
|
||
interface queueType { | ||
length(): number | ||
enqueue(item: any): queueType | ||
dequeue(item: any): any | ||
peek(): any | ||
} | ||
|
||
const queue = () => { | ||
const prototype: queueType = { | ||
length() { | ||
return this._queue.length | ||
}, | ||
|
||
enqueue(item) { | ||
this._queue.push(item) | ||
return this | ||
}, | ||
|
||
dequeue(item) { | ||
if (this.length() <= 0) { | ||
throw new Error('Queue is empty') | ||
} | ||
return this._queue.shift() | ||
}, | ||
|
||
peek() { | ||
if (this.length() <= 0) { | ||
throw new Error('Queue is empty') | ||
} | ||
return this._queue[0] | ||
} | ||
} | ||
|
||
return Object.assign(Object.create(prototype), { _queue: [] }) | ||
} | ||
|
||
export default queue |
Oops, something went wrong.