跳表是什么
跳表是在雙向鏈表(什么是鏈表)之上加多層索引構成的,相對於雙向鏈表,支持快速查找,更新,刪除,所以適用於需求靈活的場景。
查找某一個數據時,先在索引里面查找出一個大的范圍,然后再下降到原始鏈表中精確查找。
因為加一層索引后,查找一個結點需要遍歷的次數減少了,所以查找效率大大提升。【空間換時間】
針對鏈表長度比較大的時候,構建索引查找效率的提升就會非常明顯。
注意⚠️:第1層鏈表不是一個單向鏈表,而是一個有序的雙向鏈表,為了方便以倒序方式獲取一個范圍內的元素。
跳表的特點
(1) 跳表結合了鏈表和類似二分查找的思想;
(2) 有很多層結構,由原始鏈表和一些通過“跳躍”生成的鏈表組成;
(3) 每一層都是一個有序的鏈表;
(4) 最底層(Level 1)的鏈表包含所有元素,越上層“跳躍”的越高,元素(索引)越少;
(5) 查找時從頂層向下,不斷縮小搜索范圍;
(6) 上層鏈表是下層鏈表的子序列;
(7) 每個節點包含兩個指針,一個指向同一鏈表中的下一個元素,一個指向下面一層的元素。
跳表的搜索
鏈表是有序的,但不能使用二分查找("類似"二分法)。類似二叉搜索樹,我們把一些結點提取出來,作為索引。在實際開發中,原始鏈表中存儲的可能是很大的對象,而索引結點只需要存儲關鍵值和幾個指針,其額外占用的空間可以被忽略掉。
注意:每隔兩個節點往上提升一層建立索引只是理想情況,實際上是通過隨機層數K(丟硬幣決定 K,隨機算法)來實現。
跳表的時間復雜度
跳表各個操作的時間復雜度為:O(logn)。
跳表的應用
跳表最經典的應用就是在Redis中實現有序集合(ZSet)。
跳表在Redis中的唯一作用也就是對該數據類型的實現,但是除了使用跳表作為有序集類型的底層數據結構外,還使用了字典來構成有序集。
為什么使用跳表作為ZSet實現的索引,而不使用紅黑樹、B+樹?(點擊查看)