Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions spec/binarySearchTree_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import chai, { expect } from 'chai'
import chaiChange from 'chai-change'
import BinarySearchTree from '../src/binarySearchTree'

chai.use(chaiChange)

describe.only('Binary Search Tree', () => {
'use strict'

it('exists', () => {
expect(BinarySearchTree).to.be.a('function')
})

describe('insert()', () => {
it('inserts a node with the specified value into the tree.', () => {
const bst = new BinarySearchTree()
bst.insert(50)
bst.insert(30)
bst.insert(51)
bst.insert(31)
// bst.traverse( (val) => console.log('hello') )

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove comments on a final PR please :)

expect(() => bst.insert(3))
.to.alter(() => bst.count(), { from: 4, to: 5 })
})
})

describe('search()', () => {
const bst = new BinarySearchTree()
bst.insert(50)
bst.insert(30)
bst.insert(51)
bst.insert(31)


it('returns a node object if found.', () => {
expect(bst.search(51)).to.eql({ value: 51, left: null, right: null })
})

it('returns null if not found.', () => {
expect(bst.search(3)).to.be.null
})
})

describe('delete()', () => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test is missing here, not assertion is defined.

const bst = new BinarySearchTree()
bst.insert(50)
bst.insert(30)
bst.insert(51)
bst.insert(31)
bst.insert(15)
bst.remove(50)
console.log(bst)

})
})
97 changes: 97 additions & 0 deletions spec/hashTable_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import chai, { expect, assert } from 'chai'
import chaiChange from 'chai-change'
import HashTable from '../src/hashTable'

chai.use(chaiChange)

describe('Hash Table', () => {
'use strict'

it('exists', () => {
expect(HashTable).to.be.a('function')
})

describe('put()', () => {
it('adds a key-value pair to the hash table', () => {
const hashTable = new HashTable()

expect(() => hashTable.put("name", "Zanzibar"))
.to.alter(() => hashTable.size(), { from: 0, to: 1 })
})
})

describe('hash()', () => {
const hashTable = new HashTable()
let hashedKey = hashTable.hash("name")

it('generates a hash for the key "name"', () => {
expect(hashTable.hash("name")).to.equal(hashedKey)
assert.isNumber(hashedKey, "hashed key is a number")
})
})

describe('get()', () => {
it('returns the data associated with key.', () => {
const hashTable = new HashTable()
hashTable.put("name", "Zanzibar")

expect(hashTable.get("name")).to.eql("Zanzibar")
})
})

describe('contains()', () => {
const hashTable = new HashTable()
hashTable.put("name", "Zanzibar")
hashTable.put("place", "Zimbabwe")
hashTable.put("animal", "Zebra")

it('returns true if the hash table contains the key.', () => {
expect(hashTable.contains("place")).to.be.true
})
it('returns false if the hash table does not contain the key', () => {
expect(hashTable.contains("car")).to.be.false
})
})

describe('iterate()', () => {
it('takes a callback function and passes it each key and value in sequence.',
() => {
const hashTable = new HashTable()
hashTable.put("name", "Zanzibar")
hashTable.put("place", "Zimbabwe")
hashTable.put("animal", "Zebra")
let keyValueArray = []

hashTable.iterate((k, v) => keyValueArray.push(`${k}: ${v}`))

expect(keyValueArray.length)
.to.equal(3)
})
})

describe('remove()', () => {
it('removes a key-value pair by key.', () => {
const hashTable = new HashTable()
hashTable.put("name", "Zanzibar")
hashTable.put("place", "Zimbabwe")
hashTable.put("animal", "Zebra")

expect(() => hashTable.remove("name"))
.to.alter(() => hashTable.size(), { from: 3, to: 2 })
expect(hashTable.get("name"))
.to.be.null
})
})

describe('size()', () => {
it('returns the number of key-value pairs in the hash table.', () => {
const hashTable = new HashTable()
hashTable.put("name", "Zanzibar")
hashTable.put("place", "Zimbabwe")
hashTable.put("animal", "Zebra")

expect(hashTable.size()).to.equal(3)
})
})

})
157 changes: 157 additions & 0 deletions src/binarySearchTree.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
'use strict'

class TreeNode {
constructor(value) {
this.value = value;
this.left = null;
this.right = null;
}

}

export default class BinarySearchTree {
constructor() {
this.root = null;
this.size = 0;
}

insert(value) {
let node = new TreeNode(value);
let current = this.root

if(this.root === null) {
this.root = node;
this.size++

} else {
while( current !== null ){
if (node.value < current.value) {
if (current.left === null) {
current.left = node;
this.size++;
break
} else {
current = current.left
}
} else {
if (current.right === null) {
current.right = node;
this.size++;
break
} else {
current = current.right
}
}
}
}
}

search(value) {
if (this.root === null) {
return null
}
if (this.root.value === value) {
return this.root
}
let current = this.root
while (current) {
if (current.value > value) {
if (current.left === null) {
return null
} else if (current.left.value === value) {
return current.left
} else {
current = current.left
}
} else if (current.value < value) {
if (current.right === null) {
return null
} else if (current.right.value === value) {
return current.right
} else {
current = current.right
}
}
}
}

findParent(value) {
if (this.root === null) {
return null
}
if (this.root.value === value) {
return this.root
}
let current = this.root
while (current) {
if (current.value > value) {
if (current.left === null) {
return null
} else if (current.left.value === value) {
return current
} else {
current = current.left
}
} else if (current.value < value) {
if (current.right === null) {
return null
} else if (current.right.value === value) {
return current
} else {
current = current.right
}
}
}
}

remove(value) {
if (this.root === null) {
return
}

let parent = this.findParent(value)
let toDelete = this.search(value)
// find parent of value
// find node that contains value
// if that node's left child has a right subtree
if (toDelete.left === null && toDelete.right === null) {
if (parent.right.value === toDelete.value) {
parent.right = null
} else {
parent.left = null
}
} else if (toDelete.left.right !== null) {
//traverse to rightmost leaf
let current = toDelete.left.right
while (current.right != null) {
current = current.right
}
//swap values of node and leaf
parent.value = current.value
parent.right = null
// if that node's left child has no right subtree,
} else if (toDelete.left.right === null) {
// then node's right subtree becomes left child's right subtree
toDelete.left.right = toDelete.right
// parent points to left child
parent.left = toDelete.left
} else if (!toDelete.left){
parent.right = toDelete.right.right
}

this.size--
}

traverse(func, node=this.root) {
if(node !== null) {
this.traverse(func, node.left);
func(node.value)
console.log(node.value);
this.traverse(func, node.right)
}
}

count() {
return this.size
}
}
66 changes: 66 additions & 0 deletions src/hashTable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
'use strict'

class Node {
constructor(key, value) {
this.key = key;
this.value = value
this.next = null;
}
}

export default class HashTable {
constructor() {
this.list = new Array(137);
this.count = 0
}

hash(key) {
let prime = 37
let total = 0
for (var i = 0; i < key.length; i++) {
total += prime * total + key.charCodeAt(i)
}
total = total % this.list.length
return total
}

put(key, value) {
let hashedKey = this.hash(key)
this.list[hashedKey] = new Node(key, value)
this.count++
}

get(key) {
let hashedKey = this.hash(key)
if(!this.list[hashedKey]) {
return null
}
return this.list[hashedKey].value
}

contains(key) {
let hashedKey = this.hash(key)
if (!this.list[hashedKey]) {
return false
}
return this.list[hashedKey].key === key ? true : false
}

iterate(func) {
this.list.forEach((elem, index) => {
if (elem) {
func(elem.key, elem.value)
}
})
}

remove(key) {
let hashedKey = this.hash(key)
delete this.list[hashedKey]
this.count--
}

size() {
return this.count
}
}