Skip to content
Open

Day 1 #176

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
159 changes: 120 additions & 39 deletions hashtable/hashtable.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ class HashTableEntry:
"""
Linked List hash table key/value pair
"""

def __init__(self, key, value):
self.key = key
self.value = value
Expand All @@ -21,8 +22,12 @@ class HashTable:
"""

def __init__(self, capacity):
# Your code here

if capacity >= MIN_CAPACITY:
self.capacity = capacity
else:
self.capacity = MIN_CAPACITY
self.bucket = [None] * capacity
self.count = 0

def get_num_slots(self):
"""
Expand All @@ -35,7 +40,7 @@ def get_num_slots(self):
Implement this.
"""
# Your code here

return len(self.bucket)

def get_load_factor(self):
"""
Expand All @@ -44,66 +49,122 @@ def get_load_factor(self):
Implement this.
"""
# Your code here

return self.count / self.get_num_slots()

def fnv1(self, key):
"""
FNV-1 Hash, 64-bit

Implement this, and/or DJB2.
"""

# Your code here
prime_32 = 16777619
hash_32 = 2166136261
fnv_prime_64 = 1099511628211 # (in hex: 0x100000001b3)
hash_64 = 14695981039346656037 # (in hex: 0xcbf29ce484222325)

for char in key:
hash_64 = hash_64 * fnv_prime_64
hash_64 = hash_64 ^ ord(char)
return hash

def djb2(self, key):
"""
DJB2 hash, 32-bit

Implement this, and/or FNV-1.
"""
# Your code here

hash = 5381
for x in key:
# shift variable, then add it, then add the ord
hash = ((hash << 5) + hash) + ord(x)
return hash & 0xffffffff

def hash_index(self, key):
"""
Take an arbitrary key and return a valid integer index
between within the storage capacity of the hash table.
"""
#return self.fnv1(key) % self.capacity
# return self.fnv1(key) % self.capacity
return self.djb2(key) % self.capacity

def put(self, key, value):
"""
Store the value with the given key.
# first_day
# index = self.hash_index(key)
# self.bucket[index] = value

# second_day
index = self.hash_index(key) # returns a number
new_node = HashTableEntry(key, value) # returns a node Object
cur_node = self.bucket[index] # returns node Object or None
if self.bucket[index] == None:
# if node at index does NOT exist, then insert new_node at index
self.bucket[index] = new_node
self.count += 1
elif self.bucket[index] is not None and self.bucket[index].key == key:
# if node at index exists, and node.key matches key, replace value at key
self.bucket[index].value = value

elif self.bucket[index] is not None:
# if node at index exits...
while cur_node is not None:
# loop while cur_node exists...
if cur_node.next is None:
# ...if next node is None, then insert node into next index
cur_node.next = new_node
self.count += 1
return cur_node
elif cur_node.next is not None and cur_node.next.key == key:
# ...if next node exists, and next node.key matches, replace value
cur_node.next.value = value
return cur_node.next
else:
# move over to next node, run through the loop again
cur_node = cur_node.next

Hash collisions should be handled with Linked List Chaining.

Implement this.
"""
# Your code here


def delete(self, key):
"""
Remove the value stored with the given key.
# first_day
# index = self.hash_index(key)
# self.bucket[index] = None


# second_day
index = self.hash_index(key) # returns a number
is_traversing = True
cur_node = self.bucket[index] # returns a node Object
prev_node = None

while is_traversing:
# while is_traversing is true
if cur_node.key:
# ...if current node key exists
if cur_node.key == key:
# ...if current node key matches, set current to none
cur_node.value = None
if cur_node.next:
# ...if next node exists, set current node to next node
self.bucket[index] = cur_node.next
cur_node = cur_node.next
else:
self.bucket[index] = None
cur_node = None
else:
return "Error"



Print a warning if the key is not found.

Implement this.
"""
# Your code here
def get(self, key):
# first_day
# index = self.hash_index(key)
# return self.bucket[index]

# second_day
index = self.hash_index(key)
cur_node = self.bucket[index]

def get(self, key):
"""
Retrieve the value stored with the given key.
# if cur_node exists, and the key matches node key: return the node value
if cur_node is not None and cur_node.key == key:
return cur_node.value
else:
while cur_node is not None:
if cur_node.key == key:
return cur_node.value
cur_node = cur_node.next

Returns None if the key is not found.
return None

Implement this.
"""
# Your code here


def resize(self, new_capacity):
Expand All @@ -114,6 +175,26 @@ def resize(self, new_capacity):
Implement this.
"""
# Your code here
oldBucket = self.bucket
# create a new, empty bucket with new_capacity length
self.bucket = [None] * new_capacity
self.count = 0
self.capacity = new_capacity
index = 0

while index < len(oldBucket):
cur_node = oldBucket[index]

if cur_node is not None:
next_node = cur_node.next
cur_node.next = None
self.put(cur_node.key, cur_node.value)
oldBucket[index] = next_node
elif cur_node is None:
# index ONLY increments when cur_node is None
index += 1





Expand Down