查找算法之平衡查找树
前面介紹的算法在最壞的情況下還是很糟糕。這次會介紹一種二分查找樹并能保證無論如何構(gòu)造它,他的運(yùn)行時間都是對數(shù)級別的。理想情況下我們希望能夠保持二分查找樹的平衡性。但是,在動態(tài)插入中保證樹的完美平衡的代價太高了。
2-3查找樹
我們將一棵標(biāo)準(zhǔn)的二叉查找樹中的節(jié)點(diǎn)成為2-節(jié)點(diǎn)(含有一個鍵和兩條鏈接),現(xiàn)在我們引入3-節(jié)點(diǎn),它含有兩個鍵和三條鏈接。
查找
要判斷一個鍵是否在樹中,我們先將它和根節(jié)點(diǎn)中的鍵比較。如果它和其中任意一個相等,查找命中;否則我們就根據(jù)比較的結(jié)果找到指向相應(yīng)區(qū)間的鏈接,并在其指向的子樹中遞歸的遞歸查找。如果這個是空鏈接,查找未命中。
插入
樹的平衡:
任何節(jié)點(diǎn)的左子樹和右子樹之間的高度差不能超過1。
上圖中(a)是平衡的,(b)是不平衡的,很顯然,一個完全不平衡的樹,在做查找時,它就是線性級別的性能,而平衡的二叉樹,同樣的數(shù)據(jù)量,但有效利用了平衡性,它的查找性能則能降到對數(shù)級別。
而動態(tài)平衡要求的是要在插入是,時刻保持樹的平衡性。
分為幾種情況:
向2-節(jié)點(diǎn)中插入新鍵
若未命中的查找結(jié)束于一個2-節(jié)點(diǎn),我們只要把這個2節(jié)點(diǎn)替換為一個3節(jié)點(diǎn)就可以了。
向一棵只有3-節(jié)點(diǎn)的樹中插入新鍵
為了新鍵的插入,首先臨時將新鍵存入該節(jié)點(diǎn)中,使之成為一個4-節(jié)點(diǎn)。然后很容易就將他轉(zhuǎn)化為一棵由3個2-節(jié)點(diǎn)組成的2-3樹。
向一棵父節(jié)點(diǎn)為2-節(jié)點(diǎn)的3-節(jié)點(diǎn)中插入新鍵
假設(shè)未命中的查找結(jié)束于3-節(jié)點(diǎn),而他的父節(jié)點(diǎn)是2-節(jié)點(diǎn)。我們先像剛才一樣構(gòu)造一個臨時的4-節(jié)點(diǎn)并將其分解,但此時我們不會為中鍵創(chuàng)造一個新的節(jié)點(diǎn),而是將其移動至原來的父節(jié)點(diǎn)中。
向一棵父節(jié)點(diǎn)為3-節(jié)點(diǎn)的3-節(jié)點(diǎn)中插入新鍵
假設(shè)未命中的查找結(jié)束于一個父節(jié)點(diǎn)為3-節(jié)點(diǎn)的節(jié)點(diǎn),我們再次和剛才一樣構(gòu)造一個臨時的4-節(jié)點(diǎn)并分解它,然后將他的中鍵插入它的父節(jié)點(diǎn)中,但父節(jié)點(diǎn)也是一個3-節(jié)點(diǎn),因此我們再用這個中鍵構(gòu)造一個臨時的4-節(jié)點(diǎn),然后在這個節(jié)點(diǎn)上進(jìn)行相同的變換,就這樣一直向上不斷分解臨時4-節(jié)點(diǎn)并將中鍵插入到更高層的父節(jié)點(diǎn)。
分解根節(jié)點(diǎn)
構(gòu)造二叉樹
總結(jié)
盡管我們可以用不同的數(shù)據(jù)類型表示2-節(jié)點(diǎn)和3-節(jié)點(diǎn),但是這種直白的表示方法實(shí)現(xiàn)大多數(shù)操作并不方便,因?yàn)樾枰幚淼那闆r太多。我們需要維護(hù)兩種不同類型的節(jié)點(diǎn),將被查找的鍵和節(jié)點(diǎn)中的每個鍵進(jìn)行比較,將鏈接和其他信息從一種節(jié)點(diǎn)復(fù)制到另一種節(jié)點(diǎn),將節(jié)點(diǎn)從一種數(shù)據(jù)類型轉(zhuǎn)換到另一種類型,等等。不僅需要大量的代碼,而且產(chǎn)生的額外開銷可能會使算法比標(biāo)準(zhǔn)二叉樹更慢。
總結(jié)
以上是生活随笔為你收集整理的查找算法之平衡查找树的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 老司机教你一步步删掉艳照
- 下一篇: 实验四:配置端口聚合提供冗余备份链路