4.4: Analysis of Skiplists
- Page ID
- 8453
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\( \newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\)
( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\id}{\mathrm{id}}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\kernel}{\mathrm{null}\,}\)
\( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\)
\( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\)
\( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\AA}{\unicode[.8,0]{x212B}}\)
\( \newcommand{\vectorA}[1]{\vec{#1}} % arrow\)
\( \newcommand{\vectorAt}[1]{\vec{\text{#1}}} % arrow\)
\( \newcommand{\vectorB}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vectorC}[1]{\textbf{#1}} \)
\( \newcommand{\vectorD}[1]{\overrightarrow{#1}} \)
\( \newcommand{\vectorDt}[1]{\overrightarrow{\text{#1}}} \)
\( \newcommand{\vectE}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash{\mathbf {#1}}}} \)
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\(\newcommand{\avec}{\mathbf a}\) \(\newcommand{\bvec}{\mathbf b}\) \(\newcommand{\cvec}{\mathbf c}\) \(\newcommand{\dvec}{\mathbf d}\) \(\newcommand{\dtil}{\widetilde{\mathbf d}}\) \(\newcommand{\evec}{\mathbf e}\) \(\newcommand{\fvec}{\mathbf f}\) \(\newcommand{\nvec}{\mathbf n}\) \(\newcommand{\pvec}{\mathbf p}\) \(\newcommand{\qvec}{\mathbf q}\) \(\newcommand{\svec}{\mathbf s}\) \(\newcommand{\tvec}{\mathbf t}\) \(\newcommand{\uvec}{\mathbf u}\) \(\newcommand{\vvec}{\mathbf v}\) \(\newcommand{\wvec}{\mathbf w}\) \(\newcommand{\xvec}{\mathbf x}\) \(\newcommand{\yvec}{\mathbf y}\) \(\newcommand{\zvec}{\mathbf z}\) \(\newcommand{\rvec}{\mathbf r}\) \(\newcommand{\mvec}{\mathbf m}\) \(\newcommand{\zerovec}{\mathbf 0}\) \(\newcommand{\onevec}{\mathbf 1}\) \(\newcommand{\real}{\mathbb R}\) \(\newcommand{\twovec}[2]{\left[\begin{array}{r}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\ctwovec}[2]{\left[\begin{array}{c}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\threevec}[3]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\cthreevec}[3]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\fourvec}[4]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\cfourvec}[4]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\fivevec}[5]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\cfivevec}[5]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\mattwo}[4]{\left[\begin{array}{rr}#1 \amp #2 \\ #3 \amp #4 \\ \end{array}\right]}\) \(\newcommand{\laspan}[1]{\text{Span}\{#1\}}\) \(\newcommand{\bcal}{\cal B}\) \(\newcommand{\ccal}{\cal C}\) \(\newcommand{\scal}{\cal S}\) \(\newcommand{\wcal}{\cal W}\) \(\newcommand{\ecal}{\cal E}\) \(\newcommand{\coords}[2]{\left\{#1\right\}_{#2}}\) \(\newcommand{\gray}[1]{\color{gray}{#1}}\) \(\newcommand{\lgray}[1]{\color{lightgray}{#1}}\) \(\newcommand{\rank}{\operatorname{rank}}\) \(\newcommand{\row}{\text{Row}}\) \(\newcommand{\col}{\text{Col}}\) \(\renewcommand{\row}{\text{Row}}\) \(\newcommand{\nul}{\text{Nul}}\) \(\newcommand{\var}{\text{Var}}\) \(\newcommand{\corr}{\text{corr}}\) \(\newcommand{\len}[1]{\left|#1\right|}\) \(\newcommand{\bbar}{\overline{\bvec}}\) \(\newcommand{\bhat}{\widehat{\bvec}}\) \(\newcommand{\bperp}{\bvec^\perp}\) \(\newcommand{\xhat}{\widehat{\xvec}}\) \(\newcommand{\vhat}{\widehat{\vvec}}\) \(\newcommand{\uhat}{\widehat{\uvec}}\) \(\newcommand{\what}{\widehat{\wvec}}\) \(\newcommand{\Sighat}{\widehat{\Sigma}}\) \(\newcommand{\lt}{<}\) \(\newcommand{\gt}{>}\) \(\newcommand{\amp}{&}\) \(\definecolor{fillinmathshade}{gray}{0.9}\)In this section, we analyze the expected height, size, and length of the search path in a skiplist. This section requires a background in basic probability. Several proofs are based on the following basic observation about coin tosses.
Let \(T\) be the number of times a fair coin is tossed up to and including the first time the coin comes up heads. Then \(\mathrm{E}[T]=2\).
Proof. Suppose we stop tossing the coin the first time it comes up heads. Define the indicator variable
\[ I_{i} = \left\{
\begin{array}{ll}
0 & \mbox{if the coin is tossed less than $i$ times}\\
1 & \mbox{if the coin is tossed $i$ or more times}
\end{array}\right. \nonumber\]
Note that \(I_i=1\) if and only if the first \(i-1\) coin tosses are tails, so \(\mathrm{E}[I_i]=\Pr\{I_i=1\}=1/2^{i-1}\). Observe that \(T\), the total number of coin tosses, can be written as \(T=\sum_{i=1}^{\infty} I_i\). Therefore,
\[\begin{align}
\mathrm{E}[T]
&= \mathrm{E}\left[\sum_{i=1}^\infty I_i\right]\nonumber\\
&= \sum_{i=1}^\infty \mathrm{E}\left[I_i\right]\nonumber\\
&= \sum_{i=1}^\infty 1/2^{i-1}\nonumber\\
&= 1 + 1/2 + 1/4 + 1/8 + \cdots\nonumber\\
&= 2 \enspace .\nonumber
\end{align}\nonumber\]
The next two lemmata tell us that skiplists have linear size:
The expected number of nodes in a skiplist containing \(\mathtt{n}\) elements, not including occurrences of the sentinel, is \(2\mathtt{n}\).
Proof. The probability that any particular element, \(\mathtt{x}\), is included in list \(L_{\mathtt{r}}\) is \(1/2^{\mathtt{r}}\), so the expected number of nodes in \(L_{\mathtt{r}}\) is \(\mathtt{n}/2^{\mathtt{r}}\).2 Therefore, the total expected number of nodes in all lists is
\[ \sum_{\mathtt{r}=0}^\infty \mathtt{n}/2^\mathtt{r} = \mathtt{n}(1+1/2+1/4+1/8+\cdots) = 2\mathtt{n} \enspace . \nonumber\]
The expected height of a skiplist containing \(\mathtt{n}\) elements is at most \(\log \mathtt{n} + 2\).
Proof. For each \(\mathtt{r}\in\{1,2,3,\ldots,\infty\}\), define the indicator random variable
\[ I_{\mathtt{r}} = \left\{
\begin{array}{ll}
0 & \mbox{if $L_{\mathtt{r}}$ is empty} \\
1 & \mbox{if $L_{\mathtt{r}}$ is non-empty}
\end{array}\right. \nonumber\]
The height, \(\mathtt{h}\), of the skiplist is then given by
\[ \mathtt{h} = \sum_{i=1}^\infty I_{\mathtt{r}} \enspace . \nonumber\]
Note that \(I_{\mathtt{r}}\) is never more than the length, \(\vert L_{\mathtt{r}}\vert\), of \(L_{\mathtt{r}}\), so
\[ \mathrm{E}[I_{\mathtt{r}}] \le \mathrm{E}[\vert L_{\mathtt{r}}\vert] = \mathtt{n}/2^{\mathtt{r}} \enspace . \nonumber\]
Therefore, we have
\[\begin{align}
\mathrm{E}[\mathtt{h}]
&= \mathrm{E}\left[\sum_{r=1}^\infty I_{\mathtt{r}}\right]\nonumber\\
&= \sum_{\mathtt{r}=1}^{\infty} E[I_{\mathtt{r}}]\nonumber\\
&= \sum_{\mathtt{r}=1}^{\lfloor\log \mathtt{n}\rfloor} E[I_{\mathtt{r}}]
+\sum_{r=\lfloor\log \mathtt{n}\rfloor+1}^{\infty} E[I_{\mathtt{r}}]\nonumber\\
&\le \sum_{\mathtt{r}=1}^{\lfloor\log \mathtt{n}\rfloor} 1 +
\sum_{r=\lfloor\log \mathtt{n}\rfloor+1}^{\infty} \mathtt{n}/2^{\mathtt{r}}\nonumber\\
&\le \log \mathtt{n} + \sum_{\mathtt{r}=0}^\infty 1/2^{\mathtt{r}}\nonumber\\
&= \log \mathtt{n} + 2 \enspace .\nonumber
\end{align}\nonumber\]
The expected number of nodes in a skiplist containing \(\mathtt{n}\) elements, including all occurrences of the sentinel, is \(2\mathtt{n}+O(\log \mathtt{n})\).
Proof. By Lemma \(\PageIndex{2}\), the expected number of nodes, not including the sentinel, is \(2\mathtt{n}\). The number of occurrences of the sentinel is equal to the height, \(\mathtt{h}\), of the skiplist so, by Lemma \(\PageIndex{3}\) the expected number of occurrences of the sentinel is at most \(\log \mathtt{n}+2 = O(\log \mathtt{n})\).
Lemma \(\PageIndex{5}\).
The expected length of a search path in a skiplist is at most \(2\log \mathtt{n} + O(1)\).
Proof. The easiest way to see this is to consider the reverse search path for a node, \(\mathtt{x}\). This path starts at the predecessor of \(\mathtt{x}\) in \(L_0\). At any point in time, if the path can go up a level, then it does. If it cannot go up a level then it goes left. Thinking about this for a few moments will convince us that the reverse search path for \(\mathtt{x}\) is identical to the search path for \(\mathtt{x}\), except that it is reversed.
The number of nodes that the reverse search path visits at a particular level, \(\mathtt{r}\), is related to the following experiment: Toss a coin. If the coin comes up as heads, then move up and stop. Otherwise, move left and repeat the experiment. The number of coin tosses before the heads represents the number of steps to the left that a reverse search path takes at a particular level.3 Lemma \(\PageIndex{1}\) tells us that the expected number of coin tosses before the first heads is 1.
Let \(S_{\mathtt{r}}\) denote the number of steps the forward search path takes at level \(\mathtt{r}\) that go to the right. We have just argued that \(\mathrm{E}[S_{\mathtt{r}}]\le 1\). Furthermore, \(S_{\mathtt{r}}\le \vert L_{\mathtt{r}}\vert\), since we can't take more steps in \(L_{\mathtt{r}}\) than the length of \(L_{\mathtt{r}}\), so
\[ \mathrm{E}[S_{\mathtt{r}}] \le \mathrm{E}[\vert L_{\mathtt{r}}\vert] = \mathtt{n}/2^{\mathtt{r}} \enspace . \nonumber\]
We can now finish as in the proof of Lemma \(\PageIndex{3}\). Let \(S\) be the length of the search path for some node, \(\mathtt{u}\), in a skiplist, and let \(\mathtt{h}\) be the height of the skiplist. Then
\[\begin{align}
\mathrm{E}[S]
&= \mathrm{E}\left[ \mathtt{h} + \sum_{\mathtt{r}=0}^\infty S_{\mathtt{r}} \right]\nonumber\\
&= \mathrm{E}[\mathtt{h}] + \sum_{\mathtt{r}=0}^\infty \mathrm{E}[S_{\mathtt{r}}]\nonumber\\
&= \mathrm{E}[\mathtt{h}] + \sum_{\mathtt{r}=0}^{\lfloor\log \mathtt{n}\rfloor} E[S_{\mathtt{r}}]
+\sum_{r=\lfloor\log \mathtt{n}\rfloor+1}^\infty \mathrm{E}[S_{\mathtt{r}}]\nonumber\\
&\le \mathrm{E}[\mathtt{h}] + \sum_{\mathtt{r}=0}^{\lfloor\log \mathtt{n}\rfloor} 1 +
\sum_{r=\lfloor\log \mathtt{n}\rfloor+1}^\infty \mathtt{n}/2^{\mathtt{r}}\nonumber\\
&\le \mathrm{E}[\mathtt{h}]
+ \sum_{\mathtt{r}=0}^{\lfloor\log \mathtt{n}\rfloor} 1
+ \sum_{\mathtt{r}=0}^{\infty} 1/2^{\mathtt{r}}\nonumber\\
&\le \mathrm{E}[\mathtt{h}] + \sum_{\mathtt{r}=0}^{\lfloor\log \mathtt{n}\rfloor} 1
+ \sum_{\mathtt{r}=0}^{\infty} 1/2^{\mathtt{r}}\nonumber\\
&\le \mathrm{E}[\mathtt{h}] + \log \mathtt{n} + 3\nonumber\\
&\le 2\log \mathtt{n} + 5 \enspace .\nonumber
\end{align}\nonumber\]
The following theorem summarizes the results in this section:
Theorem \(\PageIndex{1}\).
A skiplist containing \(\mathtt{n}\) elements has expected size \(O(\mathtt{n})\) and the expected length of the search path for any particular element is at most \(2\log \mathtt{n} + O(1)\).
Footnotes
2See Section 1.3.4 to see how this is derived using indicator variables and linearity of expectation.
3Note that this might overcount the number of steps to the left, since the experiment should end either at the first heads or when the search path reaches the sentinel, whichever comes first. This is not a problem since the lemma is only stating an upper bound.