红黑树(RB-Tree)比AVL强在哪?
前言
以前本科同學(xué)在找工作的時(shí)候,就被面試官問(wèn)到過(guò)關(guān)于紅黑樹(shù)的問(wèn)題。因?yàn)楫?dāng)時(shí)我的知識(shí)面不廣,所以也不知道紅黑樹(shù)是個(gè)什么東西,也沒(méi)放在心上。在看過(guò)了STL源碼后才知道原來(lái)有很多底層實(shí)現(xiàn)都用的紅黑樹(shù)。簡(jiǎn)單的查閱了相關(guān)概念后,我覺(jué)得它和AVL沒(méi)啥差別,而且AVL更好理解,平衡性也更優(yōu),那為什么還要使用紅黑樹(shù)?
于是我開(kāi)始查閱相關(guān)資料,百度紅黑樹(shù)的概念及性質(zhì),在網(wǎng)上看到了一些回復(fù),感覺(jué)講的很有道理。但我沒(méi)有簡(jiǎn)單的接受他們的答案,而是在Github上找代碼,以驗(yàn)證他們所說(shuō)的紅黑樹(shù)的優(yōu)勢(shì)。本篇博文不向各位介紹紅黑樹(shù)原理及旋轉(zhuǎn)操作的過(guò)程,只介紹一些基本的概念,然后通過(guò)使用AVL和RB-Tree處理數(shù)據(jù)的時(shí)間驗(yàn)證紅黑樹(shù)的優(yōu)勢(shì)。
?
基本概念
AVL樹(shù)是最先發(fā)明的自平衡二叉查找樹(shù)。在AVL樹(shù)中任何節(jié)點(diǎn)的兩個(gè)子樹(shù)的高度最大差別為1,所以它也被稱(chēng)為高度平衡樹(shù)。增加和刪除可能需要通過(guò)一次或多次樹(shù)旋轉(zhuǎn)來(lái)重新平衡這個(gè)樹(shù)。查找、插入和刪除在平均和最壞情況下都是O(logn)。
紅黑樹(shù)(Red Black Tree)是一種自平衡二叉查找樹(shù),是在計(jì)算機(jī)科學(xué)中用到的一種數(shù)據(jù)結(jié)構(gòu),典型的用途是實(shí)現(xiàn)關(guān)聯(lián)數(shù)組。紅黑樹(shù)和AVL樹(shù)類(lèi)似,都是在進(jìn)行插入和刪除操作時(shí)通過(guò)特定操作保持二叉查找樹(shù)的平衡,從而獲得較高的查找性能。它雖然是復(fù)雜的,但它的最壞情況運(yùn)行時(shí)間也是非常良好的,并且在實(shí)踐中是高效的:它可以在O(logn)時(shí)間內(nèi)做查找,插入和刪除。
紅黑樹(shù)是每個(gè)節(jié)點(diǎn)都帶有顏色屬性的二叉查找樹(shù),顏色或紅色或黑色。在二叉查找樹(shù)強(qiáng)制一般要求以外,對(duì)于任何有效的紅黑樹(shù)有如下的額外要求:
性質(zhì)1. 節(jié)點(diǎn)是紅色或黑色。
性質(zhì)2. 根節(jié)點(diǎn)是黑色。
性質(zhì)3 每個(gè)紅色節(jié)點(diǎn)的兩個(gè)子節(jié)點(diǎn)都是黑色。(從每個(gè)葉子到根的所有路徑上不能有兩個(gè)連續(xù)的紅色節(jié)點(diǎn))
性質(zhì)4. 從任一節(jié)點(diǎn)到其每個(gè)葉子的所有路徑都包含相同數(shù)目的黑色節(jié)點(diǎn)。
從以上概念和性質(zhì)可知紅黑樹(shù)不是高度平衡的二叉樹(shù),它用非嚴(yán)格的平衡結(jié)構(gòu)來(lái)?yè)Q取增刪節(jié)點(diǎn)時(shí)旋轉(zhuǎn)次數(shù)的降低。雖然它放棄了嚴(yán)格的高度平衡,但完成查詢(xún)、插入、刪除操作的時(shí)間復(fù)雜性度依然為O(logn)。此外,由算法導(dǎo)論里的分析,我們可以得到這么一個(gè)結(jié)論:任何不平衡都會(huì)在三次旋轉(zhuǎn)之內(nèi)解決。
?
CSDN、知乎上的回答
1. 如果插入一個(gè)node引起了樹(shù)的不平衡,AVL和RB-Tree都是最多只需要2次旋轉(zhuǎn)操作,即兩者都是O(1);但是在刪除node引起樹(shù)的不平衡時(shí),最壞情況下,AVL需要維護(hù)從被刪node到root這條路徑上所有node的平衡性,因此需要旋轉(zhuǎn)的量級(jí)O(logn),而RB-Tree最多只需3次旋轉(zhuǎn),只需要O(1)的復(fù)雜度。
2. 其次,AVL的結(jié)構(gòu)相較RB-Tree來(lái)說(shuō)更為平衡,在插入和刪除node更容易引起Tree的unbalance,因此在大量數(shù)據(jù)需要插入或者刪除時(shí),AVL需要rebalance的頻率會(huì)更高。因此,RB-Tree在需要大量插入和刪除node的場(chǎng)景下,效率更高。自然,由于AVL高度平衡,因此AVL的search效率更高。
3. map的實(shí)現(xiàn)只是折衷了兩者在search、insert以及delete下的效率。總體來(lái)說(shuō),RB-tree的統(tǒng)計(jì)性能是高于AVL的。
4.紅黑樹(shù)的查詢(xún)性能略微遜色于AVL樹(shù),因?yàn)樗萢vl樹(shù)會(huì)稍微不平衡最多一層,也就是說(shuō)紅黑樹(shù)的查詢(xún)性能只比相同內(nèi)容的avl樹(shù)最多多一次比較,但是,紅黑樹(shù)在插入和刪除上完爆avl樹(shù),avl樹(shù)每次插入刪除會(huì)進(jìn)行大量的平衡度計(jì)算,而紅黑樹(shù)為了維持紅黑性質(zhì)所做的紅黑變換和旋轉(zhuǎn)的開(kāi)銷(xiāo),相較于avl樹(shù)為了維持平衡的開(kāi)銷(xiāo)要小得多
注意:因?yàn)槊看尾迦牒蛣h除都要進(jìn)行查找元素的操作,所以插入和刪除的時(shí)間復(fù)雜性的都是O(logn),其實(shí)插入和刪除操作本身的時(shí)間復(fù)雜度是O(1)。
?
實(shí)驗(yàn)驗(yàn)證
以上代碼是我在Github上找到的,作者的目的是實(shí)現(xiàn)和Linux下的紅黑樹(shù)一樣快的AVL。其中分析了AVL和紅黑樹(shù)在處理數(shù)據(jù)時(shí)的性能,也是驗(yàn)證上述回答的非常好的一個(gè)實(shí)驗(yàn)。實(shí)驗(yàn)分為靜態(tài)內(nèi)存評(píng)估和動(dòng)態(tài)內(nèi)存評(píng)估,而我只關(guān)注于兩者在插入、查找和刪除元素所耗費(fèi)的時(shí)間上。網(wǎng)址在文章結(jié)尾。
靜態(tài)內(nèi)存情況下運(yùn)行結(jié)果:
RB-Tree和AVL在處理10000000個(gè)結(jié)點(diǎn)時(shí)的數(shù)據(jù)對(duì)比: insert time: 3400ms, height=32 insert time: 3618ms, height=27search time: 2790ms error=0 search time: 2912ms error=0delete time: 510ms delete time: 612mstotal: 6700ms total: 7142msRB-Tree和AVL在處理1000000個(gè)結(jié)點(diǎn)時(shí)的數(shù)據(jù)對(duì)比: insert time: 292ms, height=26 insert time: 315ms, height=24search time: 167ms error=0 search time: 170ms error=0delete time: 56ms delete time: 62mstotal: 515ms total: 547ms
?
動(dòng)態(tài)內(nèi)存情況下運(yùn)行結(jié)果:
RB-Tree和AVL在處理10000000個(gè)結(jié)點(diǎn)時(shí)的數(shù)據(jù)對(duì)比: insert time: 3832ms, height=32 insert time: 4138ms, height=27search time: 2901ms error=0 search time: 2945ms error=0delete time: 484ms delete time: 574mstotal: 7217ms total: 7657msRB-Tree和AVL在處理1000000個(gè)結(jié)點(diǎn)時(shí)的數(shù)據(jù)對(duì)比: insert time: 342ms, height=26 insert time: 373ms, height=24search time: 187ms error=0 search time: 171ms error=0delete time: 44ms delete time: 53mstotal: 573ms total: 597ms?
分析
以下是程序運(yùn)行時(shí)間的柱狀圖,這里只做了靜態(tài)內(nèi)存的圖表,因?yàn)闊o(wú)論是靜態(tài)還是動(dòng)態(tài),程序處理數(shù)據(jù)的優(yōu)劣情況是一樣的。
從上面的兩張圖片可以看出,隨著數(shù)據(jù)量的增加,RB-Tree的優(yōu)勢(shì)更為明顯。當(dāng)這兩個(gè)樹(shù)型結(jié)構(gòu)在處理百萬(wàn)元素的時(shí)候,在刪除方面,RB-Tree比AVL快6ms,但兩者的刪除操作總共花費(fèi)時(shí)間為60ms左右。相比插入和搜索時(shí)間占比而言,在刪除操作方面,RB-Tree的表現(xiàn)更好。當(dāng)數(shù)據(jù)量增加了一個(gè)量級(jí)后,RB-Tree的刪除操作比AVL快將近100ms(節(jié)約的時(shí)間占比變高)。所以當(dāng)處理大量數(shù)據(jù),且刪除操作較為頻繁的情況下,RB-Tree的性能要優(yōu)于AVL。綜上所述,如果你的應(yīng)用中,查詢(xún)的次數(shù)遠(yuǎn)遠(yuǎn)大于插入和刪除,那么應(yīng)該選擇AVL。如果搜索,插入刪除次數(shù)幾乎差不多,則應(yīng)該選擇RB-Tree。
?
結(jié)論
結(jié)合實(shí)驗(yàn)和網(wǎng)友的回答,可知AVL在查詢(xún)上是優(yōu)于RB-Tree,但在刪除元素方面,RB-Tree所花費(fèi)的時(shí)間要小于AVL的用時(shí)。這里我不能對(duì)插入效率做出評(píng)判,因?yàn)?/span>插入一個(gè)結(jié)點(diǎn)引起的不平衡,AVL和RB-Tree都是最多只需要2次旋轉(zhuǎn)操作,所以從理論上講,兩者的時(shí)間應(yīng)該是差不多的(或者多次實(shí)驗(yàn)的好壞是交替出現(xiàn)的)。但實(shí)驗(yàn)數(shù)據(jù)往往是RB-Tree優(yōu)于AVL,這點(diǎn)和代碼有關(guān)。在尋找AVL和RB-Tree做對(duì)比實(shí)驗(yàn)的代碼時(shí),我就發(fā)現(xiàn)了網(wǎng)上所給的代碼效率參差不齊。原本我使用的是嚴(yán)蔚敏數(shù)據(jù)結(jié)構(gòu)的AVL代碼做實(shí)驗(yàn),但是嚴(yán)奶奶的書(shū)上沒(méi)有給出刪除操作的代碼,所以我就在網(wǎng)上找完整的代碼。在找代碼的過(guò)程中發(fā)現(xiàn),有很多代碼能用,但效率太低了(而且我想找的是AVL和RB-Tree運(yùn)行時(shí)間差距不是很大的代碼)。我甚至還發(fā)了一條Blink求助網(wǎng)友,但是沒(méi)有得到有效的回應(yīng),最后終于在Github上找到了可以用于驗(yàn)證以上回答的代碼。可能各位也會(huì)對(duì)代碼本身有疑問(wèn),但這是我目前找到的最符合需求的代碼了。
?
參考:
https://github.com/skywind3000/avlmini
https://blog.csdn.net/mmshixing/article/details/51692892
http://www.zhihu.com/question/20545708/answer/58717264
http://www.zhihu.com/question/43744788/answer/9825888
總結(jié)
以上是生活随笔為你收集整理的红黑树(RB-Tree)比AVL强在哪?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: TCP三次握手,握的是啥?
- 下一篇: 进程间通信:管道和命名管道(FIFO)