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

歡迎訪問(wèn) 生活随笔!

生活随笔

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

编程问答

数据映射--平衡二叉有序树

發(fā)布時(shí)間:2024/9/30 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据映射--平衡二叉有序树 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

http://blog.sina.com.cn/s/blog_693f08470101mnna.html

上次我們提到了使用有序的數(shù)組來(lái)進(jìn)行二分查找,從而提高映射查詢的效率,使時(shí)間復(fù)雜度從O(n)降低O(log2N).

?

本周讓我來(lái)介紹一下二叉樹。

?

一談到二叉樹,相信很多人一定會(huì)有一個(gè)疑問(wèn):?這玩意兒有什么用??(當(dāng)然這么多人里面肯定包括大學(xué)時(shí)候的我- -

?

其實(shí),我個(gè)人覺得這并不怪我們,是教科書寫的有點(diǎn)問(wèn)題,開始的時(shí)候沒有給到大家明確的學(xué)習(xí)意義,開始就去講如何遍歷,如何從樹變森林,如何做樹的前序中序后序遍歷。但這樣的學(xué)習(xí)會(huì)讓整個(gè)過(guò)程很無(wú)聊,太容易讓人放棄了。所以在今天,請(qǐng)?jiān)试S我用另外的方式來(lái)重新講解一下吧~

?

?

首先,明確一下意義,二叉樹主要用來(lái)表示樹形結(jié)構(gòu)的數(shù)據(jù),主要的應(yīng)用場(chǎng)景是,實(shí)現(xiàn)數(shù)據(jù)映射,或者實(shí)現(xiàn)壓縮算法(哈夫曼樹)。

?

下面,讓我們從二叉樹的特性,來(lái)看看二叉樹能做些什么。

1.???????有一個(gè)ROOT節(jié)點(diǎn)

意味著每一次查詢都需要從一個(gè)節(jié)點(diǎn)開始進(jìn)行,與之相對(duì)的,如果是圖類的數(shù)據(jù)結(jié)構(gòu),則起點(diǎn)是不固定的。

?

2.???????一個(gè)節(jié)點(diǎn)有兩個(gè)子節(jié)點(diǎn)。

與擁有多個(gè)子節(jié)點(diǎn)的樹相比,兩個(gè)子節(jié)點(diǎn)會(huì)讓樹變得更深,但好處我們?cè)诤竺娴亩媾判驑鋾r(shí)會(huì)看到。

?

3.???????父節(jié)點(diǎn)都有一個(gè)到子節(jié)點(diǎn)的引用(指針)。有些時(shí)候,為了遍歷方便,還需要一個(gè)從子節(jié)點(diǎn)到父節(jié)點(diǎn)的引用(指針)

有些時(shí)候,我們需要順序的遍歷一棵樹,這時(shí)候如果有了雙向指針,那么遍歷就會(huì)變得更為方便。

?

一個(gè)純粹的二叉樹,除了能支持遍歷以外,沒有什么油水,下面讓我們來(lái)看看二叉樹的最主要用途----映射?,是如何利用平衡二叉排序樹來(lái)實(shí)現(xiàn)的吧。

?

先從二叉排序樹開始說(shuō)起,所謂的二叉排序樹,其實(shí)只是在二叉樹上額外增加了一個(gè)條件,左邊的子節(jié)點(diǎn)上的數(shù)據(jù)一定比父節(jié)點(diǎn)的小,而右邊子節(jié)點(diǎn)一定比父節(jié)點(diǎn)的數(shù)據(jù)大。

我們還是用上周我們使用過(guò)的例子來(lái)做一下講解:

?

給定有序結(jié)果集S={1對(duì)應(yīng)a,2對(duì)應(yīng)b,3對(duì)應(yīng)c,4對(duì)應(yīng)e,6對(duì)應(yīng)f}?,讓我們以這個(gè)映射關(guān)系來(lái)做例子,以便大家能夠更快速的理解。

?

這樣做的最大好處么~就是可以進(jìn)行順序遍歷了。其他好處似乎是沒有。比如以下這樣的二叉樹:

?

?

?

?

?

這就是一個(gè)非常極端的情況了。也就是沒有左面的孩子,只有右面的孩子,這樣的一棵樹其實(shí)就退化成了鏈表,因?yàn)樵L問(wèn)只能從root開始,所以除了能夠提供順序遍歷之外,無(wú)法提供更多的功能了。

?

然而,如果我們?cè)偌由弦粋€(gè)條件,那么二叉排序樹就立刻能夠麻雀變鳳凰,成為我們的一種重要的實(shí)現(xiàn)映射的利器了。

這個(gè)條件,就是平衡,于是全稱就變成了:平衡二叉排序樹。我們來(lái)看看平衡的定義:

一棵空樹或它的左右兩個(gè)子樹的高度差的絕對(duì)值不超過(guò)1,并且左右兩個(gè)子樹都是一棵平衡二叉樹。

?

也就是說(shuō),除了最底層的節(jié)點(diǎn),樹的左子節(jié)點(diǎn)和右子節(jié)點(diǎn)應(yīng)該保證都有值。?則樹就會(huì)平衡,并且樹的高度是log2N

嘿嘿,看到log2N,是不是有似曾相識(shí)的感覺?沒錯(cuò),就是二分查找的時(shí)間復(fù)雜度,或者用更容易理解的一個(gè)詞的話,為了查找到指定的數(shù)據(jù)所需要遍歷節(jié)點(diǎn)的次數(shù)。

?

為什么二分查找和樹的高度在數(shù)值上如此的一致呢?這就是我們下面要重點(diǎn)分析的東西了。

?

首先來(lái)回憶一下我們?cè)谟行驍?shù)組章節(jié)

(http://blog.sina.com.cn/s/blog_693f08470101mi2o.html)里面提到的二分查找算法的必要條件吧:

1.???????數(shù)據(jù)能夠按照某種條件進(jìn)行排序??比如S={0,1,2,3,4,5,6,7,100,101,102}?就是排好序的數(shù)據(jù),左面的數(shù)據(jù)一定小于右面的。

2.???????可以通過(guò)某種方式,取出該數(shù)據(jù)集中任意子集的中間值。?比如對(duì)于S={0,1,2,3,4,5,6,7,100,101,102},取中值意味著應(yīng)該取出下標(biāo)為整數(shù)除法?(0 11)/2 = 5?的數(shù)字。?如果我們能夠快速而直接的取出這個(gè)中間值,也就是能夠快速的取出下標(biāo)為5的位置所對(duì)應(yīng)的數(shù)據(jù),那么我們就能夠進(jìn)行二分查找。

?

在平衡二叉排序樹中,上面的兩個(gè)要求是能夠被滿足的。

首先,數(shù)據(jù)本身是有序的,左邊的子節(jié)點(diǎn)內(nèi)的數(shù)據(jù),一定小于父節(jié)點(diǎn)內(nèi)的數(shù)據(jù),而右邊節(jié)點(diǎn)內(nèi)的數(shù)據(jù),一定大于父節(jié)點(diǎn)內(nèi)的數(shù)據(jù)。

其次,在平衡二叉樹中,你會(huì)發(fā)現(xiàn)父節(jié)點(diǎn)永遠(yuǎn)是兩個(gè)子節(jié)點(diǎn)的中值,因此可以利用這個(gè)中值非常快速的排除掉一半的數(shù)據(jù)。

?

因此,幾乎可以認(rèn)為,一顆平衡二叉樹,也一樣可以利用二分查找的方式快速的從整個(gè)數(shù)據(jù)集合上面快速的取到符合要求的結(jié)果。

?

那么,既然排序后數(shù)組和平衡二叉排序樹都可以以O(log2N)的代價(jià)來(lái)快速的根據(jù)一個(gè)key定位到value.那么我為什么不用數(shù)組來(lái)做這件事,而要選擇使用平衡二叉排序樹呢?

?

這里就涉及到一個(gè)問(wèn)題,排序數(shù)組有什么短板沒有呢??當(dāng)然是有的,就是不支持更新。而平衡二叉樹更新的代價(jià)則要小很多,原因也很簡(jiǎn)單,因?yàn)楦腹?jié)點(diǎn)和子節(jié)點(diǎn)之間使用了引用(指針)來(lái)進(jìn)行的數(shù)據(jù)組織的,所以,需要插入新數(shù)據(jù)的時(shí)候,只需要調(diào)整指針就可以讓樹從新平衡并有序了。

?

當(dāng)然,這種調(diào)整的方式有很多種,他們各有優(yōu)勢(shì)和劣勢(shì)。不過(guò)目前因?yàn)椴恍枰覀兓üΨ蛉?shí)現(xiàn)這些數(shù)據(jù)結(jié)構(gòu)了,所以只需要簡(jiǎn)單了解一下我覺得就可以了。

?

首先被提出來(lái)的平衡樹的方式是AVL樹,然后提出來(lái)的是Tree Heap樹,最后目前在實(shí)踐中最為高效的紅黑樹。

?

Java中,目前的TreeMap就是使用了紅黑樹來(lái)實(shí)現(xiàn)的,各位感興趣也可以去看一下他的代碼,對(duì)這類二叉樹的平衡算法,教科書上面教的已經(jīng)很完美了,帶偽碼帶原理,這里我就不展開了。

?

在文章的末尾,我們還是以我們定義的幾個(gè)集合的評(píng)價(jià)標(biāo)準(zhǔn)來(lái)看看這平衡二叉排序樹的技術(shù)特性

?

1.???????是否支持范圍查找

因?yàn)閿?shù)據(jù)是有序的,所以理論上來(lái)說(shuō)是能夠支持范圍查找的,但從細(xì)節(jié)來(lái)說(shuō),支持的方法卻不是完全相同。

?

這里會(huì)用到大家在教科書上面學(xué)的,二叉樹的遍歷方法中的中序遍歷方法,也即如果要順序的訪問(wèn)數(shù)據(jù),需要不斷地重復(fù)?左子樹->根節(jié)點(diǎn)->右子樹的遍歷方式,直到查詢結(jié)束。

?

如果我們只存了從父節(jié)點(diǎn)到子節(jié)點(diǎn)的指針,那么在遍歷過(guò)程中,我們就必須使用一個(gè)額外的棧來(lái)存放某個(gè)子節(jié)點(diǎn)的父節(jié)點(diǎn)的引用,否則我們是無(wú)法從子節(jié)點(diǎn)回到父節(jié)點(diǎn)的。

?

而如果我們?cè)诿總€(gè)節(jié)點(diǎn)都存放父節(jié)點(diǎn)到子節(jié)點(diǎn)的指針后,額外的再存一個(gè)從子節(jié)點(diǎn)到父節(jié)點(diǎn)的指針,那么我們就不需要用額外的棧來(lái)幫助我們進(jìn)行遍歷了,可以直接按照中序遍歷的方式即可。

?

2.???????集合是否能夠隨著數(shù)據(jù)的增長(zhǎng)而自動(dòng)擴(kuò)展

費(fèi)了那么半天勁,也就是為了能讓數(shù)據(jù)增長(zhǎng)變得更簡(jiǎn)單。?所以我們可以很高興的告知大家,使用平衡排序二叉樹,是可以支持?jǐn)?shù)據(jù)自動(dòng)擴(kuò)展的,鼓掌~

讓樹能夠在保持有序的前提下盡可能平衡的主要方式就是我們上面提到過(guò)的AVL,Tree heap,以及紅黑樹。

?

3.???????讀寫性能如何

在內(nèi)存中指針的跳轉(zhuǎn)速度雖然不如使用數(shù)組快,不過(guò)也是很快的,基本上我們可以認(rèn)為查詢效率就是O(log2N)

對(duì)于寫來(lái)說(shuō),效率也是O(log2N)

4.???????是否面向磁盤結(jié)構(gòu)

回憶我們提到過(guò)的磁盤的特性,一次取出一塊數(shù)據(jù),能比較好的處理順序讀寫,而對(duì)隨機(jī)讀寫則不擅長(zhǎng)。

對(duì)于內(nèi)存來(lái)說(shuō),根據(jù)指針的要求在內(nèi)存中進(jìn)行跳躍,代價(jià)并不高,但如果這個(gè)操作在磁盤中進(jìn)行,那么根據(jù)指針的要求的每一次跳躍,都是一次磁盤的隨機(jī)讀寫,因?yàn)樵谌〕龉?jié)點(diǎn)來(lái)實(shí)際看看之前,我們無(wú)法預(yù)測(cè)這個(gè)父節(jié)點(diǎn)的子節(jié)點(diǎn)被放在磁盤的哪個(gè)位置上的。那么查詢一次數(shù)據(jù)需要跳躍多少次呢?O(log2N-1)次。。跳躍的次數(shù)還是非常夸張的。

因此,平衡二叉查找樹,不是個(gè)面向磁盤的結(jié)構(gòu)。

?

5.???????并行指標(biāo)

不大適合并行操作,在進(jìn)行結(jié)構(gòu)調(diào)整的時(shí)候讀取肯定是錯(cuò)誤的,能夠使用的并行讀寫的思路,主要是兩類:

一個(gè)是鎖分離

一個(gè)是copy on write

不過(guò)因?yàn)樵谀壳暗钠胶舛鏄鋵?shí)現(xiàn)中基本都需要做旋轉(zhuǎn)操作,無(wú)法保證這個(gè)旋轉(zhuǎn)的原子性,所以在主流的平衡二叉排序樹中沒見過(guò)能夠很好地處理并發(fā)的。

?

6.???????內(nèi)存占用

相比較數(shù)組而言,鏈表的內(nèi)存占用是固定的,每個(gè)節(jié)點(diǎn)上固定的兩個(gè)到下層子節(jié)點(diǎn)的指針,以及到父節(jié)點(diǎn)的一個(gè)指針。?其他空間全部可以存放數(shù)據(jù),空間消耗上,如果數(shù)組上的數(shù)據(jù)是全滿的,那么鏈表沒優(yōu)勢(shì)。不過(guò)如果要是自增的數(shù)組,也即每次都以2倍空間大小做自動(dòng)擴(kuò)展,那么鏈表的內(nèi)存占用一般是優(yōu)于自動(dòng)擴(kuò)展數(shù)組的各類實(shí)現(xiàn)的,因?yàn)樽詣?dòng)擴(kuò)展數(shù)組最壞情況下有一半的空間都是空著的。


總結(jié)

以上是生活随笔為你收集整理的数据映射--平衡二叉有序树的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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