日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数据结构三——跳表

發(fā)布時間:2023/12/10 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构三——跳表 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章出處:極客時間《數(shù)據(jù)結(jié)構(gòu)和算法之美》-作者:王爭。該系列文章是本人的學(xué)習(xí)筆記。

跳表的由來

說明:圖片來自極客時間
由來
  二分查找的數(shù)據(jù)結(jié)構(gòu)是數(shù)組,利用數(shù)組隨機訪問的特定查找的時間復(fù)雜度是O(logn)。如果數(shù)據(jù)結(jié)構(gòu)是鏈表,可以達(dá)到這樣的速度嗎?答案是可以的。只是要改造。改造之后的結(jié)構(gòu)就是跳表,是一種動態(tài)數(shù)據(jù)結(jié)構(gòu),可以支持快速的插入、刪除、查找、按范圍查找。功能類似于紅黑樹。Redis中的有序集合使用的就是跳表。

跳表的結(jié)構(gòu)


  對于單鏈表來說,存儲的數(shù)據(jù)是有序的,想要查找某個數(shù),時間復(fù)雜度是O(n)。如果對單鏈表建一個一級“索引”,就是說每兩個節(jié)點提取一個節(jié)點。提取出的節(jié)點有一個down指針指向原始鏈表中的同一個節(jié)點。
  
  現(xiàn)在要查找數(shù)據(jù)16,那么查找路徑是:1,4,7,9,13,13(原始鏈表),16。查找7個節(jié)點。單鏈表查找16需要查找10個節(jié)點。
  如果對一級索引再建“索引”,形成二級索引。
  
  現(xiàn)在要查找數(shù)據(jù)16,那么查找路徑是:1,7,13,13,13,16。查找6個節(jié)點。
  當(dāng)n小的時候,減少的節(jié)點數(shù)量不明顯。如果是n=64。建5級索引。
  
  現(xiàn)在查找62需要11個節(jié)點,路徑是1,33,33,49,49,57,57,61,61,61,62。原來需要62個節(jié)點。提升效果很明顯。當(dāng)n越大,提升效果越明顯。
  跳表=鏈表+多級索引

跳表的時空復(fù)雜度

時間復(fù)雜度
 當(dāng)節(jié)點個數(shù)為n的時候,跳表會建幾層索引呢?第1級索引節(jié)點個數(shù)n2\dfrac{n}{2}2n?,第2級索引節(jié)點個數(shù)n4\dfrac{n}{4}4n?,第k級索引節(jié)點個數(shù)n2k\dfrac{n}{2^k}2kn?。最上面一層索引節(jié)點個數(shù)是2。也就是說2=n2l2=\dfrac{n}{2^l}2=2ln?,l+1=log2nl+1=log_2nl+1=log2?n,l=log2n?1l=log_2n-1l=log2?n?1。再加上原始鏈表層,跳表有log2nlog_2nlog2?n層,記為logn。
 每一層最多查詢的節(jié)點個數(shù)是3。因為在建每一層索引的時候,是每2個數(shù)據(jù)建一個節(jié)點。例如查找數(shù)據(jù)x,在第k層發(fā)現(xiàn)y&lt;x,x&gt;zy&lt;x,x&gt;zy<x,x>z,所以通過y的down指針向,從第k層走到第k-1層。而y和z節(jié)點之間最多有3個節(jié)點(包含y和z)。
 
 那么跳表的時間復(fù)雜度就是O(logn)。和二分查找是同樣的查找效率。
空間復(fù)雜度
 鏈表的查找速度和二分一樣,這是需要付出空間代價的。也就是以空間換時間。那么額外需要多少空間呢?n2+n4+n8+...+2=n\dfrac{n}{2}+\dfrac{n}{4}+\dfrac{n}{8}+...+2=n2n?+4n?+8n?+...+2=n,等比數(shù)列求和。所以空間復(fù)雜度是O(n)。

跳表插入和刪除

插入
 對于插入來講,為了維持鏈表的有序性,在插入一個數(shù)據(jù)的時候需要先查找到插入的位置。
 
 例如在鏈表中插入6,需要查找插入位置,查找節(jié)點1,1,4,4,5,時間復(fù)雜度和查找一個數(shù)字類似,O(logn)。鏈表的插入操作是O(1),所以整體插入操作時間復(fù)雜度O(logn)。
刪除
 刪除操作不僅要刪除鏈表層,同時需要刪除索引層的節(jié)點。時間復(fù)雜度O(logn)。

動態(tài)索引表更新

索引更新
 當(dāng)不斷插入數(shù)據(jù)的時候,如果不更新索引層,極端情況下跳表退化為單鏈表。當(dāng)插入數(shù)據(jù)的時候,同時更新某些索引層。至于在哪些層建索引,可以通過隨機函數(shù)來選擇。

思考題

1 redist為什么使用跳表而不是紅黑樹?
 redist的核心操作是:
 插入一個數(shù)據(jù);
 刪除一個數(shù)據(jù);
 查找一個數(shù)據(jù);
 按范圍查找一個區(qū)間內(nèi)的數(shù)據(jù);
 迭代輸出有序序列
 紅黑樹效率不高的操作是:按范圍查找一個區(qū)間內(nèi)的數(shù)據(jù)。
 其他原因:跳表更容易實現(xiàn),代碼比較簡單。

2 如果每3個或者5個節(jié)點抽取一個做索引,那么跳表的時間復(fù)雜度和空間復(fù)雜度是多少呢?
如果每三個或者五個節(jié)點提取一個節(jié)點作為上級索引,那么對應(yīng)的查詢數(shù)據(jù)時間復(fù)雜度,也還是 O(logn)。其實這里的底數(shù)已經(jīng)不是2,而是3或者5。
空間復(fù)雜度,也依然是一個等比數(shù)列的和:n3+n9+n8+...+3=32(n?1)\dfrac{n}{3}+\dfrac{n}{9}+\dfrac{n}{8}+...+3=\dfrac{3}{2}(n-1)3n?+9n?+8n?+...+3=23?(n?1),記為O(n)。

總結(jié)

以上是生活随笔為你收集整理的数据结构三——跳表的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。