forked from GuildCrafts/core-data-structures
-
Notifications
You must be signed in to change notification settings - Fork 1
#nifty-bushpig 157: Core Data Structures (Advanced) #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
breyana
wants to merge
2
commits into
empty-branch
Choose a base branch
from
master
base: empty-branch
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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,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') ) | ||
| 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()', () => { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) | ||
|
|
||
| }) | ||
| }) | ||
This file contains hidden or 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,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) | ||
| }) | ||
| }) | ||
|
|
||
| }) |
This file contains hidden or 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,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 | ||
| } | ||
| } |
This file contains hidden or 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,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 | ||
| } | ||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
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 :)