跳錶
為什麼選擇跳錶
目前經常使用的平衡資料結構有:B樹,紅黑樹,AVL樹,Splay Tree, Treep等。
想象一下,給你一張草稿紙,一隻筆,一個編輯器,你能立即實現一顆紅黑樹,或者AVL樹
出來嗎? 很難吧,這需要時間,要考慮很多細節,要參考一堆演算法與資料結構之類的樹,
還要參考網上的程式碼,相當麻煩。
用跳錶吧,跳錶是一種隨機化的資料結構,目前開源軟體 Redis 和 LevelDB 都有用到它,
它的效率和紅黑樹以及 AVL 樹不相上下,但跳錶的原理相當簡單,只要你能熟練操作連結串列,
就能輕鬆實現一個 SkipList。
有序表的搜尋
考慮一個有序表:
從該有序表中搜尋元素 < 23, 43, 59 > ,需要比較的次數分別為 < 2, 4, 6 >,總共比較的次數
為 2 + 4 + 6 = 12 次。有沒有優化的演算法嗎? 連結串列是有序的,但不能使用二分查詢。類似二叉
搜尋樹,我們把一些節點提取出來,作為索引。得到如下結構:
這裡我們把 < 14, 34, 50, 72 > 提取出來作為一級索引,這樣搜尋的時候就可以減少比較次數了。
我們還可以再從一級索引提取一些元素出來,作為二級索引,變成如下結構:
這裡元素不多,體現不出優勢,如果元素足夠多,這種索引結構就能體現出優勢來了。
這基本上就是跳錶的核心思想,其實也是一種通過“空間來換取時間”的一個演算法,通過在每個節點中增加了向前的指標,從而提升查詢的效率。
跳錶
下面的結構是就是跳錶:
其中 -1 表示 INT_MIN, 連結串列的最小值,1 表示 INT_MAX,連結串列的最大值。
跳錶具有如下性質:
(1) 由很多層結構組成
(2) 每一層都是一個有序的連結串列
(3) 最底層(Level 1)的連結串列包含所有元素
(4) 如果一個元素出現在 Level i 的連結串列中,則它在 Level i 之下的連結串列也都會出現。
(5) 每個節點包含兩個指標,一個指向同一連結串列中的下一個元素,一個指向下面一層的元素。
跳錶的搜尋
例子:查詢元素 117
(1) 比較 21, 比 21 大,往後面找
(2) 比較 37, 比 37大,比連結串列最大值小,從 37 的下面一層開始找
(3) 比較 71, 比 71 大,比連結串列最大值小,從 71 的下面一層開始找
(4) 比較 85, 比 85 大,從後面找
(5) 比較 117, 等於 117, 找到了節點。
具體的搜尋演算法如下:
C程式碼
跳錶的插入
先確定該元素要佔據的層數 K(採用丟硬幣的方式,這完全是隨機的)
然後在 Level 1 ... Level K 各個層的連結串列都插入元素。
例子:插入 119, K = 2
如果 K 大於連結串列的層數,則要新增新的層。
例子:插入 119, K = 4
丟硬幣決定 K
插入元素的時候,元素所佔有的層數完全是隨機的,通過一下隨機演算法產生:
C程式碼
相當與做一次丟硬幣的實驗,如果遇到正面,繼續丟,遇到反面,則停止,
用實驗中丟硬幣的次數 K 作為元素佔有的層數。顯然隨機變數 K 滿足引數為 p = 1/2 的幾何分佈,
K 的期望值 E[K] = 1/p = 2. 就是說,各個元素的層數,期望值是 2 層。
跳錶的高度。
n 個元素的跳錶,每個元素插入的時候都要做一次實驗,用來決定元素佔據的層數 K,
跳錶的高度等於這 n 次實驗中產生的最大 K,待續。。。
跳錶的空間複雜度分析
根據上面的分析,每個元素的期望高度為 2, 一個大小為 n 的跳錶,其節點數目的
期望值是 2n。
跳錶的刪除
在各個層中找到包含 x 的節點,使用標準的 delete from list 方法刪除該節點。
例子:刪除 71
相關文章
- 跳錶實現
- 跳錶(SkipList)原理篇
- 跳錶 | 會跳的連結串列真的非常diao
- 資料結構之跳錶資料結構
- LSM-Tree - LevelDb Skiplist跳錶
- 聊聊Mysql索引和redis跳錶MySql索引Redis
- 連結串列中的跳錶小結
- 來一起寫一個跳錶吧
- Golang 實現 Redis(5): 使用跳錶實現 SortedSetGolangRedis
- 資料結構和演算法之——跳錶資料結構演算法
- 資料結構與演算法-跳錶《八》資料結構演算法
- 深入理解跳錶及其在Redis中的應用Redis
- 如何用 30s 給面試官講清楚跳錶面試
- 資料結構與演算法整理總結---跳錶資料結構演算法
- 自己動手實現java資料結構(九) 跳錶Java資料結構
- JDK原始碼閱讀(十二) : 基於跳錶的併發容器——ConcurrentSkipListMapJDK原始碼
- ??Java開發者的Python快速進修指南:實戰之簡易跳錶JavaPython
- Java開發者的Python快速進修指南:實戰之跳錶pro版本JavaPython
- 7.跳錶:各方面都非常優秀的動態資料結構資料結構
- LevelDB學習筆記 (3): 長文解析memtable、跳錶和記憶體池Arena筆記記憶體
- 上手做一個華為鴻蒙手錶應用 3 - 兩頁面互相跳轉鴻蒙
- 跳錶--怎麼讓一個有序連結串列能夠進行"二分"查詢?
- Redis常見面試題:ZSet底層資料結構,SDS、壓縮列表ZipList、跳錶SkipListRedis面試題資料結構
- 太刺激了,面試官讓我手寫跳錶,而我用兩種實現方式吊打了TA!面試
- 檢視錶大小
- JavaScript 秒錶效果JavaScript
- MySQL 聯錶速查MySql
- 智慧手錶API介面API
- oracle 左錶連結Oracle
- 小米手錶Color與華米手錶GTR哪個好?小米Color與華米GTR手錶區別對比
- [跳一跳] Nodejs + Opencv 版NodeJSOpenCV
- CCF跳一跳Python程式Python
- 2.陣列、連結串列、跳錶的基本實現和特性 (7 天掌握演算法面試必考知識點)陣列演算法面試
- 手錶廠家一覽
- oracle 檢視錶空間Oracle
- openGauss 對錶執行VACUUM
- 檢視錶的定義
- JavaScript 秒錶效果詳解JavaScript