Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[DEV] Implementation of Hash Table Data Structure #1627

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
miladsade96 wants to merge 5 commits into TheAlgorithms:master
base: master
Choose a base branch
Loading
from miladsade96:devHashTable
Open
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Implementing HashTable class
  • Loading branch information
miladsade96 committed Mar 1, 2024
commit 0089b701eda70524fa36e9602f2a56683ba1bd43
76 changes: 76 additions & 0 deletions Data-Structures/HashTable/HashTable.js
View file Open in desktop
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
export default class HashTable {
constructor(limit = 100) {
Copy link
Collaborator

@appgurueu appgurueu Mar 2, 2024

Choose a reason for hiding this comment

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

100 seems very arbitrary. I'd force the user to choose for a fixed-size hash table. (I'd also make it clear that this is a fixed-size hash table (with dynamically grown buckets) as opposed to a dynamic hash table. In particular, a fixed-size hash table can't guarantee expected O(1) operations.)

limit is also a slightly misleading name: This is not a hard limit, just a hash table "size". If you insert more elements, you will just get worse performance as your buckets fill up.

this.storage = new Array(limit)
Copy link
Collaborator

@appgurueu appgurueu Mar 2, 2024

Choose a reason for hiding this comment

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

It would be helpful to call this property this.#buckets (it should also be private).

this.limit = limit
Copy link
Collaborator

@appgurueu appgurueu Mar 2, 2024

Choose a reason for hiding this comment

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

This field is redundant with this.buckets.length.

}

_hash(key, max) {
Copy link
Collaborator

@appgurueu appgurueu Mar 2, 2024

Choose a reason for hiding this comment

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

Use the # syntax for private properties. The max parameter is also unnecessary; you can just get it as this.storage.length instead.

let hash = 0
for (let i = 0; i < key.length; i++) hash += key.charCodeAt(i)
return hash % max
}

set(key, value) {
const index = this._hash(key, this.limit)
if (this.storage[index] === undefined) this.storage[index] = [[key, value]]
Copy link
Collaborator

@appgurueu appgurueu Mar 2, 2024

Choose a reason for hiding this comment

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

Use an object {key, value} here for better readability (s.t. instead of [0] and [1], you can do .key and .value respectively). You could consider introducing a class Entry or Pair that stores a key-value pair for this.

else {
let inserted = false
for (let i = 0; i < this.storage[index].length; i++) {
Copy link
Collaborator

@appgurueu appgurueu Mar 2, 2024

Choose a reason for hiding this comment

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

Use a for-of loop here: for (const entry of this.storage[index]).

if (this.storage[index][i][0] === key) {
this.storage[index][i][1] = value
inserted = true
Copy link
Collaborator

@appgurueu appgurueu Mar 2, 2024

Choose a reason for hiding this comment

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

Just early return here. Then you don't need the inserted variable, and you will be more efficient (by not doing any further loop iterations).

}
}
if (inserted === false) this.storage[index].push([key, value])
}
}

// Get a value from the hash table
get(key) {
const index = this._hash(key, this.limit)
if (this.storage[index] === undefined) return undefined
else {
for (let i = 0; i < this.storage[index].length; i++) {
Copy link
Collaborator

@appgurueu appgurueu Mar 2, 2024

Choose a reason for hiding this comment

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

Use a for-of loop.

if (this.storage[index][i][0] === key) return this.storage[index][i][1]
}
}
}

remove(key) {
const index = this._hash(key, this.limit)
if (this.storage[index]) {
Copy link
Collaborator

@appgurueu appgurueu Mar 2, 2024

Choose a reason for hiding this comment

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

I'd use an early return here: const bucket = this.storage[index]; if (!bucket) return (empty / undefined bucket). Then you don't need to indent the rest of the function.

if (
this.storage[index].length === 1 &&
this.storage[index][0][0] === key
) {
delete this.storage[index]
} else {
for (let i = 0; i < this.storage[index].length; i++) {
if (this.storage[index][i][0] === key) delete this.storage[index][i]
Copy link
Collaborator

@appgurueu appgurueu Mar 2, 2024

Choose a reason for hiding this comment

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

You're creating an array with holes here. I think this is rather dirty; it results in suboptimal time complexities (deleted items negatively affecting the time it takes to search a bucket).

It would be cleaner to just take an entry from the end, swap the entry to be deleted with that, then pop the entry from the end.

}
}
}
}

has(key) {
const index = this._hash(key, this.limit)
if (this.storage[index]) {
for (let i = 0; i < this.storage[index].length; i++) {
if (this.storage[index][i][0] === key) return true
}
}
return false
}

printTable() {
Copy link
Collaborator

@appgurueu appgurueu Mar 2, 2024

Choose a reason for hiding this comment

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

I don't think "print" helpers are good design. A debugger, or even just JSON.stringify, work just as well for inspecting values.

A better abstraction would be an "entries"-like method to iterate over all the key-value-pairs.

for (let i = 0; i < this.storage.length; i++) {
if (this.storage[i] !== undefined)
console.log(`Bucket ${i}: ${JSON.stringify(this.storage[i])}`)
else console.log(`Bucket ${i} Empty`)
}
}

clear() {
this.storage = new Array(this.limit)
}
}

AltStyle によって変換されたページ (->オリジナル) /