kopia lustrzana https://github.com/animator/learn-python
153 wiersze
4.5 KiB
Markdown
153 wiersze
4.5 KiB
Markdown
![]() |
# Hashing with Chaining
|
||
|
|
||
|
In Data Structures and Algorithms, hashing is used to map data of arbitrary size to fixed-size values. A common approach to handle collisions in hashing is **chaining**. In chaining, each slot of the hash table contains a linked list, and all elements that hash to the same slot are stored in that list.
|
||
|
|
||
|
## Points to be Remembered
|
||
|
|
||
|
- **Hash Function**: A function that converts an input (or 'key') into an index in a hash table.
|
||
|
- **Collision**: When two keys hash to the same index.
|
||
|
- **Chaining**: A method to resolve collisions by maintaining a linked list for each hash table slot.
|
||
|
|
||
|
## Real Life Examples of Hashing with Chaining
|
||
|
|
||
|
- **Phone Directory**: Contacts are stored in a hash table where the contact's name is hashed to an index. If multiple names hash to the same index, they are stored in a linked list at that index.
|
||
|
- **Library Catalog**: Books are indexed by their titles. If multiple books have titles that hash to the same index, they are stored in a linked list at that index.
|
||
|
|
||
|
## Applications of Hashing
|
||
|
|
||
|
Hashing is widely used in Computer Science:
|
||
|
|
||
|
- **Database Indexing**
|
||
|
- **Caches** (like CPU caches, web caches)
|
||
|
- **Associative Arrays** (or dictionaries in Python)
|
||
|
- **Sets** (unordered collections of unique elements)
|
||
|
|
||
|
Understanding these applications is essential for Software Development.
|
||
|
|
||
|
## Operations in Hash Table with Chaining
|
||
|
|
||
|
Key operations include:
|
||
|
|
||
|
- **INSERT**: Insert a new element into the hash table.
|
||
|
- **SEARCH**: Find the position of an element in the hash table.
|
||
|
- **DELETE**: Remove an element from the hash table.
|
||
|
|
||
|
## Implementing Hash Table with Chaining in Python
|
||
|
|
||
|
```python
|
||
|
class Node:
|
||
|
def __init__(self, key, value):
|
||
|
self.key = key
|
||
|
self.value = value
|
||
|
self.next = None
|
||
|
|
||
|
class HashTable:
|
||
|
def __init__(self, size):
|
||
|
self.size = size
|
||
|
self.table = [None] * size
|
||
|
|
||
|
def hash_function(self, key):
|
||
|
return key % self.size
|
||
|
|
||
|
def insert(self, key, value):
|
||
|
hash_index = self.hash_function(key)
|
||
|
new_node = Node(key, value)
|
||
|
|
||
|
if self.table[hash_index] is None:
|
||
|
self.table[hash_index] = new_node
|
||
|
else:
|
||
|
current = self.table[hash_index]
|
||
|
while current.next is not None:
|
||
|
current = current.next
|
||
|
current.next = new_node
|
||
|
|
||
|
def search(self, key):
|
||
|
hash_index = self.hash_function(key)
|
||
|
current = self.table[hash_index]
|
||
|
|
||
|
while current is not None:
|
||
|
if current.key == key:
|
||
|
return current.value
|
||
|
current = current.next
|
||
|
|
||
|
return None
|
||
|
|
||
|
def delete(self, key):
|
||
|
hash_index = self.hash_function(key)
|
||
|
current = self.table[hash_index]
|
||
|
prev = None
|
||
|
|
||
|
while current is not None:
|
||
|
if current.key == key:
|
||
|
if prev is None:
|
||
|
self.table[hash_index] = current.next
|
||
|
else:
|
||
|
prev.next = current.next
|
||
|
return True
|
||
|
prev = current
|
||
|
current = current.next
|
||
|
|
||
|
return False
|
||
|
|
||
|
def display(self):
|
||
|
for index, item in enumerate(self.table):
|
||
|
print(f"Index {index}:", end=" ")
|
||
|
current = item
|
||
|
while current is not None:
|
||
|
print(f"({current.key}, {current.value})", end=" -> ")
|
||
|
current = current.next
|
||
|
print("None")
|
||
|
|
||
|
# Example usage
|
||
|
hash_table = HashTable(10)
|
||
|
|
||
|
hash_table.insert(1, 'A')
|
||
|
hash_table.insert(11, 'B')
|
||
|
hash_table.insert(21, 'C')
|
||
|
|
||
|
print("Hash Table after Insert operations:")
|
||
|
hash_table.display()
|
||
|
|
||
|
print("Search operation for key 11:", hash_table.search(11))
|
||
|
|
||
|
hash_table.delete(11)
|
||
|
|
||
|
print("Hash Table after Delete operation:")
|
||
|
hash_table.display()
|
||
|
```
|
||
|
|
||
|
## Output
|
||
|
|
||
|
```markdown
|
||
|
Hash Table after Insert operations:
|
||
|
Index 0: None
|
||
|
Index 1: (1, 'A') -> (11, 'B') -> (21, 'C') -> None
|
||
|
Index 2: None
|
||
|
Index 3: None
|
||
|
Index 4: None
|
||
|
Index 5: None
|
||
|
Index 6: None
|
||
|
Index 7: None
|
||
|
Index 8: None
|
||
|
Index 9: None
|
||
|
|
||
|
Search operation for key 11: B
|
||
|
|
||
|
Hash Table after Delete operation:
|
||
|
Index 0: None
|
||
|
Index 1: (1, 'A') -> (21, 'C') -> None
|
||
|
Index 2: None
|
||
|
Index 3: None
|
||
|
Index 4: None
|
||
|
Index 5: None
|
||
|
Index 6: None
|
||
|
Index 7: None
|
||
|
Index 8: None
|
||
|
Index 9: None
|
||
|
```
|
||
|
|
||
|
## Complexity Analysis
|
||
|
|
||
|
- **Insertion**: Average case O(1), Worst case O(n) when many elements hash to the same slot.
|
||
|
- **Search**: Average case O(1), Worst case O(n) when many elements hash to the same slot.
|
||
|
- **Deletion**: Average case O(1), Worst case O(n) when many elements hash to the same slot.
|