Open In App

Linear Probing in Hash Tables

Last Updated : 02 Jul, 2025
Summarize
Comments
Improve
Suggest changes
Share
Like Article
Like
Report

In Open Addressing, all elements are stored in the hash table itself. So at any point, size of table must be greater than or equal to total number of keys (Note that we can increase table size by copying old data if needed).

  • Insert(k) - Keep probing until an empty slot is found. Once an empty slot is found, insert k.
  • Search(k) - Keep probing until slot’s key doesn’t become equal to k or an empty slot is reached.
  • Delete(k) - Delete operation is interesting. If we simply delete a key, then search may fail. So slots of deleted keys are marked specially as “deleted”.

Here, to mark a node deleted we have used dummy node with key and value -1. 
Insert can insert an item in a deleted slot, but search doesn’t stop at a deleted slot.
The entire process ensures that for any key, we get an integer position within the size of the Hash Table to insert the corresponding value. 
So the process is simple, user gives a (key, value) pair set as input and based on the value generated by hash function an index is generated to where the value corresponding to the particular key is stored. So whenever we need to fetch a value corresponding to a key that is just O(1).
 

Implementation:

CPP
#include <iostream>
#include <vector>
using namespace std;

// class to represent each key-value pair
class hashNode {
public:
    // key and value
    int key;
    int value;

    // constructor
    hashNode(int key, int value) {
        this->key = key;
        this->value = value;
    }
};

// class for hash map implementation
class hashMap {
    hashNode** arr;
    int capacity;
    int size;

    hashNode* dummy;

public:

    // constructor to initialize members
    hashMap() {
        capacity = 20;
        size = 0;
        arr = new hashNode*[capacity];
        for (int i = 0; i < capacity; i++)
            arr[i] = NULL;
        dummy = new hashNode(-1, -1);
    }

    // hash function to calculate index
    int hashCode(int key) {
        return key % capacity;
    }

    // function to insert a key-value pair
    void insertNode(int key, int value) {
        hashNode* temp = new hashNode(key, value);
        int hashIndex = hashCode(key);

        // linear probing to find correct index
        while (arr[hashIndex] != NULL &&
               arr[hashIndex]->key != key &&
               arr[hashIndex]->key != -1) {
            hashIndex++;
            hashIndex %= capacity;
        }

        // insert node and update size if it's a new entry
        if (arr[hashIndex] == NULL || 
                    arr[hashIndex]->key == -1)
            size++;
        arr[hashIndex] = temp;
    }

    // function to delete a node by key
    int deleteNode(int key) {
        int hashIndex = hashCode(key);

        // search for the node with the given key
        while (arr[hashIndex] != NULL) {
            if (arr[hashIndex]->key == key) {
                hashNode* temp = arr[hashIndex];
                arr[hashIndex] = dummy;
                size--;
                return temp->value;
            }
            hashIndex++;
            hashIndex %= capacity;
        }

        // key not found
        return -1;
    }

    // function to get value for a given key
    int get(int key) {
        int hashIndex = hashCode(key);
        int counter = 0;

        // search for the key using linear probing
        while (arr[hashIndex] != NULL) {
            if (counter++ > capacity)
                return -1;

            if (arr[hashIndex]->key == key)
                return arr[hashIndex]->value;
            hashIndex++;
            hashIndex %= capacity;
        }

        // key not found
        return -1;
    }

    // function to return number of elements in map
    int sizeofMap() {
        return size;
    }

    // function to check if map is empty
    bool isEmpty() {
        return size == 0;
    }

    // function to print all key-value pairs
    void display() {
        for (int i = 0; i < capacity; i++) {
            if (arr[i] != NULL && arr[i]->key != -1)
                cout  << arr[i]->key << " "
                         << arr[i]->value << endl;
        }
    }
};

int main() {
    hashMap* h = new hashMap;

    h->insertNode(1, 1);
    h->insertNode(2, 2);
    h->insertNode(2, 3);

    h->display();

    cout << h->sizeofMap() << endl;

    cout << h->deleteNode(2) << endl;

    cout << h->sizeofMap() << endl;

    cout << boolalpha << h->isEmpty() << endl;

    cout << h->get(2);

    return 0;
}
Java
import java.lang.*;

class hashNode {
    int key;
    int value;

    // constructor
    public hashNode(int key, int value) {
        this.key = key;
        this.value = value;
    }
}

class hashMap {
    hashNode[] arr;
    int capacity;
    int size;
    hashNode dummy;

    // constructor
    public hashMap() {
        capacity = 20;
        size = 0;
        arr = new hashNode[capacity];
        dummy = new hashNode(-1, -1);
    }

    // hash function
    int hashCode(int key) {
        return key % capacity;
    }

    // insert key-value pair
    void insertNode(int key, int value) {
        hashNode temp = new hashNode(key, value);
        int hashIndex = hashCode(key);

        while (arr[hashIndex] != null &&
               arr[hashIndex].key != key &&
               arr[hashIndex].key != -1) {
            hashIndex++;
            hashIndex %= capacity;
        }

        if (arr[hashIndex] == null || arr[hashIndex].key == -1)
            size++;
        arr[hashIndex] = temp;
    }

    // delete by key
    int deleteNode(int key) {
        int hashIndex = hashCode(key);

        while (arr[hashIndex] != null) {
            if (arr[hashIndex].key == key) {
                hashNode temp = arr[hashIndex];
                arr[hashIndex] = dummy;
                size--;
                return temp.value;
            }
            hashIndex++;
            hashIndex %= capacity;
        }

        return -1;
    }

    // get value by key
    int get(int key) {
        int hashIndex = hashCode(key);
        int counter = 0;

        while (arr[hashIndex] != null) {
            if (counter++ > capacity)
                return -1;

            if (arr[hashIndex].key == key)
                return arr[hashIndex].value;
            hashIndex++;
            hashIndex %= capacity;
        }

        return -1;
    }

    // size of map
    int sizeofMap() {
        return size;
    }

    // check if map is empty
    boolean isEmpty() {
        return size == 0;
    }

    // display key-value pairs
    void display() {
        for (int i = 0; i < capacity; i++) {
            if (arr[i] != null && arr[i].key != -1) {
                System.out.println(arr[i].key +
                " " + arr[i].value);
            }
        }
    }

    public static void main(String[] args) {
        hashMap h = new hashMap();
        h.insertNode(1, 1);
        h.insertNode(2, 2);
        h.insertNode(2, 3);
        h.display();
        System.out.println(h.sizeofMap());
        System.out.println(h.deleteNode(2));
        System.out.println(h.sizeofMap());
        System.out.println(h.isEmpty());
        System.out.println(h.get(2));
    }
}
Python
class hashNode:
    
    # constructor
    def __init__(self, key, value):
        self.key = key
        self.value = value

class hashMap:
    
    # constructor
    def __init__(self):
        self.capacity = 20
        self.size = 0
        self.arr = [None] * self.capacity
        self.dummy = hashNode(-1, -1)

    # hash function
    def hashCode(self, key):
        return key % self.capacity

    # insert key-value pair
    def insertNode(self, key, value):
        temp = hashNode(key, value)
        hashIndex = self.hashCode(key)

        while self.arr[hashIndex] is not None and \
              self.arr[hashIndex].key != key and \
              self.arr[hashIndex].key != -1:
            hashIndex = (hashIndex + 1) % self.capacity

        if self.arr[hashIndex] is None or \
                    self.arr[hashIndex].key == -1:
            self.size += 1
        self.arr[hashIndex] = temp

    # delete by key
    def deleteNode(self, key):
        hashIndex = self.hashCode(key)

        while self.arr[hashIndex] is not None:
            if self.arr[hashIndex].key == key:
                temp = self.arr[hashIndex]
                self.arr[hashIndex] = self.dummy
                self.size -= 1
                return temp.value
            hashIndex = (hashIndex + 1) % self.capacity

        return -1

    # get value by key
    def get(self, key):
        hashIndex = self.hashCode(key)
        counter = 0

        while self.arr[hashIndex] is not None:
            if counter > self.capacity:
                return -1
            if self.arr[hashIndex].key == key:
                return self.arr[hashIndex].value
            hashIndex = (hashIndex + 1) % self.capacity
            counter += 1

        return -1

    # return map size
    def sizeofMap(self):
        return self.size

    # check if map is empty
    def isEmpty(self):
        return self.size == 0

    # display all key-value pairs
    def display(self):
        for node in self.arr:
            if node is not None and node.key != -1:
                print(f"{node.key} {node.value}")

if __name__ == "__main__":
    h = hashMap()
    h.insertNode(1, 1)
    h.insertNode(2, 2)
    h.insertNode(2, 3)
    h.display()
    print(h.sizeofMap())
    print(h.deleteNode(2))
    print(h.sizeofMap())
    print(str(h.isEmpty()).lower())
    print(h.get(2))
C#
using System;

class hashNode {
    public int key;
    public int value;

    // constructor
    public hashNode(int key, int value) {
        this.key = key;
        this.value = value;
    }
}

class hashMap {
    hashNode[] arr;
    int capacity;
    int size;
    hashNode dummy;

    // constructor
    public hashMap() {
        capacity = 20;
        size = 0;
        arr = new hashNode[capacity];
        dummy = new hashNode(-1, -1);
    }

    // hash function
    int hashCode(int key) {
        return key % capacity;
    }

    // insert key-value pair
    public void insertNode(int key, int value) {
        hashNode temp = new hashNode(key, value);
        int hashIndex = hashCode(key);

        while (arr[hashIndex] != null &&
               arr[hashIndex].key != key &&
               arr[hashIndex].key != -1) {
            hashIndex++;
            hashIndex %= capacity;
        }

        if (arr[hashIndex] == null || arr[hashIndex].key == -1)
            size++;
        arr[hashIndex] = temp;
    }

    // delete by key
    public int deleteNode(int key) {
        int hashIndex = hashCode(key);

        while (arr[hashIndex] != null) {
            if (arr[hashIndex].key == key) {
                hashNode temp = arr[hashIndex];
                arr[hashIndex] = dummy;
                size--;
                return temp.value;
            }
            hashIndex++;
            hashIndex %= capacity;
        }

        return -1;
    }

    // get value by key
    public int get(int key) {
        int hashIndex = hashCode(key);
        int counter = 0;

        while (arr[hashIndex] != null) {
            if (counter++ > capacity)
                return -1;

            if (arr[hashIndex].key == key)
                return arr[hashIndex].value;
            hashIndex++;
            hashIndex %= capacity;
        }

        return -1;
    }

    // size of map
    public int sizeofMap() {
        return size;
    }

    // check if map is empty
    public bool isEmpty() {
        return size == 0;
    }

    // display key-value pairs
    public void display() {
        for (int i = 0; i < capacity; i++) {
            if (arr[i] != null && arr[i].key != -1) {
                Console.WriteLine(arr[i].key + 
                                    " " + arr[i].value);
            }
        }
    }

    static void Main(string[] args) {
        hashMap h = new hashMap();
        h.insertNode(1, 1);
        h.insertNode(2, 2);
        h.insertNode(2, 3);
        h.display();
        Console.WriteLine(h.sizeofMap());
        Console.WriteLine(h.deleteNode(2));
        Console.WriteLine(h.sizeofMap());
        Console.WriteLine(h.isEmpty().
                    ToString().ToLower());
        Console.WriteLine(h.get(2));
    }
}
JavaScript
class hashNode {
    constructor(key, value) {
        this.key = key;
        this.value = value;
    }
}

class hashMap {
    constructor() {
        this.capacity = 20;
        this.size = 0;
        this.arr = new Array(this.capacity).fill(null);
        this.dummy = new hashNode(-1, -1);
    }

    hashCode(key) {
        return key % this.capacity;
    }

    insertNode(key, value) {
        let temp = new hashNode(key, value);
        let hashIndex = this.hashCode(key);

        while (this.arr[hashIndex] !== null &&
               this.arr[hashIndex].key !== key &&
               this.arr[hashIndex].key !== -1) {
            hashIndex = (hashIndex + 1) % this.capacity;
        }

        if (this.arr[hashIndex] === null || this.arr[hashIndex].key === -1)
            this.size++;
        this.arr[hashIndex] = temp;
    }

    deleteNode(key) {
        let hashIndex = this.hashCode(key);

        while (this.arr[hashIndex] !== null) {
            if (this.arr[hashIndex].key === key) {
                let temp = this.arr[hashIndex];
                this.arr[hashIndex] = this.dummy;
                this.size--;
                return temp.value;
            }
            hashIndex = (hashIndex + 1) % this.capacity;
        }

        return -1;
    }

    get(key) {
        let hashIndex = this.hashCode(key);
        let counter = 0;

        while (this.arr[hashIndex] !== null) {
            if (counter++ > this.capacity)
                return -1;

            if (this.arr[hashIndex].key === key)
                return this.arr[hashIndex].value;
            hashIndex = (hashIndex + 1) % this.capacity;
        }

        return -1;
    }

    sizeofMap() {
        return this.size;
    }

    isEmpty() {
        return this.size === 0;
    }

    display() {
        for (let i = 0; i < this.capacity; i++) {
            let node = this.arr[i];
            if (node !== null && node.key !== -1)
                console.log(`${node.key} ${node.value}`);
        }
    }
}

// Driver Code
let h = new hashMap();
h.insertNode(1, 1);
h.insertNode(2, 2);
h.insertNode(2, 3);
h.display();
console.log(h.sizeofMap());
console.log(h.deleteNode(2));
console.log(h.sizeofMap());
console.log(h.isEmpty());
console.log(h.get(2));

Output
1 1
2 3
2
3
1
false
-1

Complexity analysis for Insertion:

Time Complexity:

  • Best Case: O(1)
  • Worst Case: O(n). This happens when all elements have collided and we need to insert the last element by checking free space one by one.
  • Average Case: O(1) for good hash function, O(n) for bad hash function

Auxiliary Space: O(1)

Complexity analysis for Deletion:

Time Complexity:

  • Best Case: O(1)
  • Worst Case: O(n)
  • Average Case: O(1) for good hash function; O(n) for bad hash function

Auxiliary Space: O(1) 

Complexity analysis for Searching:

Time Complexity:

  • Best Case: O(1)
  • Worst Case: O(n)
  • Average Case: O(1) for good hash function; O(n) for bad hash function

Auxiliary Space: O(1) for search operation


Next Article
Article Tags :
Practice Tags :

Similar Reads