Skip to content
Related Articles

Related Articles

Double Hashing

View Discussion
Improve Article
Save Article
View Discussion
Improve Article
Save Article

Double hashing is a collision resolving technique in Open Addressed Hash tables. Double hashing uses the idea of applying a second hash function to key when a collision occurs.

Advantages of Double hashing

  • The advantage of Double hashing is that it is one of the best form of probing, producing a uniform distribution of records throughout a hash table.
  • This technique does not yield any clusters.
  • It is one of effective method for resolving collisions.

Double hashing can be done using : 
(hash1(key) + i * hash2(key)) % TABLE_SIZE 
Here hash1() and hash2() are hash functions and TABLE_SIZE 
is size of hash table. 
(We repeat by increasing i when collision occurs)

First hash function is typically hash1(key) = key % TABLE_SIZE
A popular second hash function is : hash2(key) = PRIME – (key % PRIME) where PRIME is a prime smaller than the TABLE_SIZE.
A good second Hash function is: 
 

  • It must never evaluate to zero
  • Must make sure that all cells can be probed

 

 

CPP




/*
** Handling of collision via open addressing
** Method for Probing: Double Hashing
*/
 
#include <iostream>
#include <vector>
#include <bitset>
using namespace std;
#define MAX_SIZE 10000001ll
 
class doubleHash {
 
    int TABLE_SIZE, keysPresent, PRIME;
    vector<int> hashTable;
    bitset<MAX_SIZE> isPrime;
 
    /* Function to set sieve of Eratosthenes. */
    void __setSieve(){
        isPrime[0] = isPrime[1] = 1;
        for(long long i = 2; i*i <= MAX_SIZE; i++)
            if(isPrime[i] == 0)
                for(long long j = i*i; j <= MAX_SIZE; j += i)
                    isPrime[j] = 1;
 
    }
 
    int inline hash1(int value){
        return value%TABLE_SIZE;
    }
     
    int inline hash2(int value){      
        return PRIME - (value%PRIME);
    }
 
    bool inline isFull(){
        return (TABLE_SIZE == keysPresent);
    }
 
    public:
 
    doubleHash(int n){
        __setSieve();
        TABLE_SIZE = n;
 
        /* Find the largest prime number smaller than hash table's size. */
        PRIME = TABLE_SIZE - 1;
        while(isPrime[PRIME] == 1)
            PRIME--;
 
        keysPresent = 0;
 
        /* Fill the hash table with -1 (empty entries). */
        for(int i = 0; i < TABLE_SIZE; i++)
            hashTable.push_back(-1);
    }
 
    void __printPrime(long long n){
        for(long long i = 0; i <= n; i++)
            if(isPrime[i] == 0)
                cout<<i<<", ";
        cout<<endl;
    }
 
    /* Function to insert value in hash table */
    void insert(int value){
 
        if(value == -1 || value == -2){
            cout<<("ERROR : -1 and -2 can't be inserted in the table\n"); 
        }
 
        if(isFull()){
            cout<<("ERROR : Hash Table Full\n");
            return;
        }
         
        int probe = hash1(value), offset = hash2(value); // in linear probing offset = 1;
         
        while(hashTable[probe] != -1){
            if(-2 == hashTable[probe])                 
                break;                                  // insert at deleted element's location
            probe = (probe+offset) % TABLE_SIZE;
        }
 
        hashTable[probe] = value;
        keysPresent += 1;
    }
 
    void erase(int value){
        /* Return if element is not present */
        if(!search(value))
            return;    
         
        int probe = hash1(value), offset = hash2(value);
 
        while(hashTable[probe] != -1)
            if(hashTable[probe] == value){
                hashTable[probe] = -2;          // mark element as deleted (rather than unvisited(-1)).
                keysPresent--;
                return;
            }
            else
                probe = (probe + offset) % TABLE_SIZE;
 
    }
 
    bool search(int value){
        int probe = hash1(value), offset = hash2(value), initialPos = probe;
        bool firstItr = true;
 
        while(1){
            if(hashTable[probe] == -1)                   // Stop search if -1 is encountered.
                break;
            else if(hashTable[probe] == value)           // Stop search after finding the element.
                return true;
            else if(probe == initialPos && !firstItr)    // Stop search if one complete traversal of hash table is completed.
                return false;
            else
                probe = ((probe + offset) % TABLE_SIZE);  // if none of the above cases occur then update the index and check at it.
 
            firstItr = false;
        }
        return false;
    }
 
    /* Function to display the hash table. */
    void print(){
        for(int i = 0; i < TABLE_SIZE; i++)
            cout<<hashTable[i]<<", ";
        cout<<"\n";
    }
 
};
 
int main(){
    doubleHash myHash(13); // creates an empty hash table of size 13
 
    /* Inserts random element in the hash table */
     
    int insertions[] = {115, 12, 87, 66, 123},
        n1 = sizeof(insertions)/sizeof(insertions[0]);
     
    for(int i = 0; i < n1; i++)
        myHash.insert(insertions[i]);
     
    cout<< "Status of hash table after initial insertions : "; myHash.print();
     
 
    /*
    ** Searches for random element in the hash table,
    ** and prints them if found.
    */
     
    int queries[] = {1, 12, 2, 3, 69, 88, 115},
        n2 = sizeof(queries)/sizeof(queries[0]);
     
    cout<<"\n"<<"Search operation after insertion : \n";
 
    for(int i = 0; i < n2; i++)
        if(myHash.search(queries[i]))
            cout<<queries[i]<<" present\n";
     
 
    /* Deletes random element from the hash table. */
     
    int deletions[] = {123, 87, 66},
        n3 = sizeof(deletions)/sizeof(deletions[0]);
     
    for(int i = 0; i < n3; i++)
        myHash.erase(deletions[i]);
 
    cout<< "Status of hash table after deleting elements : "; myHash.print();
     
    return 0;
}


Output

Status of hash table after initial insertions : -1, 66, -1, -1, -1, -1, 123, -1, -1, 87, -1, 115, 12, 

Search operation after insertion : 
12 present
115 present
Status of hash table after deleting elements : -1, -2, -1, -1, -1, -1, -2, -1, -1, -2, -1, 115, 12, 

Here is an Easy implementation of Double Hashing in Python.

Note: It’s written in python3.

Python3




class DoubleHashing:
    def __init__(self, TableSize = 1111111):
        self.ts = TableSize
        self.List = [None]*self.ts
        self.count = 0 #to count element in list
         
    def nearestPrime(self):
        for l in range((self.ts-1),1,-1):
            flag = True
            for i in range(2, int(l**0.5)+1):
                 
                if l%i == 0:
                    flag = False
                    break
 
            if flag:
                return l
 
        return 3 #default prime number
 
 
    def Hx1(self,key): #HashFunction 1 or Default Hash function when there is no collision.
        return key%self.ts
 
    def Hx2(self, key): #Hash Function 2 only used when collision occurs.
        return self.nearestPrime() - (key% self.nearestPrime())         #Formula: PRIME - (KEY % PRIME), Here always PRIME < TABLE_SIZE
         
 
    def dHasing(self, key):
        if self.count == self.ts:
            print("List is Full")
            return self.List
 
        elif self.List[self.Hx1(key)] == None:
            self.List[self.Hx1(key)] = key
            self.count +=1
            print(f"Entered key: {key} at index {self.Hx1(key)}")
             
        else:
            comp = False
            i = 1
            while not comp:    
 
                index = (self.Hx1(key) + i*self.Hx2(key))%self.ts  # Index = ( HashFunc1 - i*HashFunc2)%TABle_SIZE
 
                if self.List[index] == None:
                    self.List[index] = key
                    print(f"Entered key: {key} at index {index}")
                    comp = True
                    self.count +=1
                else:
                    i +=1
        return self.List
 
 
 
    def PrintHashList(self):
        for i in range(0, len(self.List)):
            print(self.List[i])
 
     
 
def main():
 
    tableSize = 5 #Taking 5 as size of the hash Table
    DHash = DoubleHashing(tableSize)
 
    InputElements = [4,11, 29, 1, 5]
 
    for i in InputElements:
        DHash.dHasing(i)
 
 
    print('\n')
    print("The Hash List After Entering Elements")
    DHash.PrintHashList() #Printing the resultant HashList.
 
 
 
 
if __name__ =="__main__":
    main()
 
 
 
 
 
         
 
 
            


Output

Entered key: 4 at index 4
Entered key: 11 at index 1
Entered key: 29 at index 0
Entered key: 1 at index 3
Entered key: 5 at index 2


The Hash List After Entering Elements
29
11
5
1
4

My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!