Skip List

Introduction to Skip List Data Structure

In the realm of computer science and software engineering, data structures play a pivotal role in organizing and manipulating data efficiently. Among the plethora of data structures, the skip list stands out as a versatile and powerful tool. In this comprehensive article, we delve into the intricacies of skip lists, examining their definition, utility, characteristics, types, merits, and demerits.

Skip List

What is Skip List Data Structure

A skip list is a probabilistic data structure that enables efficient search, insertion, deletion, and traversal operations on a sorted sequence of elements. Inspired by the idea of balanced trees, skip lists utilize a series of linked lists with multiple levels of nodes, allowing for logarithmic time complexity for search operations. The key innovation of skip lists lies in the use of forward pointers at different levels, enabling skipping over elements and reducing the average time complexity of operations.

Why We Use Skip List Data Structure in Programming

Skip lists are used in programming for several reasons:

  1. Efficient Search Operations: Skip lists offer efficient search operations with logarithmic time complexity, making them suitable for applications requiring fast retrieval of elements.
  2. Dynamic Data Structures: Skip lists dynamically adjust their structure based on the number of elements added or removed, providing flexibility in managing dynamic datasets.
  3. Space Efficiency: Skip lists maintain a balance between space and time complexity, offering efficient memory usage while ensuring fast search operations.
  4. Simple Implementation: Skip lists have a relatively simple implementation compared to other balanced tree structures, making them easier to understand and maintain.

Characteristics of Skip List Data Structure

  1. Multiple Levels: Skip lists consist of multiple levels of nodes, with each level representing a subset of elements in the list. The top level contains all elements, while lower levels contain progressively fewer elements.
  2. Probabilistic Structure: The structure of skip lists is probabilistic, with the presence of forward pointers at each level determining the skipping behavior during search operations.
  3. Logarithmic Time Complexity: Skip lists offer logarithmic time complexity for search, insertion, deletion, and traversal operations, making them efficient for large datasets.
  4. Balancing Mechanism: Skip lists maintain balance by adjusting the number of forward pointers at each level, ensuring that search operations remain efficient.

Types of Skip List Data Structure

  1. Standard Skip List: The standard skip list consists of multiple levels of nodes, with forward pointers enabling efficient skipping during search operations.
  2. Sorted Skip List: Sorted skip lists maintain elements in sorted order at each level, facilitating fast search operations without requiring additional sorting.
  3. Concurrent Skip List: Concurrent skip lists support concurrent access by multiple threads, ensuring thread safety and efficient parallel processing.

Advantages of Skip List Data Structure

  1. Efficient Search Operations: Skip lists offer efficient search operations with logarithmic time complexity, making them suitable for large datasets.
  2. Dynamic Structure: Skip lists dynamically adjust their structure based on the number of elements, providing flexibility in managing dynamic datasets.
  3. Space Efficiency: Skip lists maintain a balance between space and time complexity, offering efficient memory usage while ensuring fast search operations.
  4. Simple Implementation: Skip lists have a relatively simple implementation compared to other balanced tree structures, making them easier to understand and maintain.

Dis-Advantages of Skip List Data Structure

  1. Higher Space Overhead: Skip lists may incur higher space overhead compared to simpler data structures due to the presence of multiple levels and forward pointers.
  2. Probabilistic Behavior: The probabilistic nature of skip lists may lead to unpredictable performance in certain scenarios, requiring careful tuning of parameters.
  3. Limited Applications: Skip lists may not be suitable for applications requiring strict deterministic behavior or real-time constraints, as their performance can vary based on the dataset and access patterns.
  4. Complexity of Maintenance: While skip lists offer efficient search operations, maintaining the structure and ensuring balance may require additional overhead compared to simpler data structures.

Code Examples of Skip List Data Structure

Below are code examples demonstrating skip list usage in various programming languages:

Skip Lists in C++

#include <iostream>
#include <cstdlib>
#include <ctime>

const int MAX_LEVEL = 5;

// Node structure
struct Node {
    int value;
    Node* forward[MAX_LEVEL + 1];
    Node() {
        memset(forward, 0, sizeof(forward));
    }
};

// Skip list class
class SkipList {
private:
    Node* header;
    int level;
public:
    SkipList();
    int randomLevel();
    Node* createNode(int value, int level);
    void insertElement(int value);
    bool searchElement(int value);
    void deleteElement(int value);
    void display();
};

// Constructor
SkipList::SkipList() {
    header = new Node();
    level = 0;
}

// Generate random level for a node
int SkipList::randomLevel() {
    int level = 0;
    while (rand() % 2)
        level++;
    return level;
}

// Create a new node
Node* SkipList::createNode(int value, int level) {
    Node* newNode = new Node();
    newNode->value = value;
    return newNode;
}

// Insert an element into the skip list
void SkipList::insertElement(int value) {
    Node* current = header;
    Node* update[MAX_LEVEL + 1];
    memset(update, 0, sizeof(Node*) * (MAX_LEVEL + 1));

    for (int i = level; i >= 0; i--) {
        while (current->forward[i] != nullptr && current->forward[i]->value < value)
            current = current->forward[i];
        update[i] = current;
    }

    current = current->forward[0];

    if (current == nullptr || current->value != value) {
        int newLevel = randomLevel();
        if (newLevel > level) {
            for (int i = level + 1; i <= newLevel; i++)
                update[i] = header;
            level = newLevel;
        }
        Node* newNode = createNode(value, newLevel);

        for (int i = 0; i <= newLevel; i++) {
            newNode->forward[i] = update[i]->forward[i];
            update[i]->forward[i] = newNode;
        }
    }
}

// Search for an element in the skip list
bool SkipList::searchElement(int value) {
    Node* current = header;
    for (int i = level; i >= 0; i--) {
        while (current->forward[i] != nullptr && current->forward[i]->value < value)
            current = current->forward[i];
    }
    current = current->forward[0];
    return (current != nullptr && current->value == value);
}

// Delete an element from the skip list
void SkipList::deleteElement(int value) {
    Node* current = header;
    Node* update[MAX_LEVEL + 1];
    memset(update, 0, sizeof(Node*) * (MAX_LEVEL + 1));

    for (int i = level; i >= 0; i--) {
        while (current->forward[i] != nullptr && current->forward[i]->value < value)
            current = current->forward[i];
        update[i] = current;
    }

    current = current->forward[0];

    if (current != nullptr && current->value == value) {
        for (int i = 0; i <= level; i++) {
            if (update[i]->forward[i] != current)
                break;
            update[i]->forward[i] = current->forward[i];
        }

        while (level > 0 && header->forward[level] == nullptr)
            level--;
    }
}

// Display the skip list
void SkipList::display() {
    std::cout << "Skip List: " << std::endl;
    for (int i = 0; i <= level; i++) {
        Node* node = header->forward[i];
        std::cout << "Level " << i << ": ";
        while (node != nullptr) {
            std::cout << node->value << " ";
            node = node->forward[i];
        }
        std::cout << std::endl;
    }
}

int main() {
    // Initialize random seed
    srand(time(nullptr));
    // Create a skip list
    SkipList skipList;
    // Insert elements
    skipList.insertElement(3);
    skipList.insertElement(6);
    skipList.insertElement(7);
    skipList.insertElement(9);
    skipList.insertElement(12);
    // Display the skip list
    skipList.display();
    // Search for an element
    std::cout << "Search for 7: " << (skipList.searchElement(7) ? "Found" : "Not found") << std::endl;
    // Delete an element
    skipList.deleteElement(7);
    // Display the skip list after deletion
    skipList.display();
    return 0;
}

Output

Skip List:
Level 0: 3 6 7 9 12
Search for 7: Found
Skip List:
Level 0: 3 6 9 12 

Skip Lists in Java

import java.util.Random;

public class SkipList {
    private static final int MAX_LEVEL = 5;
    private Node header;
    private int level;

    // Node class
    private class Node {
        int value;
        Node[] forward;
        Node(int level, int value) {
            this.value = value;
            forward = new Node[level + 1];
        }
    }

    // Constructor
    public SkipList() {
        header = new Node(MAX_LEVEL, Integer.MIN_VALUE);
        level = 0;
    }

    // Generate random level for a node
    private int randomLevel() {
        int level = 0;
        Random rand = new Random();
        while (rand.nextBoolean() && level < MAX_LEVEL)
            level++;
        return level;
    }

    // Insert an element into the skip list
    public void insertElement(int value) {
        Node current = header;
        Node[] update = new Node[MAX_LEVEL + 1];
        for (int i = level; i >= 0; i--) {
            while (current.forward[i] != null && current.forward[i].value < value)
                current = current.forward[i];
            update[i] = current;
        }
        current = current.forward[0];
        if (current == null || current.value != value) {
            int newLevel = randomLevel();
            if (newLevel > level) {
                for (int i = level + 1; i <= newLevel; i++)
                    update[i] = header;
                level = newLevel;
            }
            Node newNode = new Node(newLevel, value);
            for (int i = 0; i <= newLevel; i++) {
                newNode.forward[i] = update[i].forward[i];
                update[i].forward[i] = newNode;
            }
        }
    }

    // Search for an element in the skip list
    public boolean searchElement(int value) {
        Node current = header;
        for (int i = level; i >= 0; i--) {
            while (current.forward[i] != null && current.forward[i].value < value)
                current = current.forward[i];
        }
        current = current.forward[0];
        return (current != null && current.value == value);
    }

    // Delete an element from the skip list
    public void deleteElement(int value) {
        Node current = header;
        Node[] update = new Node[MAX_LEVEL + 1];
        for (int i = level; i >= 0; i--) {
            while (current.forward[i] != null && current.forward[i].value < value)
                current = current.forward[i];
            update[i] = current;
        }
        current = current.forward[0];
        if (current != null && current.value == value) {
            for (int i = 0; i <= level; i++) {
                if (update[i].forward[i] != current)
                    break;
                update[i].forward[i] = current.forward[i];
            }
            while (level > 0 && header.forward[level] == null)
                level--;
        }
    }

    // Display the skip list
    public void display() {
        System.out.println("Skip List:");
        for (int i = 0; i <= level; i++) {
            Node node = header.forward[i];
            System.out.print("Level " + i + ": ");
            while (node != null) {
                System.out.print(node.value + " ");
                node = node.forward[i];
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        // Create a skip list
        SkipList skipList = new SkipList();
        // Insert elements
        skipList.insertElement(3);
        skipList.insertElement(6);
        skipList.insertElement(7);
        skipList.insertElement(9);
        skipList.insertElement(12);
        // Display the skip list
        skipList.display();
        // Search for an element
        System.out.println("Search for 7: " + (skipList.searchElement(7) ? "Found" : "Not found"));
        // Delete an element
        skipList.deleteElement(7);
        // Display the skip list after deletion
        skipList.display();
    }
}

Output

Skip List:
Level 0: 3 6 7 9 12 
Search for 7: Found
Skip List:
Level 0: 3 6 9 12 

Skip Lists in Python

import random

class Node:
    def __init__(self, level, value):
        self.value = value
        self.forward = [None] * (level + 1)

class SkipList:
    MAX_LEVEL = 5

    def __init__(self):
        self.header = Node(SkipList.MAX_LEVEL, float('-inf'))
        self.level = 0

    def random_level(self):
        level = 0
        while random.randint(0, 1) and level < SkipList.MAX_LEVEL:
            level += 1
        return level

    def insert_element(self, value):
        update = [None] * (SkipList.MAX_LEVEL + 1)
        current = self.header
        for i in range(self.level, -1, -1):
            while current.forward[i] and current.forward[i].value < value:
                current = current.forward[i]
            update[i] = current
        current = current.forward[0]
        if current is None or current.value != value:
            new_level = self.random_level()
            if new_level > self.level:
                for i in range(self.level + 1, new_level + 1):
                    update[i] = self.header
                self.level = new_level
            new_node = Node(new_level, value)
            for i in range(new_level + 1):
                new_node.forward[i] = update[i].forward[i]
                update[i].forward[i] = new_node

    def search_element(self, value):
        current = self.header
        for i in range(self.level, -1, -1):
            while current.forward[i] and current.forward[i].value < value:
                current = current.forward[i]
        current = current.forward[0]
        return current is not None and current.value == value

    def delete_element(self, value):
        update = [None] * (SkipList.MAX_LEVEL + 1)
        current = self.header
        for i in range(self.level, -1, -1):
            while current.forward[i] and current.forward[i].value < value:
                current = current.forward[i]
            update[i] = current
        current = current.forward[0]
        if current and current.value == value:
            for i in range(self.level + 1):
                if update[i].forward[i] != current:
                    break
                update[i].forward[i] = current.forward[i]
            while self.level > 0 and self.header.forward[self.level] is None:
                self.level -= 1

    def display(self):
        print("Skip List:")
        for i in range(self.level + 1):
            node = self.header.forward[i]
            print("Level {}: ".format(i), end="")
            while node:
                print(node.value, end=" ")
                node = node.forward[i]
            print()

if __name__ == "__main__":
    # Create a skip list
    skip_list = SkipList()
    # Insert elements
    skip_list.insert_element(3)
    skip_list.insert_element(6)
    skip_list.insert_element(7)
    skip_list.insert_element(9)
    skip_list.insert_element(12)
    # Display the skip list
    skip_list.display()
    # Search for an element
    print("Search for 7:", "Found" if skip_list.search_element(7) else "Not found")
    # Delete an element
    skip_list.delete_element(7)
    # Display the skip list after deletion
    skip_list.display()

Output

Skip List:
Level 0: 3 6 7 9 12 
Search for 7: Found
Skip List:
Level 0: 3 6 9 12 

Skip Lists in JavaScript

class Node {
    constructor(level, value) {
        this.value = value;
        this.forward = Array(level + 1).fill(null);
    }
}

class SkipList {
    static MAX_LEVEL = 5;

    constructor() {
        this.header = new Node(SkipList.MAX_LEVEL, Number.MIN_SAFE_INTEGER);
        this.level = 0;
    }

    randomLevel() {
        let level = 0;
        while (Math.random() < 0.5 && level < SkipList.MAX_LEVEL)
            level++;
        return level;
    }

    insertElement(value) {
        const update = new Array(SkipList.MAX_LEVEL + 1);
        let current = this.header;
        for (let i = this.level; i >= 0; i--) {
            while (current.forward[i] && current.forward[i].value < value)
                current = current.forward[i];
            update[i] = current;
        }
        current = current.forward[0];
        if (!current || current.value !== value) {
            const newLevel = this.randomLevel();
            if (newLevel > this.level) {
                for (let i = this.level + 1; i <= newLevel; i++)
                    update[i] = this.header;
                this.level = newLevel;
            }
            const newNode = new Node(newLevel, value);
            for (let i = 0; i <= newLevel; i++) {
                newNode.forward[i] = update[i].forward[i];
                update[i].forward[i] = newNode;
            }
        }
    }

    searchElement(value) {
        let current = this.header;
        for (let i = this.level; i >= 0; i--) {
            while (current.forward[i] && current.forward[i].value < value)
                current = current.forward[i];
        }
        current = current.forward[0];
        return current && current.value === value;
    }

    deleteElement(value) {
        const update = new Array(SkipList.MAX_LEVEL + 1);
        let current = this.header;
        for (let i = this.level; i >= 0; i--) {
            while (current.forward[i] && current.forward[i].value < value)
                current = current.forward[i];
            update[i] = current;
        }
        current = current.forward[0];
        if (current && current.value === value) {
            for (let i = 0; i <= this.level; i++) {
                if (update[i].forward[i] !== current)
                    break;
                update[i].forward[i] = current.forward[i];
            }
            while (this.level > 0 && !this.header.forward[this.level])
                this.level--;
        }
    }

    display() {
        console.log("Skip List:");
        for (let i = 0; i <= this.level; i++) {
            let node = this.header.forward[i];
            process.stdout.write(`Level ${i}: `);
            while (node) {
                process.stdout.write(`${node.value} `);
                node = node.forward[i];
            }
            console.log();
        }
    }
}

// Create a skip list
const skipList = new SkipList();
// Insert elements
skipList.insertElement(3);
skipList.insertElement(6);
skipList.insertElement(7);
skipList.insertElement(9);
skipList.insertElement(12);
// Display the skip list
skipList.display();
// Search for an element
console.log("Search for 7:", skipList.searchElement(7) ? "Found" : "Not found");
// Delete an element
skipList.deleteElement(7);
// Display the skip list after deletion
skipList.display();

Output

Skip List:
Level 0: 3 6 7 9 12 
Search for 7: Found
Skip List:
Level 0: 3 6 9 12 

Conclusion

In conclusion, skip lists represent a versatile and efficient data structure, offering logarithmic time complexity for search operations while maintaining a balance between space and time efficiency. Despite their probabilistic nature and potential space overhead, skip lists find widespread applications in various domains, including database indexing, caching, and search algorithms. By mastering the concepts and applications of skip lists, programmers can enhance their problem-solving skills and develop robust, efficient algorithms, contributing to the advancement of technology and innovation in the digital age.

For more visit my website Codelikechamp.com

What is Data Structure

Types of data structure

what is Linked List

what is array

🤞 Don’t miss any latest posts!

Please subscribe by joining our community for free and stay updated!!!

IF YOU HAVE ALREADY SUBSCRIBED JUST CLOSE THIS FORM !

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top