From 9ca3bdc48a21d2806e78b820a617fd61bce6d4bf Mon Sep 17 00:00:00 2001 From: Aliaksei Mazheika Date: Mon, 21 Aug 2023 14:20:31 +0100 Subject: [PATCH] Added tests to hash table --- package.json | 6 +-- src/binary-search-tree/index.ts | 14 +++--- src/hash-table/README.md | 11 ++++ src/hash-table/hash-table.js | 89 --------------------------------- src/hash-table/index.ts | 53 ++++++++++++++++++++ src/hash-table/tests/index.ts | 34 +++++++++++++ src/linked-list/index.ts | 4 +- 7 files changed, 110 insertions(+), 101 deletions(-) delete mode 100644 src/hash-table/hash-table.js create mode 100644 src/hash-table/index.ts create mode 100644 src/hash-table/tests/index.ts diff --git a/package.json b/package.json index 6677e48..dfbc923 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "data-structures", - "version": "1.0.0", + "version": "1.1.0", "description": "A collection of the most famous data structures implemented in Javascript", - "author": "Alexey Mozheyko", + "author": "Aliaksei Mazheika", "scripts": { - "test:unit": "jest --silent", + "test:unit": "jest", "editorconfig:check": "editorconfig-checker --exclude '.git|node_modules|.DS_store'" }, "devDependencies": { diff --git a/src/binary-search-tree/index.ts b/src/binary-search-tree/index.ts index 8ce7dea..039167a 100644 --- a/src/binary-search-tree/index.ts +++ b/src/binary-search-tree/index.ts @@ -17,11 +17,11 @@ class BinarySearchTree implements IBinarySearchTree { constructor(value: number) { this.value = value; - this.left = null; + this.left = null; this.right = null; } - contains(value?: number): boolean { + public contains(value?: number): boolean { if (!value) { return false; } @@ -46,7 +46,7 @@ class BinarySearchTree implements IBinarySearchTree { } } - breadthFirstTraversal() { + public breadthFirstTraversal() { const queue = [this] as BinarySearchTree[]; while (queue.length) { @@ -64,7 +64,7 @@ class BinarySearchTree implements IBinarySearchTree { } } - depthFirstTraversal(order: DepthFirstTraversalOrder) { + public depthFirstTraversal(order: DepthFirstTraversalOrder) { if (order === 'pre-order') { console.log(this.value); } @@ -86,7 +86,7 @@ class BinarySearchTree implements IBinarySearchTree { } } - getMaxVal(): number { + public getMaxVal(): number { if (this.right) { return this.right.getMaxVal(); } @@ -94,7 +94,7 @@ class BinarySearchTree implements IBinarySearchTree { return this.value; } - getMinVal(): number { + public getMinVal(): number { if (this.left) { return this.left.getMinVal(); } @@ -102,7 +102,7 @@ class BinarySearchTree implements IBinarySearchTree { return this.value; } - insert(value: number) { + public insert(value: number) { if (value <= this.value) { if (!this.left) { this.left = new BinarySearchTree(value); diff --git a/src/hash-table/README.md b/src/hash-table/README.md index e69de29..e70d5fe 100644 --- a/src/hash-table/README.md +++ b/src/hash-table/README.md @@ -0,0 +1,11 @@ +# Hash table + +A [hash table](https://en.wikipedia.org/wiki/Hash_table) s a data structure that implements an associative array or dictionary. It is an abstract data type that maps keys to values. +A hash table uses a hash function to compute an index, also called a hash code, into an array of buckets or slots, from which the desired value can be found. + +A hash table implemented here has following methods: + + - `get(key)` - returns value by provided `key`. Returns `null` if no `key` found. + - `set(key, value)` - adds new key/value pair into hash table. + - `remove(key)` - removes key/value pair from hash table by provided `key` and returns `true`. Return `false` if no `key` found. + - `_hash(key)` - private method that transforms `key` into an index. diff --git a/src/hash-table/hash-table.js b/src/hash-table/hash-table.js deleted file mode 100644 index 3cb1beb..0000000 --- a/src/hash-table/hash-table.js +++ /dev/null @@ -1,89 +0,0 @@ -class HashNode { - constructor(key, value, next = null) { - this.key = key; - this.value = value; - this.next = next; - } -} - -class HashTable { - constructor(size) { - this.buckets = new Array(size); - this.numBuckets = size; - } - - get(key) { - const index = this.hash(key); - - if (!this.buckets[index]) { - return null; - } - - let currentNode = this.buckets[index]; - - while (currentNode) { - if (currentNode.key === key) { - return currentNode.value; - } - - currentNode = currentNode.next; - } - - return null; - } - - hash(key) { - const keyLength = key.length; - let total = 0; - - for (let i = 0; i < keyLength; i++) { - total += key.charCodeAt(i); - } - - return total % this.numBuckets; - } - - insert(key, value) { - const index = this.hash(key); - - if (!this.buckets[index]) { - this.buckets[index] = new HashNode(key, value); - } - else if (this.buckets[index].key === key) { - this.buckets[index].value = value; - } - else { - let currentNode = this.buckets[index]; - - while (currentNode.next) { - if (currentNode.next.key === key) { - currentNode.next.value = value; - - return; - } - - currentNode = currentNode.next; - } - - currentNode.next = new HashNode(key, value); - } - } - - retrieveAll() { - let allNodes = []; - - for (let i = 0; i < this.numBuckets; i++) { - let currentNode = this.buckets[i]; - - while (currentNode) { - allNodes.push(currentNode); - - currentNode = currentNode.next; - } - } - - return allNodes; - } -} - -module.exports = HashTable; diff --git a/src/hash-table/index.ts b/src/hash-table/index.ts new file mode 100644 index 0000000..b479df2 --- /dev/null +++ b/src/hash-table/index.ts @@ -0,0 +1,53 @@ +interface IHashTable { + get(key: string): unknown; + set(key: string, value: unknown): void; + remove(key: string): boolean; +} + +class HashTable implements IHashTable { + private table: (Array | undefined)[]; + public size: number; + + constructor(size: number) { + this.table = new Array(size); + this.size = 0; + } + + private hash(key: string): number { + let total = 0; + + for (let i = 0; i < key.length; i++) { + total += key.charCodeAt(i); + } + + return total % this.size; + } + + public get(key: string): unknown { + const index = this.hash(key); + + return this.table[index]?.[1] ?? null; + } + + public set(key: string, value: unknown) { + const index = this.hash(key); + + this.table[index] = [key, value]; + this.size++; + } + + public remove(key: string) { + const index = this.hash(key); + + if (this.table[index]?.length) { + this.table[index] = undefined; + this.size--; + + return true; + } + + return false; + } +} + +export default HashTable; diff --git a/src/hash-table/tests/index.ts b/src/hash-table/tests/index.ts new file mode 100644 index 0000000..8693c32 --- /dev/null +++ b/src/hash-table/tests/index.ts @@ -0,0 +1,34 @@ +import HashTable from '..'; + +/** Test cases on get() and set() method */ +describe('HashTable:', () => { + describe('get() and set() methods', () => { + test('should get correct values', () => { + const hashTable = new HashTable(3); + + hashTable.set("Canada", 300); + hashTable.set("France", 100); + hashTable.set("Spain", 110); + + expect(hashTable.get("Canada")).toBe(300); + expect(hashTable.get("France")).toBe(100); + expect(hashTable.get("Spain")).toBe(110); + expect(hashTable.get("Germany")).toBe(null); + }); + }); + + describe('remove() methods', () => { + test('should remove correct values', () => { + const hashTable = new HashTable(3); + + hashTable.set("Andrew", 300); + hashTable.set("Florence", 100); + hashTable.set("Paul", 110); + + expect(hashTable.remove("Canada")).toBeTruthy(); + expect(hashTable.remove("Florence")).toBeTruthy(); + expect(hashTable.remove("Paul")).toBeTruthy(); + expect(hashTable.remove("Kate")).toBeFalsy(); + }); + }); +}); diff --git a/src/linked-list/index.ts b/src/linked-list/index.ts index d741d3f..35d1fdb 100644 --- a/src/linked-list/index.ts +++ b/src/linked-list/index.ts @@ -17,8 +17,8 @@ class ListNode { constructor(value: unknown, next: ListNode | null, prev: ListNode | null) { this.value = value; - this.next = next; - this.prev = prev; + this.next = next; + this.prev = prev; } }