Open In App

Program for hashing with chaining

Improve
Improve
Like Article
Like
Save
Share
Report

In hashing there is a hash function that maps keys to some values. But these hashing functions may lead to a collision that is two or more keys are mapped to same value. Chain hashing avoids collision. The idea is to make each cell of hash table point to a linked list of records that have same hash function value.

Let’s create a hash function, such that our hash table has ‘N’ number of buckets. 

To insert a node into the hash table, we need to find the hash index for the given key. And it could be calculated using the hash function. 

Example: hashIndex = key % noOfBuckets
Insert: Move to the bucket corresponding to the above-calculated hash index and insert the new node at the end of the list.
Delete: To delete a node from hash table, calculate the hash index for the key, move to the bucket corresponding to the calculated hash index, and search the list in the current bucket to find and remove the node with the given key (if found).  

Please refer Hashing | Set 2 (Separate Chaining) for details.
We use a list in C++ which is internally implemented as linked list (Faster insertion and deletion).

Method – 1 :

This method has not concept of rehashing. It only has a fixed size array i.e. fixed numbers of buckets.

CPP




// CPP program to implement hashing with chaining
#include<bits/stdc++.h>
using namespace std;
 
class Hash
{
    int BUCKET;    // No. of buckets
 
    // Pointer to an array containing buckets
    list<int> *table;
public:
    Hash(int V);  // Constructor
 
    // inserts a key into hash table
    void insertItem(int x);
 
    // deletes a key from hash table
    void deleteItem(int key);
 
    // hash function to map values to key
    int hashFunction(int x) {
        return (x % BUCKET);
    }
 
    void displayHash();
};
 
Hash::Hash(int b)
{
    this->BUCKET = b;
    table = new list<int>[BUCKET];
}
 
void Hash::insertItem(int key)
{
    int index = hashFunction(key);
    table[index].push_back(key);
}
 
void Hash::deleteItem(int key)
{
  // get the hash index of key
  int index = hashFunction(key);
 
  // find the key in (index)th list
  list <int> :: iterator i;
  for (i = table[index].begin();
           i != table[index].end(); i++) {
    if (*i == key)
      break;
  }
 
  // if key is found in hash table, remove it
  if (i != table[index].end())
    table[index].erase(i);
}
 
// function to display hash table
void Hash::displayHash() {
  for (int i = 0; i < BUCKET; i++) {
    cout << i;
    for (auto x : table[i])
      cout << " --> " << x;
    cout << endl;
  }
}
 
// Driver program
int main()
{
  // array that contains keys to be mapped
  int a[] = {15, 11, 27, 8, 12};
  int n = sizeof(a)/sizeof(a[0]);
 
  // insert the keys into the hash table
  Hash h(7);   // 7 is count of buckets in
               // hash table
  for (int i = 0; i < n; i++)
    h.insertItem(a[i]); 
 
  // delete 12 from hash table
  h.deleteItem(12);
 
  // display the Hash table
  h.displayHash();
 
  return 0;
}


Java




import java.util.ArrayList;
 
public class Hash {
    // Number of buckets
    private final int bucket;
    // Hash table of size bucket
    private final ArrayList<Integer>[] table;
 
    public Hash(int bucket)
    {
        this.bucket = bucket;
        this.table = new ArrayList[bucket];
        for (int i = 0; i < bucket; i++) {
            table[i] = new ArrayList<>();
        }
    }
 
    // hash function to map values to key
    public int hashFunction(int key)
    {
        return (key % bucket);
    }
 
    public void insertItem(int key)
    {
        // get the hash index of key
        int index = hashFunction(key);
        // insert key into hash table at that index
        table[index].add(key);
    }
 
    public void deleteItem(int key)
    {
        // get the hash index of key
        int index = hashFunction(key);
 
        // Check if key is in hash table
        if (!table[index].contains(key)) {
            return;
        }
 
        // delete the key from hash table
        table[index].remove(Integer.valueOf(key));
    }
 
    // function to display hash table
    public void displayHash()
    {
        for (int i = 0; i < bucket; i++) {
            System.out.print(i);
            for (int x : table[i]) {
                System.out.print(" --> " + x);
            }
            System.out.println();
        }
    }
 
    // Drive Program
    public static void main(String[] args)
    {
        // array that contains keys to be mapped
        int[] a = { 15, 11, 27, 8, 12 };
 
        // Create a empty has of BUCKET_SIZE
        Hash h = new Hash(7);
 
        // insert the keys into the hash table
        for (int x : a) {
            h.insertItem(x);
        }
 
        // delete 12 from the hash table
        h.deleteItem(12);
 
        // Display the hash table
        h.displayHash();
    }
}


Python3




# Python3 program to implement hashing with chaining
BUCKET_SIZE = 7
 
 
class Hash(object):
    def __init__(self, bucket):
        # Number of buckets
        self.__bucket = bucket
        # Hash table of size bucket
        self.__table = [[] for _ in range(bucket)]
 
    # hash function to map values to key
    def hashFunction(self, key):
        return (key % self.__bucket)
 
    def insertItem(self, key):
        # get the hash index of key
        index = self.hashFunction(key)
        self.__table[index].append(key)
 
    def deleteItem(self, key):
        # get the hash index of key
        index = self.hashFunction(key)
 
        # Check the key in the hash table
        if key not in self.__table[index]:
            return
 
        # delete the key from hash table
        self.__table[index].remove(key)
 
    # function to display hash table
    def displayHash(self):
        for i in range(self.__bucket):
            print("[%d]" % i, end='')
            for x in self.__table[i]:
                print(" --> %d" % x, end='')
            print()
 
 
# Drive Program
if __name__ == "__main__":
    # array that contains keys to be mapped
    a = [15, 11, 27, 8, 12]
 
    # Create a empty has of BUCKET_SIZE
    h = Hash(BUCKET_SIZE)
 
    # insert the keys into the hash table
    for x in a:
        h.insertItem(x)
 
    # delete 12 from the hash table
    h.deleteItem(x)
    # Display the hash table
    h.displayHash()


C#




using System;
using System.Collections.Generic;
 
class Hash
{
    int BUCKET; // No. of buckets
 
    // List of integers to store values
    List<int>[] table;
 
    public Hash(int V)
    {
        this.BUCKET = V;
        table = new List<int>[BUCKET];
        for (int i = 0; i < BUCKET; i++)
            table[i] = new List<int>();
    }
 
    // Hash function to map values to key
    int hashFunction(int x)
    {
        return (x % BUCKET);
    }
 
    // Inserts a key into the hash table
    public void insertItem(int key)
    {
        int index = hashFunction(key);
        table[index].Add(key);
    }
 
    // Deletes a key from the hash table
    public void deleteItem(int key)
    {
        int index = hashFunction(key);
        table[index].Remove(key);
    }
 
    // Displays the hash table
    public void displayHash()
    {
        for (int i = 0; i < BUCKET; i++)
        {
            Console.Write(i + " --> ");
            foreach (int x in table[i])
                Console.Write(x + " ");
            Console.WriteLine();
        }
    }
}
 
class Program
{
    static void Main(string[] args)
    {
        // Array that contains keys to be mapped
        int[] a = { 15, 11, 27, 8, 12 };
        int n = a.Length;
 
        // Insert the keys into the hash table
        Hash h = new Hash(7); // 7 is the count of buckets in the hash table
        for (int i = 0; i < n; i++)
            h.insertItem(a[i]);
 
        // Delete 12 from the hash table
        h.deleteItem(12);
 
        // Display the hash table
        h.displayHash();
    }
}


Javascript




class Hash {
    constructor(V) {
        this.BUCKET = V; // No. of buckets
        this.table = new Array(V); // Pointer to an array containing buckets
        for (let i = 0; i < V; i++) {
            this.table[i] = new Array();
        }
    }
 
    // inserts a key into hash table
    insertItem(x) {
        const index = this.hashFunction(x);
        this.table[index].push(x);
    }
 
    // deletes a key from hash table
    deleteItem(key) {
        // get the hash index of key
        const index = this.hashFunction(key);
 
        // find the key in (index)th list
        const i = this.table[index].indexOf(key);
 
        // if key is found in hash table, remove it
        if (i !== -1) {
            this.table[index].splice(i, 1);
        }
    }
 
    // hash function to map values to key
    hashFunction(x) {
        return x % this.BUCKET;
    }
 
    // function to display hash table
    displayHash() {
        for (let i = 0; i < this.BUCKET; i++) {
            let str = `${i}`;
            for (let j = 0; j < this.table[i].length; j++) {
                str += ` --> ${this.table[i][j]}`;
            }
            console.log(str);
        }
    }
}
 
// Driver program
const a = [15, 11, 27, 8, 12];
const n = a.length;
 
// insert the keys into the hash table
const h = new Hash(7);   // 7 is count of buckets in hash table
for (let i = 0; i < n; i++) {
    h.insertItem(a[i]);
}
 
// delete 12 from hash table
h.deleteItem(12);
 
// display the Hash table
h.displayHash();


Output

0
1 --> 15 --> 8
2
3
4 --> 11
5
6 --> 27





Time Complexity:

  • Search : O(1+(n/m))
  • Delete : O(1+(n/m))
    where n =  Total elements in hash table
                 m = Size of hash table
  • Here n/m is the Load Factor.
  • Load Factor (∝) must be as small as possible.
  • If load factor increases,then possibility of collision increases.
  • Load factor is trade of space and time .
  • Assume , uniform distribution of keys ,
  • Expected chain length : O(∝)
  • Expected time to search : O( 1 + ∝ )
  • Expected time to insert/ delete :  O( 1 + ∝ )

Auxiliary Space: O(1), since no extra space has been taken.

Method – 2 : 

Let’s discuss another method where we have no boundation on number of buckets. Number of buckets will increase when value of load factor is greater than 0.5. 

We will do rehashing when the value of load factor is greater than 0.5. In rehashing, we double the size of array and add all the values again to new array (doubled size array is new array) based on hash function. Hash function should also be change as it is depends on number of buckets. Therefore, hash function behaves differently from the previous one.

  • Our Hash function is : (ascii value of character * some prime number ^ x) % total number of buckets. In this case prime number is 31.
  • Load Factor = number of elements in Hash Map / total number of buckets
  • Our key should be string in this case.
  • We can make our own Hash Function but it should be depended on the size of array because if we do rehashing then it must reflect changes and number of collisions should reduce.

C++




#include <iostream>
#define ll long long int
 
using namespace std;
 
// Linked List
template <typename T>
class node
{
public:
    string key;
    T value;
    node *next;
 
    node(string key, T value) // constructor
    {
        this->key = key;
        this->value = value;
        this->next = NULL;
    }
    node(node &obj) // copy constructor
    {
        this->key = obj.key;
        this->value = obj.value;
        this->next = NULL;
    }
 
    ~node() // destructor
    {
        node *head = this;
        while (head != NULL)
        {
            node *currNode = head;
            head = head->next;
            delete currNode;
        }
    }
};
 
// hash table
template <typename T>
class unordered_map
{
public:
    int numOfElements, capacity;
    node<T> **arr; // want a array which stores pointers to node<T> i.e. head of a Linked List
 
    unordered_map() // constructor
    {
        this->capacity = 1;
        this->numOfElements = 0;
        this->arr = new node<T> *[this->capacity];
        this->arr[0] = NULL;
    }
 
    int hashFunction(string key) // hash function for hashing a string
    {   
        int bucketIndex;
        ll sum = 0, factor = 31;
        for (int i = 0; i < key.size(); i++)
        {   
              // sum = sum + (ascii value of character * (prime number ^ x)) % total number of buckets
              // factor = factor * prime number i.e. prime number ^ x
            sum = ((sum % this->capacity) + ((int(key[i])) * factor) % this->capacity) % this->capacity;
            factor = ((factor % INT16_MAX) * (31 % INT16_MAX)) % INT16_MAX;
        }
 
        bucketIndex = sum;
        return bucketIndex;
    }
 
    float getLoadFactor()
    {   
          // number of elements in hash table / total numbers of buckets
        return (float)(this->numOfElements + 1) / (float)(this->capacity);
    }
 
    void rehashing()
    {
        int oldCapacity = this->capacity;
        node<T> **temp = this->arr; // temp is hodling current array
 
        this->capacity = oldCapacity * 2; // doubling the size of current capacity
        this->arr = new node<T> *[this->capacity]; // points to new array of doubled size
 
        for (int i = 0; i < this->capacity; i++)
        {
            arr[i] = NULL;
        }
        for (int i = 0; i < oldCapacity; i++) // copying all the previous values in new array
        {
            node<T> *currBucketHead = temp[i];
            while (currBucketHead != NULL) // copying whole linked list
            {
                this->insert(currBucketHead->key, currBucketHead->value); // insert function have now updated hash function as capacity is doubled
                currBucketHead = currBucketHead->next;
            }
        }
        delete[] temp; // deleting old array from heap memory
        return;
    }
 
    void insert(string key, T value)
    {
        while (this->getLoadFactor() > 0.5f) // when load factor > 0.5
        {
            this->rehashing();
        }
 
        int bucketIndex = this->hashFunction(key);
        if (this->arr[bucketIndex] == NULL) // when there is no linked list at bucket
        {
            node<T> *newNode = new node<T>(key, value);
            arr[bucketIndex] = newNode;
        }
        else // adding at the head of current linked list
        {
            node<T> *newNode = new node<T>(key, value);
            newNode->next = this->arr[bucketIndex];
            this->arr[bucketIndex] = newNode;
        }
        return;
    }
 
    int search(string key)
    {
        int bucketIndex = this->hashFunction(key); // getting bucket index
        node<T> *bucketHead = this->arr[bucketIndex];
        while (bucketHead != NULL) // searching in the linked list which is present at bucket for given key
        {
            if (bucketHead->key == key)
            {
                return bucketHead->value;
            }
            bucketHead = bucketHead->next; // moving to next node in linked list
        }
        cout << "Oops!! Data not found." << endl; // when key is not matched...
        return -1;
    }
};
 
int main()
{
    unordered_map<int> mp; // int is value....in our case key must be of string type
      mp.insert("Manish", 16);
      mp.insert("Vartika", 14);
      mp.insert("ITT", 5);
      mp.insert("elite_Programmer", 4);
      mp.insert("pluto14", 14);
      mp.insert("GeeksForGeeks", 11);
       
      cout << "Value of GeeksForGeeks : " << mp.search("GeeksForGeeks") << endl;
      cout << "Value of ITT : " << mp.search("ITT") << endl;
      cout << "Value of Manish : " << mp.search("Manish") << endl;
      cout << "Value of Vartika : " << mp.search("Vartika") << endl;
      cout << "Value of elite_Programmer : " << mp.search("elite_Programmer") << endl;
      cout << "Value of pluto14 : " << mp.search("pluto14") << endl;
         
        // prints Oops!! Data not found and return -1
      mp.search("GFG"); // case when there is no key present in Hash Map..
   
      return 0;
}


Java




import java.util.LinkedList;
 
class Node<T> {
    String key;
    T value;
    Node<T> next;
 
    Node(String key, T value) {
        this.key = key;
        this.value = value;
        next = null;
    }
}
 
class HashTable<T> {
    int capacity;
    int size;
    LinkedList<Node<T>>[] buckets;
 
    HashTable(int capacity) {
        this.capacity = capacity;
        size = 0;
        buckets = new LinkedList[capacity];
        for (int i = 0; i < capacity; i++) {
            buckets[i] = new LinkedList<Node<T>>();
        }
    }
 
    int hashFunction(String key) {
        int sum = 0;
        int factor = 31;
        for (int i = 0; i < key.length(); i++) {
            sum = (sum + (int)(key.charAt(i)) * factor) % capacity;
            factor = (factor * 31) % (int)1e7; // using prime number 31
        }
        return sum;
    }
 
    void insert(String key, T value) {
        int index = hashFunction(key);
        LinkedList<Node<T>> list = buckets[index];
        for (Node<T> node : list) {
            if (node.key.equals(key)) {
                node.value = value;
                return;
            }
        }
        Node<T> node = new Node<T>(key, value);
        list.addFirst(node);
        size++;
    }
 
    T search(String key) {
        int index = hashFunction(key);
        LinkedList<Node<T>> list = buckets[index];
        for (Node<T> node : list) {
            if (node.key.equals(key)) {
                return node.value;
            }
        }
        System.out.println("Oops!! Data not found.");
        return null;
    }
 
    void delete(String key) {
        int index = hashFunction(key);
        LinkedList<Node<T>> list = buckets[index];
        Node<T> prev = null;
        for (Node<T> node : list) {
            if (node.key.equals(key)) {
                if (prev == null) {
                    list.removeFirst();
                } else {
                    prev.next = node.next;
                }
                size--;
                return;
            }
            prev = node;
        }
        System.out.println("Key not found.");
    }
 
    double loadFactor() {
        return (double)size / capacity;
    }
 
    void rehash() {
        capacity *= 2;
        LinkedList<Node<T>>[] newBuckets = new LinkedList[capacity];
        for (int i = 0; i < capacity; i++) {
            newBuckets[i] = new LinkedList<Node<T>>();
        }
        for (int i = 0; i < buckets.length; i++) {
            for (Node<T> node : buckets[i]) {
                int newIndex = hashFunction(node.key);
                newBuckets[newIndex].addFirst(node);
            }
        }
        buckets = newBuckets;
    }
}
 
public class Main {
    public static void main(String[] args) {
        HashTable<Integer> map = new HashTable<>(10);
        map.insert("Manish", 16);
        map.insert("Vartika", 14);
        map.insert("ITT", 5);
        map.insert("elite_Programmer", 4);
        map.insert("pluto14", 14);
        map.insert("GeeksForGeeks", 11);
 
        System.out.println("Value of GeeksForGeeks: " + map.search("GeeksForGeeks"));
       System.out.println("Value of ITT: " + map.search("ITT"));
      System.out.println("Value of Manish: " + map.search("Manish"));
      System.out.println("Value of Vartika: " + map.search("Vartika"));
      System.out.println("Value of elite_programmer: " + map.search("elite_programmer"));
      System.out.println("Value of pluto14: " + map.search("pluto14"));
    }
}


Python3




class Node:
    def __init__(self, key, value):
        self.key = key
        self.value = value
        self.next = None
 
class UnorderedMap:
    def __init__(self):
        self.capacity = 1
        self.num_of_elements = 0
        self.arr = [None] * self.capacity
 
    def hash_function(self, key):
        sum_val = 0
        factor = 31
        for char in key:
            sum_val = (sum_val + (ord(char) * factor) % self.capacity) % self.capacity
            factor = (factor * 31) % 0x7FFF_FFFF  # Using 0x7FFF_FFFF as INT16_MAX in Python
 
        return sum_val
 
    def get_load_factor(self):
        return (self.num_of_elements + 1) / self.capacity
 
    def rehashing(self):
        old_capacity = self.capacity
        temp = self.arr.copy()
 
        self.capacity = old_capacity * 2
        self.arr = [None] * self.capacity
 
        for i in range(self.capacity):
            self.arr[i] = None
 
        for i in range(old_capacity):
            curr_bucket_head = temp[i]
            while curr_bucket_head is not None:
                self.insert(curr_bucket_head.key, curr_bucket_head.value)
                curr_bucket_head = curr_bucket_head.next
 
    def insert(self, key, value):
        while self.get_load_factor() > 0.5:
            self.rehashing()
 
        bucket_index = self.hash_function(key)
 
        if self.arr[bucket_index] is None:
            new_node = Node(key, value)
            self.arr[bucket_index] = new_node
        else:
            new_node = Node(key, value)
            new_node.next = self.arr[bucket_index]
            self.arr[bucket_index] = new_node
 
    def search(self, key):
        bucket_index = self.hash_function(key)
        bucket_head = self.arr[bucket_index]
 
        while bucket_head is not None:
            if bucket_head.key == key:
                return bucket_head.value
            bucket_head = bucket_head.next
 
        print("Oops!! Data not found.")
        return -1
 
def main():
    mp = UnorderedMap()
    mp.insert("Manish", 16)
    mp.insert("Vartika", 14)
    mp.insert("ITT", 5)
    mp.insert("elite_Programmer", 4)
    mp.insert("pluto14", 14)
    mp.insert("GeeksForGeeks", 11)
 
    print("Value of GeeksForGeeks:", mp.search("GeeksForGeeks"))
    print("Value of ITT:", mp.search("ITT"))
    print("Value of Manish:", mp.search("Manish"))
    print("Value of Vartika:", mp.search("Vartika"))
    print("Value of elite_Programmer:", mp.search("elite_Programmer"))
    print("Value of pluto14:", mp.search("pluto14"))
 
    # prints "Oops!! Data not found." and returns -1
    mp.search("GFG")
 
if __name__ == "__main__":
    main()
 
# COntributed By Siddhesh22


C#




using System;
using System.Text;
 
public class Node<T>
{
    public string Key { get; set; }
    public T Value { get; set; }
    public Node<T> Next { get; set; }
 
    public Node(string key, T value)
    {
        Key = key;
        Value = value;
        Next = null;
    }
}
 
public class HashMap<T>
{
    private int numOfElements;
    private int capacity;
    private Node<T>[] arr;
 
    public HashMap()
    {
        capacity = 1;
        numOfElements = 0;
        arr = new Node<T>[capacity];
        arr[0] = null;
    }
 
    private int HashFunction(string key)
    {
        long sum = 0;
        long factor = 31;
 
        foreach (char c in key)
        {
            sum = (sum % capacity + (int)c * factor % capacity) % capacity;
            factor = (factor % (int)ushort.MaxValue * 31 % (int)ushort.MaxValue) %
              (int)ushort.MaxValue;
        }
 
        return (int)sum;
    }
 
    private float GetLoadFactor()
    {
        return (float)(numOfElements + 1) / capacity;
    }
 
    private void Rehashing()
    {
        int oldCapacity = capacity;
        Node<T>[] temp = arr;
        capacity = oldCapacity * 2;
        arr = new Node<T>[capacity];
 
        for (int i = 0; i < capacity; i++)
        {
            arr[i] = null;
        }
 
        for (int i = 0; i < oldCapacity; i++)
        {
            Node<T> currBucketHead = temp[i];
 
            while (currBucketHead != null)
            {
                Insert(currBucketHead.Key, currBucketHead.Value);
                currBucketHead = currBucketHead.Next;
            }
        }
 
        Array.Clear(temp, 0, temp.Length);
    }
 
    public void Insert(string key, T value)
    {
        while (GetLoadFactor() > 0.5f)
        {
            Rehashing();
        }
 
        int bucketIndex = HashFunction(key);
 
        if (arr[bucketIndex] == null)
        {
            Node<T> newNode = new Node<T>(key, value);
            arr[bucketIndex] = newNode;
        }
        else
        {
            Node<T> newNode = new Node<T>(key, value);
            newNode.Next = arr[bucketIndex];
            arr[bucketIndex] = newNode;
        }
    }
 
    public T Search(string key)
    {
        int bucketIndex = HashFunction(key);
        Node<T> bucketHead = arr[bucketIndex];
 
        while (bucketHead != null)
        {
            if (bucketHead.Key == key)
            {
                return bucketHead.Value;
            }
            bucketHead = bucketHead.Next;
        }
 
        Console.WriteLine("Oops!! Data not found.");
        return default(T);
    }
}
 
class Program
{
    static void Main()
    {
        HashMap<int> hashMap = new HashMap<int>();
         
        hashMap.Insert("Manish", 16);
        hashMap.Insert("Vartika", 14);
        hashMap.Insert("ITT", 5);
        hashMap.Insert("elite_Programmer", 4);
        hashMap.Insert("pluto14", 14);
        hashMap.Insert("GeeksForGeeks", 11);
         
        Console.WriteLine("Value of GeeksForGeeks: " + hashMap.Search("GeeksForGeeks"));
        Console.WriteLine("Value of ITT: " + hashMap.Search("ITT"));
        Console.WriteLine("Value of Manish: " + hashMap.Search("Manish"));
        Console.WriteLine("Value of Vartika: " + hashMap.Search("Vartika"));
        Console.WriteLine("Value of elite_Programmer: " + hashMap.Search("elite_Programmer"));
        Console.WriteLine("Value of pluto14: " + hashMap.Search("pluto14"));
         
        // This will print "Oops!! Data not found" and return the default value for int (0).
        hashMap.Search("GFG");
    }
}


Javascript




class Node {
  constructor(key, value) {
    this.key = key;
    this.value = value;
    this.next = null;
  }
}
 
class HashMap {
  constructor() {
    this.capacity = 1;
    this.numOfElements = 0;
    this.arr = new Array(this.capacity).fill(null);
  }
 
  hashFunction(key) {
    let bucketIndex;
    let sum = 0;
    let factor = 31;
 
    for (let i = 0; i < key.length; i++) {
      sum = ((sum % this.capacity) + (key.charCodeAt(i) * factor) % this.capacity) % this.capacity;
      factor = ((factor % 32767) * (31 % 32767)) % 32767;
    }
 
    bucketIndex = sum;
    return bucketIndex;
  }
 
  getLoadFactor() {
    return (this.numOfElements + 1) / this.capacity;
  }
 
  rehashing() {
    const oldCapacity = this.capacity;
    const temp = this.arr.slice();
 
    this.capacity = oldCapacity * 2;
    this.arr = new Array(this.capacity).fill(null);
 
    for (let i = 0; i < this.capacity; i++) {
      this.arr[i] = null;
    }
 
    for (let i = 0; i < oldCapacity; i++) {
      let currBucketHead = temp[i];
 
      while (currBucketHead !== null) {
        this.insert(currBucketHead.key, currBucketHead.value);
        currBucketHead = currBucketHead.next;
      }
    }
 
    return;
  }
 
  insert(key, value) {
    while (this.getLoadFactor() > 0.5) {
      this.rehashing();
    }
 
    const bucketIndex = this.hashFunction(key);
 
    if (this.arr[bucketIndex] === null) {
      const newNode = new Node(key, value);
      this.arr[bucketIndex] = newNode;
    } else {
      const newNode = new Node(key, value);
      newNode.next = this.arr[bucketIndex];
      this.arr[bucketIndex] = newNode;
    }
 
    return;
  }
 
  search(key) {
    const bucketIndex = this.hashFunction(key);
    let bucketHead = this.arr[bucketIndex];
 
    while (bucketHead !== null) {
      if (bucketHead.key === key) {
        return bucketHead.value;
      }
 
      bucketHead = bucketHead.next;
    }
 
    console.log("Oops!! Data not found.");
    return -1;
  }
}
 
const hashMap = new HashMap();
 
hashMap.insert("Manish", 16);
hashMap.insert("Vartika", 14);
hashMap.insert("ITT", 5);
hashMap.insert("elite_Programmer", 4);
hashMap.insert("pluto14", 14);
hashMap.insert("GeeksForGeeks", 11);
 
console.log("Value of GeeksForGeeks:", hashMap.search("GeeksForGeeks"));
console.log("Value of ITT:", hashMap.search("ITT"));
console.log("Value of Manish:", hashMap.search("Manish"));
console.log("Value of Vartika:", hashMap.search("Vartika"));
console.log("Value of elite_Programmer:", hashMap.search("elite_Programmer"));
console.log("Value of pluto14:", hashMap.search("pluto14"));
 
// prints "Oops!! Data not found." and returns -1
hashMap.search("GFG");


Output

Value of GeeksForGeeks : 11
Value of ITT : 5
Value of Manish : 16
Value of Vartika : 14
Value of elite_Programmer : 4
Value of pluto14 : 14
Oops!! Data not found.





Complexity analysis of Insert:

  • Time Complexity: O(N), It takes O(N) time complexity because we are checking the load factor each time and when it is greater than 0.5 we call rehashing function which takes O(N) time. 
  • Space Complexity: O(N), It takes O(N) space complexity because we are creating a new array of doubled size and copying all the elements to the new array.

Complexity analysis of Search:

  • Time Complexity: O(N),  It takes O(N) time complexity because we are searching in a linked list of size N. 
  • Space Complexity: O(1),  It takes O(1) space complexity because we are not using any extra space for searching.


Last Updated : 18 Dec, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads