Unverified Commit 66ec57c7 authored by Shuhao Zhang's avatar Shuhao Zhang Committed by GitHub
Browse files

Merge pull request #2573 from Backl1ght/patch-1

Update skiplist.md
parents 19e71c92 c6d725c1
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -10,9 +10,11 @@

一个有序链表的查找操作,就是从头部开始逐个比较,直到当前节点的值大于或者等于目标节点的值。很明显,这个操作的复杂度是 $O(n)$ 。

跳表在有序链表的基础上,引入了 **分层** 的概念。首先,跳表的每一层都是一个有序链表,特别地,最底层是初始的有序链表。每个位于第 $i$ 层的节点有 $p$ 的概率出现在第 $i+1$ 层, $p$ 为常数。可以计算出,跳表的期望层数为 $\log_{\frac{1}{p}}n$ 。
跳表在有序链表的基础上,引入了 **分层** 的概念。首先,跳表的每一层都是一个有序链表,特别地,最底层是初始的有序链表。每个位于第 $i$ 层的节点有 $p$ 的概率出现在第 $i+1$ 层, $p$ 为常数。

在跳表中查找,就是从最高层开始,水平地逐个比较,直至当前节点大于等于目标节点。若是当前节点等于目标节点,则成功查找;若是大于目标节点或者是达到链表的末尾,就退回上一个元素后下降到下一层,直到找到目标节点或者达到最底层的末尾。这样一来,查找的过程中会跳过一些没有必要的比较,所以相比于有序链表的查询,跳表的查询更快。可以证明,跳表查询的平均复杂度为 $O(\log n)$ 。
记在 n 个节点的跳表中,期望包含 $\frac{1}{p}$ 个元素的层为第 $L(n)$ 层,易得 $L(n) = \log_{\frac{1}{p}}n$ 。

在跳表中查找,就是从第 $L(n)$ 层开始,水平地逐个比较直至当前节点的下一个节点大于等于目标节点,然后移动至下一层。重复这个过程直至到达第一层且无法继续进行操作。此时,若下一个节点是目标节点,则成功查找;反之,则元素不存在。这样一来,查找的过程中会跳过一些没有必要的比较,所以相比于有序链表的查询,跳表的查询更快。可以证明,跳表查询的平均复杂度为 $O(\log n)$ 。

## 复杂度证明

@@ -24,8 +26,6 @@

### 时间复杂度

记 n 个节点的跳表的期望层数为 $L(n)$ 。

从后向前分析查找路径,这个过程可以分为从最底层爬到第 $L(n)$ 层和后续操作两个部分。在分析时,假设一个节点的具体信息在它被访问之前是未知的。

假设当前我们处于一个第 $i$ 层的节点 $x$ ,我们并不知道 $x$ 的最大层数和 $x$ 左侧节点的最大层数,只知道 $x$ 的最大层数至少为 $i$ 。如果 $x$ 的最大层数大于 $i$ ,那么下一步应该是向上走,这种情况的概率为 $p$ ;如果 $x$ 的最大层数等于 $i$ ,那么下一步应该是向左走,这种情况概率为 $1-p$ 。