面试中的高级数据结构之跳表

本文探讨了跳表这一高级数据结构,它由多层有序链表组成,底层包含所有元素。跳表在Redis和LevelDB等系统中广泛应用,并提供了高效的查找、插入和删除操作。通过JavaScript实现,展示了跳表的随机化特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

微信公众号:算法面试题

           扫码开启算法之旅

总结:
跳表具有如下性质:
(1) 由很多层结构组成
(2) 每一层都是一个有序的链表
(3) 最底层(第0层)的链表包含所有元素
(4) 如果一个元素出现在第i层中,则它在第0到第i-1层也都会出现 
(5) 跳表是一种随机化的数据结构(通过掷硬币的过程可以看出)
点评:跳表是一种应用广泛的数据结构,著名的Redis与LevelDB系统的源码中,均可看到跳表的踪影。

 

代码实现

 

下面是作者用JavaScript实现的一个跳表,包括查找、插入和删除操作。

 

 1//定义跳表结点
 2function Node(key, value) {
 3    this.key = key;
 4    this.value = value;
 5    //next指针数组
 6    //此元素跨越多少层,next数组就含有多少指向下一结点的指针
 7    this.next = [];
 8}
 9
10//跳表
11class SkipList {
12    constructor() {
13        //头结点不存值
14        this.head = new Node(undefined, undefined);
15        //初始时,跳表层数为0
16        this.level = 0;
17        //初始时,跳表含有0个元素
18        this.size = 0;
19    }
20
21    //查找操作,通过key获取值
22    get(key) {
23        let p = this.head;
24        for(let i = this.level - 1; i >= 0; i--) {
25            while(p.next[i] && p.next[i].key <= key) p = p.next[i];
26            if(p.key == key) return p.value;
27        }
28        return undefined;
29    }
30
31    //插入操作,插入一个键值对
32    set(key, value) {
33        let p = this.head;
34        //update用于记录每层拐点
35        let update = new Array(this.level);
36        for(let i = this.level - 1; i >= 0; i--) {
37            while(p.next[i] && p.next[i].key <= key) p = p.next[i];
38            if(p.key == key) {
39                p.value = value;
40                return this;
41            }
42            update[i] = p;
43        }
44        let newNode = new Node(key, value);
45        //k代表新插入结点跨越层数
46        let k = 1;
47        //模拟抛硬币过程
48        while(Math.random() < 0.5) k++;
49
50        if(k > this.level) {
51            for(let i = this.level; i < k; i++) {
52                newNode.next[i] = null;
53                this.head.next[i] = newNode;
54            }
55            this.level = k;
56            k = update.length;
57        }
58
59        for(let i = k - 1; i >= 0; i--) {
60            newNode.next[i] = update[i].next[i];
61            update[i].next[i] = newNode;
62        }
63
64        this.size++;
65        return this;
66    }
67
68    //删除一个键值对
69    delete(key) {
70        let p = this.head;
71        //update用于记录每层拐点
72        let update = new Array(this.level);
73        for(let i = this.level - 1; i >= 0; i--) {
74            while(p.next[i] && p.next[i].key < key) p = p.next[i];
75            update[i] = p;
76        }
77        if(p.next[0] && p.next[0].key == key) {
78            let deleteNode = p.next[0];
79            for(let i = deleteNode.next.length - 1; i >= 0; i--) {
80                update[i].next[i] = deleteNode.next[i];
81                deleteNode.next[i] = null;
82                if(this.head.next[i] == null) {
83                    this.level--;
84                }
85            }
86            this.head.next.length = this.level;
87            this.size--;
88            return true;
89        }
90        return false;
91    }
92}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值