跳跃表是一种概率性数据结构,支持O(log n)的查找、插入和删除操作。它使用多层链表,每一层都"跳过"更多的元素,类似于高速公路上的快速车道。

输入值并选择操作

跳跃表结构

  • 多层有序链表
  • 底层包含所有元素
  • 每一层都是下一层的子集
  • 层级提升由抛硬币决定(概率性)

查找过程

  1. 从左上角开始(最高层头节点)
  2. 向右移动,直到下一个元素大于目标
  3. 向下移动一层,重复上述步骤
  4. 继续直到找到或到达底层

插入过程

  1. 在每一层找到插入位置(类似查找)
  2. 在第0层插入
  3. 抛硬币:正面则提升到上一层
  4. 重复抛硬币直到反面或达到最大层
操作 平均 最坏
查找 O(log n) O(n)*
插入 O(log n) O(n)*
删除 O(log n) O(n)*

*由于概率特性,最坏情况非常罕见

空间复杂度:平均O(n),最坏O(n log n)

期望层数:p=0.5时为O(log n)

Redis 有序集合

Redis 使用跳跃表实现 ZSET,支持O(log n)的范围查询和分数更新

LevelDB / RocksDB

用于 MemTable 实现内存中的有序键值存储

并发数据结构

无锁跳跃表比无锁平衡树更容易实现

代码实现

import random

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

class SkipList:
    def __init__(self, max_level=16, p=0.5):
        self.max_level = max_level
        self.p = p
        self.level = 0
        self.head = SkipListNode(float('-inf'), max_level)
    
    def random_level(self):
        """Generate random level using coin flips"""
        level = 0
        while random.random() < self.p and level < self.max_level:
            level += 1
        return level
    
    def search(self, key):
        """Search for a key in the skip list"""
        current = self.head
        for i in range(self.level, -1, -1):
            while current.forward[i] and current.forward[i].key < key:
                current = current.forward[i]
        current = current.forward[0]
        return current and current.key == key
    
    def insert(self, key):
        """Insert a key into the skip list"""
        update = [None] * (self.max_level + 1)
        current = self.head
        
        # Find position at each level
        for i in range(self.level, -1, -1):
            while current.forward[i] and current.forward[i].key < key:
                current = current.forward[i]
            update[i] = current
        
        # Determine level for new node
        new_level = self.random_level()
        if new_level > self.level:
            for i in range(self.level + 1, new_level + 1):
                update[i] = self.head
            self.level = new_level
        
        # Create and insert new node
        new_node = SkipListNode(key, new_level)
        for i in range(new_level + 1):
            new_node.forward[i] = update[i].forward[i]
            update[i].forward[i] = new_node

# Usage
sl = SkipList(max_level=6, p=0.5)
for val in [3, 6, 7, 9, 12, 19, 21, 25]:
    sl.insert(val)
print(sl.search(19))  # True
import java.util.Random;

public class SkipList {
    private static final int MAX_LEVEL = 16;
    private static final double P = 0.5;
    
    private int level;
    private SkipListNode head;
    private Random random;
    
    public SkipList() {
        this.level = 0;
        this.head = new SkipListNode(Integer.MIN_VALUE, MAX_LEVEL);
        this.random = new Random();
    }
    
    private int randomLevel() {
        int lvl = 0;
        while (random.nextDouble() < P && lvl < MAX_LEVEL) {
            lvl++;
        }
        return lvl;
    }
    
    public boolean search(int key) {
        SkipListNode current = head;
        for (int i = level; i >= 0; i--) {
            while (current.forward[i] != null && 
                   current.forward[i].key < key) {
                current = current.forward[i];
            }
        }
        current = current.forward[0];
        return current != null && current.key == key;
    }
    
    public void insert(int key) {
        SkipListNode[] update = new SkipListNode[MAX_LEVEL + 1];
        SkipListNode current = head;
        
        for (int i = level; i >= 0; i--) {
            while (current.forward[i] != null && 
                   current.forward[i].key < key) {
                current = current.forward[i];
            }
            update[i] = current;
        }
        
        int newLevel = randomLevel();
        if (newLevel > level) {
            for (int i = level + 1; i <= newLevel; i++) {
                update[i] = head;
            }
            level = newLevel;
        }
        
        SkipListNode newNode = new SkipListNode(key, newLevel);
        for (int i = 0; i <= newLevel; i++) {
            newNode.forward[i] = update[i].forward[i];
            update[i].forward[i] = newNode;
        }
    }
    
    public static void main(String[] args) {
        SkipList sl = new SkipList();
        int[] values = {3, 6, 7, 9, 12, 19, 21, 25};
        for (int v : values) sl.insert(v);
        System.out.println(sl.search(19)); // true
    }
}

class SkipListNode {
    int key;
    SkipListNode[] forward;
    
    SkipListNode(int key, int level) {
        this.key = key;
        this.forward = new SkipListNode[level + 1];
    }
}