Redis内部数据结构-跳跃表
??? 今天學(xué)習(xí)了跳躍表,記錄一下下~??
一、跳躍表簡(jiǎn)介
?
跳躍表是一種隨機(jī)化數(shù)據(jù)結(jié)構(gòu),基于并聯(lián)的鏈表,其效率可以比擬平衡二叉樹,查找、刪除、插入等操作都可以在對(duì)數(shù)期望時(shí)間內(nèi)完成,對(duì)比平衡樹,跳躍表的實(shí)現(xiàn)要簡(jiǎn)單直觀很多。
以下是一個(gè)跳躍表的例圖(來(lái)自維基百科):
從圖中可以看出跳躍表主要有以下幾個(gè)部分構(gòu)成:
1、? 表頭head:負(fù)責(zé)維護(hù)跳躍表的節(jié)點(diǎn)指針
2、? 節(jié)點(diǎn)node:實(shí)際保存元素值,每個(gè)節(jié)點(diǎn)有一層或多層
3、? 層level:保存著指向該層下一個(gè)節(jié)點(diǎn)的指針
4、? 表尾tail:全部由null組成
跳躍表的遍歷總是從高層開始,然后隨著元素值范圍的縮小,慢慢降低到低層。
?
用大白話來(lái)解釋一下跳躍表:
如上圖,
跳躍表在redis中主要是有序表的一種底層實(shí)現(xiàn)。對(duì)于普通鏈表的查找,即使有序,我們也不能使用二分法,需要從頭開始,一個(gè)一個(gè)找,時(shí)間復(fù)雜度為O(n)。而對(duì)于跳躍表,從名字可以看出跳躍表的優(yōu)勢(shì)就在于可以跳躍。如何做到呢?在于其特殊的層設(shè)計(jì)。比如我們查找46,普通鏈表只能從頭開始查找,比對(duì)-3,2,17...直到46,要比對(duì)7次。但是對(duì)于跳躍表,我們可以從最高層開始查找:
第一步:在L4層直接與55比對(duì),發(fā)現(xiàn)大了,退回到第3層
第二步:在L3層與21比對(duì),發(fā)現(xiàn)小了,繼續(xù)往前比對(duì)55,發(fā)現(xiàn)大了,退回到第二層
第三步:在L2層與37比對(duì),發(fā)現(xiàn)小了,往前,與55比對(duì),發(fā)現(xiàn)大了,退回到第一層
第四步:在第1層,與46比對(duì),查找成功。
共比對(duì)了6次,比普通鏈表只節(jié)省了一次,似乎沒什么優(yōu)勢(shì)。但如果細(xì)想,當(dāng)鏈表比較長(zhǎng)的時(shí)候,在高層查找時(shí),跳過(guò)的元素?cái)?shù)量將相當(dāng)可觀,提速的效果將非常明顯。比如如果元素在55之后,在L4層,我們直接就跳過(guò)了7個(gè)元素,這是非常大的進(jìn)步。
?
??? 跳躍表(Skiplist)是一種隨機(jī)化數(shù)據(jù)結(jié)構(gòu),它在查找、插入、刪除等操作的期望時(shí)間復(fù)雜度都能達(dá)到對(duì)數(shù)級(jí),并且編碼相對(duì)簡(jiǎn)單許多,跳躍表目前是Redis中用于存儲(chǔ)有序集合的底層數(shù)據(jù)結(jié)構(gòu),另外可以存儲(chǔ)有序集的數(shù)據(jù)結(jié)構(gòu)是字典,Redis中還有一種底層數(shù)據(jù)結(jié)構(gòu)intset可以用來(lái)存儲(chǔ)有序整數(shù)集。
??? Redis作者通過(guò)對(duì)原有的跳躍表進(jìn)行修改,包括span的設(shè)計(jì)、score值可以重復(fù)、添加tail與backward指針等,從而實(shí)現(xiàn)了排序功能,從尾至頭反向遍歷的功能等。
?
總結(jié)
以上是生活随笔為你收集整理的Redis内部数据结构-跳跃表的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 重写navigationControll
- 下一篇: Mysql:替换某个字段中的部分字符串—