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

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

生活随笔

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

编程问答

java 二叉树特点_疯狂java笔记之树和二叉树

發(fā)布時(shí)間:2025/3/11 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 二叉树特点_疯狂java笔记之树和二叉树 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

樹(shù)的概述

樹(shù)是一種非常常用的數(shù)據(jù)結(jié)構(gòu),樹(shù)與前面介紹的線性表,棧,隊(duì)列等線性結(jié)構(gòu)不同,樹(shù)是一種非線性結(jié)構(gòu)

1.樹(shù)的定義和基本術(shù)語(yǔ)

計(jì)算機(jī)世界里的樹(shù),是從自然界中實(shí)際的樹(shù)抽象而來(lái)的,它指的是N個(gè)有父子關(guān)系的節(jié)點(diǎn)的有限集合。對(duì)于這個(gè)有限的節(jié)點(diǎn)集合而言,它滿足如下條件:

當(dāng)N=0時(shí),改節(jié)點(diǎn)集合為空,這課樹(shù)也被稱為空樹(shù)

在任意的非空樹(shù)中,有且僅有一個(gè)根(root)節(jié)點(diǎn)

當(dāng)N>1時(shí),除根節(jié)點(diǎn)以外的其余節(jié)點(diǎn)可分為M個(gè)互為相交的有限集合T1,T2,...,Tm,其中的每個(gè)集合本身又是一棵樹(shù),并稱其為根的子樹(shù)(subtree)。

從上面定義可以發(fā)現(xiàn)樹(shù)的遞歸特性:一棵樹(shù)由根和若干棵子樹(shù)組成,而每棵子樹(shù)又由若干棵更小的子樹(shù)組成。

樹(shù)中任一節(jié)點(diǎn)可以有0或多個(gè)子節(jié)點(diǎn),但只能有一個(gè)父節(jié)點(diǎn)。根節(jié)點(diǎn)是一個(gè)特例,根節(jié)點(diǎn)沒(méi)有父節(jié)點(diǎn),葉子節(jié)點(diǎn)沒(méi)有子節(jié)點(diǎn)。樹(shù)中每個(gè)節(jié)點(diǎn)既可以是其上一級(jí)節(jié)點(diǎn)的子節(jié)點(diǎn),也可以是下一級(jí)節(jié)點(diǎn)的父節(jié)點(diǎn),因此同一個(gè)節(jié)點(diǎn)既可以是父節(jié)點(diǎn),也可以是子節(jié)點(diǎn)(類似于一個(gè)人—————他既是他兒子的父親,又是他父親的兒子)。

很顯然,父子關(guān)系是一種非線性關(guān)系,所以樹(shù)結(jié)構(gòu)是非線性結(jié)構(gòu)。

如果按節(jié)點(diǎn)是否包含子節(jié)點(diǎn)來(lái)分,節(jié)點(diǎn)可以分成以下兩種:

普通節(jié)點(diǎn):包含子節(jié)點(diǎn)的節(jié)點(diǎn)

葉子節(jié)點(diǎn):沒(méi)有子節(jié)點(diǎn)的節(jié)點(diǎn),因此葉子節(jié)點(diǎn)不可作為父節(jié)點(diǎn)

如果按節(jié)點(diǎn)是否具有唯一的父節(jié)點(diǎn)來(lái)分,節(jié)點(diǎn)有可分為如下兩種:

根節(jié)點(diǎn):沒(méi)有父節(jié)點(diǎn)的節(jié)點(diǎn),根節(jié)點(diǎn)不可作為子節(jié)點(diǎn)

普通節(jié)點(diǎn):具有唯一父節(jié)點(diǎn)的節(jié)點(diǎn)

一棵樹(shù)只能有一個(gè)根節(jié)點(diǎn),如果一棵樹(shù)有了多個(gè)根節(jié)點(diǎn),那么它已經(jīng)不再是一棵樹(shù)了,而是多棵樹(shù)的集合,有時(shí)也被稱為森林。示意圖如下:

tree.PNG

與樹(shù)有關(guān)的術(shù)語(yǔ)有如下一些:

節(jié)點(diǎn):樹(shù)的最基本組成單元,通常包括一個(gè)數(shù)據(jù)元素及若干指針用于指向其他節(jié)點(diǎn)。

節(jié)點(diǎn)的度:節(jié)點(diǎn)擁有的子樹(shù)的個(gè)數(shù)被稱為節(jié)點(diǎn)的度(degree)

樹(shù)的度:樹(shù)中所有節(jié)點(diǎn)的度的最大值就是該樹(shù)的度

葉子節(jié)點(diǎn):度為0的節(jié)點(diǎn)被稱為葉子節(jié)點(diǎn)或終端節(jié)點(diǎn)

分支節(jié)點(diǎn):度不為0的節(jié)點(diǎn)被稱為分支節(jié)點(diǎn)或非終端節(jié)點(diǎn)

子節(jié)點(diǎn),父節(jié)點(diǎn),兄弟節(jié)點(diǎn):節(jié)點(diǎn)的子樹(shù)的根被稱為該節(jié)點(diǎn)的子節(jié)點(diǎn),而該節(jié)點(diǎn)稱為子節(jié)點(diǎn)的父節(jié)點(diǎn)(parent).具有相同父節(jié)點(diǎn)的子節(jié)點(diǎn)之間互稱為兄弟節(jié)點(diǎn)。

節(jié)點(diǎn)的層次(level):節(jié)點(diǎn)的層次從根開(kāi)始算起,根的層次值為1,其余節(jié)點(diǎn)的層次值為父節(jié)點(diǎn)層次值加l。

樹(shù)的深度(depth):樹(shù)中節(jié)點(diǎn)的最大層次值稱為樹(shù)的深度或高度。

有序樹(shù)與無(wú)序樹(shù):如果將樹(shù)中節(jié)點(diǎn)的各棵子樹(shù)看成從左到右是有序的(即不能互換),則稱該樹(shù)為有序樹(shù),否則稱為無(wú)序樹(shù)。

祖先節(jié)點(diǎn)(ancestor):從根到該節(jié)點(diǎn)所經(jīng)分支上的所有節(jié)點(diǎn)

后代節(jié)點(diǎn)(descendant):以某節(jié)點(diǎn)為根的子樹(shù)中任一節(jié)點(diǎn)都稱為該節(jié)點(diǎn)的后代節(jié)點(diǎn)。

森林(forest):森林是;兩顆或兩顆以上互不相交的樹(shù)的集合,刪去一棵樹(shù)的根,就得到一個(gè)森林。

樹(shù)的基本操作

如果需要實(shí)現(xiàn)一棵樹(shù),程序不僅要以合適的方式保存該樹(shù)的所有節(jié)點(diǎn),還要記錄節(jié)點(diǎn)與節(jié)點(diǎn)之間的父子關(guān)系。接下來(lái),還應(yīng)該為樹(shù)實(shí)現(xiàn)如下基本操作。

初始化:通常是一個(gè)構(gòu)造器,用于創(chuàng)建一棵空樹(shù),或者以指定節(jié)點(diǎn)為根來(lái)創(chuàng)建樹(shù)。

為指定節(jié)點(diǎn)添加子節(jié)點(diǎn)

判斷樹(shù)是否為空

返回根節(jié)點(diǎn)

返回指定節(jié)點(diǎn)(非根節(jié)點(diǎn))的父節(jié)點(diǎn)

返回指定節(jié)點(diǎn)(非葉子節(jié)點(diǎn))的所有子節(jié)點(diǎn)

返回指定節(jié)點(diǎn)(非葉子節(jié)點(diǎn))的第i個(gè)子節(jié)點(diǎn)

返回該樹(shù)的深度

返回指定節(jié)點(diǎn)的位置

為了實(shí)現(xiàn)樹(shù)這種數(shù)據(jù)結(jié)構(gòu),程序必須能記錄節(jié)點(diǎn)與節(jié)點(diǎn)之間的父子關(guān)系,為此有一下兩種選擇:

父節(jié)點(diǎn)表示法:每個(gè)子節(jié)點(diǎn)都記錄它的父節(jié)點(diǎn)。

子節(jié)點(diǎn)鏈表示法:每個(gè)非葉子節(jié)點(diǎn)通過(guò)一個(gè)鏈表來(lái)記錄它所有的子節(jié)點(diǎn)。

父節(jié)點(diǎn)表示法

通過(guò)前面的介紹可以發(fā)現(xiàn),樹(shù)中除根節(jié)點(diǎn)之外的每個(gè)節(jié)點(diǎn)都有一個(gè)父節(jié)點(diǎn)。為了記錄樹(shù)中節(jié)點(diǎn)與節(jié)點(diǎn)之間的父子關(guān)系,可以為每個(gè)節(jié)點(diǎn)增加一個(gè)parent域,用以記錄該節(jié)點(diǎn)的父節(jié)點(diǎn)。用如下圖和如下表來(lái)表示

tree_show.PNG

數(shù)組索引

data

parent

0

A

-1

1

B

0

2

C

0

3

D

0

4

E

1

5

F

3

6

G

3

7

H

4

8

I

4

9

J

4

10

K

6

...

...

...

由此可見(jiàn),只要用一個(gè)節(jié)點(diǎn)數(shù)組來(lái)保存樹(shù)里的每個(gè)節(jié)點(diǎn),并讓每個(gè)節(jié)點(diǎn)記錄其父節(jié)點(diǎn)在數(shù)組中的索引即可。

子節(jié)點(diǎn)鏈表表示法

父節(jié)點(diǎn)表示法的思想是讓每個(gè)節(jié)點(diǎn)“記住”它的父節(jié)點(diǎn)的索引,父節(jié)點(diǎn)表示法是從子節(jié)點(diǎn)著手的;反過(guò)來(lái),還有另外一種方式:讓父節(jié)點(diǎn)“記住”它的所有子節(jié)點(diǎn)口在這種方式下,由于每個(gè)父節(jié)點(diǎn)需要記住多個(gè)子節(jié)點(diǎn),因此必須采用“子節(jié)點(diǎn)鏈”表示法。示意圖如下:

tree_linked.PNG

二叉樹(shù)

二叉樹(shù)的定義和基本概念

二叉樹(shù)指的是每個(gè)節(jié)點(diǎn)最多只能有兩個(gè)子樹(shù)的有序樹(shù)。通常左邊的子樹(shù)被稱作“左子樹(shù)”(left subtree),右邊的子樹(shù)被稱為“右子樹(shù)”(right subtree).由此可見(jiàn),二叉樹(shù)依然是樹(shù),它是一種特殊的樹(shù)。

二叉樹(shù)的每個(gè)節(jié)點(diǎn)最多只有來(lái)兩顆樹(shù)(不存在度大于2的節(jié)點(diǎn)),二叉樹(shù)的子樹(shù)有左,右之分,次序不能顛倒。

樹(shù)和二叉樹(shù)的兩個(gè)重要區(qū)別如下:

樹(shù)中節(jié)點(diǎn)的最大度數(shù)沒(méi)有限制,而二叉樹(shù)節(jié)點(diǎn)的最大度數(shù)為2,也就是說(shuō),二叉樹(shù)是節(jié)點(diǎn)的最大度數(shù)為2的樹(shù)。

無(wú)序樹(shù)的節(jié)點(diǎn)無(wú)左右之分,而二叉樹(shù)的節(jié)點(diǎn)有左,右之分,也就是說(shuō),二叉樹(shù)是有序樹(shù)。

一棵深度為k的二叉樹(shù),如果它包含了

2^k-1

個(gè)節(jié)點(diǎn),就把這棵二叉樹(shù)稱為滿二叉樹(shù)。滿二叉樹(shù)的特點(diǎn)是。每一層上的節(jié)點(diǎn)數(shù)都是最大節(jié)點(diǎn)數(shù),即各層節(jié)點(diǎn)數(shù)分別為1,2,4,8, 16,...,滿二叉樹(shù)下圖所示:

two_tree.PNG

一顆有n個(gè)節(jié)點(diǎn)的二叉樹(shù),按滿二叉樹(shù)的編號(hào)方式對(duì)它進(jìn)行編號(hào),若樹(shù)中所有節(jié)點(diǎn)和滿二叉樹(shù)1~n編號(hào)完全一致,則稱該樹(shù)為完全二叉樹(shù)。也就是說(shuō),如果一顆二叉樹(shù)除最后一層外,其余層的所有節(jié)點(diǎn)都是滿的,并且最后一層或者是滿的,或者僅在右邊缺少若干連續(xù)的節(jié)點(diǎn),則此二叉樹(shù)就是完全二叉樹(shù)。

綜上所述,二叉樹(shù)大致有如下幾個(gè)性質(zhì):

二叉樹(shù)第i層上的節(jié)點(diǎn)數(shù)據(jù)至多為2的i-1次方

深度為k的二叉樹(shù)至多有2的k次方-1個(gè)節(jié)點(diǎn).滿二叉樹(shù)的每層節(jié)點(diǎn)的數(shù)量依次為1, 2, 4,8,…,因此深度為k的滿二叉樹(shù)包含的節(jié)點(diǎn)數(shù)為公比為2的等比數(shù)列的前k項(xiàng)總和,

即2的k次方一1。

在任何一棵二叉樹(shù)中,如果其葉子節(jié)點(diǎn)的數(shù)量為n0,度為2的子節(jié)點(diǎn)數(shù)量為n2,則

n0=n2 + 1。這是因?yàn)?如果為任意葉子節(jié)點(diǎn)增加一個(gè)子節(jié)點(diǎn),則原有葉子節(jié)點(diǎn)變成非葉子節(jié)點(diǎn),新增節(jié)點(diǎn)變成葉子節(jié)點(diǎn),上述等式不變;如果為任意葉子節(jié)點(diǎn)增加兩個(gè)子節(jié)點(diǎn),則原有葉子節(jié)點(diǎn)變成度為2的非葉子lto點(diǎn),新增的兩個(gè)節(jié)點(diǎn)變成葉子節(jié)點(diǎn),上述等式依然不變。

具有n個(gè)節(jié)點(diǎn)的完全二叉樹(shù)的深度為log2(n+1)

對(duì)于一顆具有n個(gè)節(jié)點(diǎn)的完全二叉樹(shù)的節(jié)點(diǎn)按層自左向右編號(hào),則對(duì)任一編號(hào)為i(n>=i>=1)的節(jié)點(diǎn)有下列性質(zhì)。

當(dāng)i==1時(shí),節(jié)點(diǎn)i是二叉樹(shù)的根;若i>1,則節(jié)點(diǎn)的父節(jié)點(diǎn)是i/2

若2i

若2i+1<=n,則節(jié)點(diǎn)i有右孩子,右孩子的編號(hào)是2i+1;否則,節(jié)點(diǎn)無(wú)右孩子。

1~n/2范圍的節(jié)點(diǎn)都是有孩子節(jié)點(diǎn)的非葉子節(jié)點(diǎn),其余的節(jié)點(diǎn)全部都是葉子節(jié)點(diǎn)。編號(hào)為n/2的節(jié)點(diǎn)可能只有左子節(jié)點(diǎn),也可能即有左子節(jié)點(diǎn),又有右子節(jié)點(diǎn)。

二叉樹(shù)的基本操作

二叉樹(shù)記錄其節(jié)點(diǎn)之間的父子關(guān)系更加簡(jiǎn)單,因?yàn)槎鏄?shù)中的每個(gè)節(jié)點(diǎn)最多只能保存兩個(gè)子節(jié)點(diǎn)。接下來(lái),程序也需要為二叉樹(shù)實(shí)現(xiàn)如下基本操作。

初始化:通常是一個(gè)構(gòu)造器,用于創(chuàng)建一顆空樹(shù),或者以指定節(jié)點(diǎn)為根來(lái)創(chuàng)建二叉樹(shù)。

為指定節(jié)點(diǎn)添加子節(jié)點(diǎn)

判斷二叉樹(shù)是否為空

返回根節(jié)點(diǎn)

返回指定節(jié)點(diǎn)(非根節(jié)點(diǎn))的父節(jié)點(diǎn)

返回指定節(jié)點(diǎn)(非葉子節(jié)點(diǎn))的左子節(jié)點(diǎn)

返回指定節(jié)點(diǎn)(非葉子節(jié)點(diǎn))的右子節(jié)點(diǎn)

返回該二叉樹(shù)的深度

返回指定節(jié)點(diǎn)的位置

要實(shí)現(xiàn)二叉樹(shù)這種數(shù)據(jù)結(jié)構(gòu),有以下三種選擇。

順序存儲(chǔ):采用數(shù)組來(lái)記錄二叉樹(shù)的所有節(jié)點(diǎn)。

二叉鏈表存儲(chǔ):每個(gè)節(jié)點(diǎn)保留一個(gè)left,right域,分別指向其左、右子節(jié)點(diǎn)。

三叉鏈表存儲(chǔ):每個(gè)節(jié)點(diǎn)保留一個(gè)left, right,parent域,分別指向其左、右子節(jié)點(diǎn)和父節(jié)點(diǎn)。

二叉樹(shù)的順序存儲(chǔ)

順序存儲(chǔ)指的是充分利用滿二叉樹(shù)的特性:每層的節(jié)點(diǎn)數(shù)分別為1, 2, 4, 8,…,2的(i-1)2的i次方。一棵

深度為i的二叉樹(shù)最多只能包含2的i次方一1個(gè)節(jié)點(diǎn),因此只要定義一個(gè)長(zhǎng)度為2的i次方一1的數(shù)組即可存儲(chǔ)這棵二叉樹(shù)。

對(duì)于普通二叉樹(shù)(不是滿二叉樹(shù)),那些空出來(lái)的節(jié)點(diǎn)對(duì)應(yīng)的數(shù)組元素留空就可以了。由此可見(jiàn),二叉樹(shù)采用順序存儲(chǔ)會(huì)造成一定的空間浪費(fèi)。對(duì)于下圖1所示的二叉樹(shù)(完全二叉樹(shù)),采用下圖2所示的數(shù)組來(lái)保存即可。

圖1.PNG

圖2.PNG

對(duì)于左圖所示的二叉樹(shù),需使用右圖所示的數(shù)組來(lái)保存。

compare_tree.PNG

當(dāng)使用數(shù)組來(lái)存儲(chǔ)二又樹(shù)的所有節(jié)點(diǎn)時(shí)可能會(huì)產(chǎn)生一定的空間浪費(fèi),如果該二叉樹(shù)是完全二叉樹(shù),就不會(huì)有任何空間浪費(fèi)了;但如果該二叉樹(shù)的所有節(jié)點(diǎn)都只有右子節(jié)點(diǎn),那么就會(huì)產(chǎn)生相當(dāng)大的空間浪費(fèi).

二叉樹(shù)的二叉鏈表存儲(chǔ)

二叉鏈表存儲(chǔ)的思想是讓每個(gè)節(jié)點(diǎn)都能“記住”它的左,右兩個(gè)子節(jié)點(diǎn)。為每個(gè)節(jié)點(diǎn)增加left,right兩個(gè)指針,分別引用改節(jié)點(diǎn)的左,右兩個(gè)子節(jié)點(diǎn),因此二叉鏈表存儲(chǔ)的每個(gè)節(jié)點(diǎn)有如下圖結(jié)構(gòu):

two_fork_tree.PNG

二叉鏈表存儲(chǔ)的二叉樹(shù)的節(jié)點(diǎn)大致有如下定義:

class Node{

Object data;

Node left;

Node right;

}

對(duì)于這種二叉鏈表存儲(chǔ)的二叉樹(shù),如果程序需要,為指定節(jié)點(diǎn)添加子節(jié)點(diǎn)也非常容易,讓父節(jié)點(diǎn)的left或right引用指向新節(jié)點(diǎn)即可。

二叉樹(shù)的三叉鏈表存儲(chǔ)

三叉鏈表存儲(chǔ)的思想是讓每個(gè)節(jié)點(diǎn)不僅“記住”它的左右兩個(gè)子節(jié)點(diǎn),還要“記住”它的父節(jié)點(diǎn),因此需要為每個(gè)節(jié)點(diǎn)增加left,right和parent三個(gè)指針,分別引用該節(jié)點(diǎn)的左,右兩個(gè)子節(jié)點(diǎn)和父節(jié)點(diǎn)。因此,三叉鏈表存儲(chǔ)的每個(gè)節(jié)點(diǎn)有如下圖的結(jié)構(gòu):

three_tree.PNG

因此三叉鏈表存儲(chǔ)的二叉樹(shù)的節(jié)點(diǎn)大致如下:

class Node{

Object data;

Node left;

Node right;

Node parent;

}

對(duì)于這種三叉鏈表存儲(chǔ)的二叉樹(shù),如果程序需要,為指定節(jié)點(diǎn)添加子節(jié)點(diǎn)也非常容易,除了要維護(hù)父節(jié)點(diǎn)的left,right引用之外,還要維護(hù)新增節(jié)點(diǎn)的parent引用。

遍歷二叉樹(shù)

遍歷二叉樹(shù)指的是按某種規(guī)律依次訪問(wèn)二叉樹(shù)的每個(gè)節(jié)點(diǎn),對(duì)二叉樹(shù)的遍歷過(guò)程就是講非線性結(jié)構(gòu)的二叉樹(shù)的節(jié)點(diǎn)排列成線性序列的過(guò)程。

如果采用順序結(jié)構(gòu)來(lái)保存二叉樹(shù),程序遍歷二叉樹(shù)非常容易,無(wú)須進(jìn)行任何思考,直接遍歷底層數(shù)組即可。如果采用鏈表來(lái)保存二叉樹(shù)的節(jié)點(diǎn),則有以下兩種遍歷方式。

深度優(yōu)先遍歷:這種遍歷算法將先訪問(wèn)到樹(shù)中最深層次的節(jié)點(diǎn)

廣度優(yōu)先遍歷:這種遍歷算法將逐層訪問(wèn)每層的節(jié)點(diǎn),先訪問(wèn)根(第一層)節(jié)點(diǎn),然后訪問(wèn)第二層的節(jié)點(diǎn).....一次類推。因此,廣度優(yōu)先遍歷方法又被稱為按層遍歷。

先(前)序遍歷二叉樹(shù)

中序遍歷二叉樹(shù)

后序遍歷二叉樹(shù)

如果L,D,W表示左子樹(shù)、根、右子樹(shù),習(xí)慣上總是必須先遍歷左子樹(shù),后遍歷右子樹(shù),根據(jù)遍歷根節(jié)點(diǎn)的順序不同,上面三種算法可表示如下。

DLR:先序遍歷

LDR:中序遍歷

LRD:后序遍歷

深度遍歷的先序遙歷、中序遍歷、后序遍歷這三種遍歷方式的名稱都是針對(duì)根節(jié)點(diǎn)(D)而言的。先處理根節(jié)點(diǎn)(D)時(shí)就稱為先序遍歷。其次處理根節(jié)點(diǎn)(D)時(shí)就稱為中序遍歷;最后處理根節(jié)點(diǎn)(D)時(shí)就稱為后序遍歷。

先序遍歷

先序遍歷指先處理根節(jié)點(diǎn),其處理順序如下:

(1) 訪問(wèn)根節(jié)點(diǎn)

(2) 遞歸遍歷左子樹(shù)

(3) 遞歸遍歷右子樹(shù)

中序遍歷

中序遍歷指其次處理根節(jié)點(diǎn).其處理順序如下。

(1) 遞歸遍歷左子樹(shù)

(2) 訪問(wèn)根節(jié)點(diǎn)

(3) 遞歸遍歷右子樹(shù)

后序遍歷

后序遍歷指最后處理根節(jié)點(diǎn),其處理順序如下。

(1) 遞歸遍歷左子樹(shù)

(2) 遞歸遍歷右子樹(shù)

(3) 訪問(wèn)根節(jié)點(diǎn)

廣度優(yōu)先(按層)遍歷

廣度優(yōu)先遍歷又稱為按層遍歷,整個(gè)遍歷算法是先遍歷幾叉樹(shù)的第一層(根節(jié)點(diǎn)),再遍歷根節(jié)點(diǎn)的兩個(gè)子’節(jié)點(diǎn)(第二層)……依此類推,逐層遍歷二叉樹(shù)的所有節(jié)點(diǎn)。

為了實(shí)現(xiàn)廣度優(yōu)先遍歷,可以借助于具有FIFO特征的隊(duì)列來(lái)實(shí)現(xiàn)。如下所示。

建一個(gè)隊(duì)列(先進(jìn)先出),把樹(shù)的根節(jié)點(diǎn)壓入隊(duì)列。

從隊(duì)列中彈出一個(gè)節(jié)點(diǎn)(第一個(gè)彈出的就是根節(jié)點(diǎn)),然后把改節(jié)點(diǎn)的左,右節(jié)點(diǎn)壓入隊(duì)列,如果沒(méi)有子節(jié)點(diǎn),則說(shuō)明已經(jīng)達(dá)到葉子節(jié)點(diǎn)了。

用循環(huán)重復(fù)執(zhí)行2步,知道隊(duì)列為空。當(dāng)隊(duì)列為空時(shí),說(shuō)明所有的葉子節(jié)點(diǎn)(深度最深的層)都已經(jīng)經(jīng)過(guò)了隊(duì)列,也就完成了遍歷。

轉(zhuǎn)換方法

由于二叉樹(shù)是一種更“確定”(它的每個(gè)節(jié)點(diǎn)最多只有兩個(gè)子節(jié)點(diǎn))的數(shù)據(jù)結(jié)構(gòu),因此不管是存儲(chǔ)、增加、刪除節(jié)點(diǎn),還是遍歷節(jié)點(diǎn),程序都可以更簡(jiǎn)單、方便地實(shí)現(xiàn)口反之,由于樹(shù)的每個(gè)節(jié)點(diǎn)具有個(gè)數(shù)不確定的節(jié)點(diǎn),因此程序?qū)崿F(xiàn)起來(lái)更復(fù)雜。

為了充分利用二義樹(shù)的簡(jiǎn)單易用性,可以將普通樹(shù)轉(zhuǎn)換為二叉樹(shù),以二叉樹(shù)的形式來(lái)保存柞通樹(shù),當(dāng)程序需要樹(shù)時(shí),再將悅義樹(shù)轉(zhuǎn)換為普通樹(shù)。

森林其實(shí)更簡(jiǎn)單,如果將一棵伶通樹(shù)的根節(jié)點(diǎn)去掉,這棵樹(shù)就變成了森林?;蛘呖梢赞D(zhuǎn)換一下思維,森林其實(shí)就是有多個(gè)根節(jié)點(diǎn)的樹(shù)。

森林,樹(shù)和二叉樹(shù)的轉(zhuǎn)換

有序樹(shù),森林和二叉樹(shù)之間有一一映射的關(guān)系,可以進(jìn)行互相轉(zhuǎn)換。

多叉樹(shù)向二叉樹(shù)的方法如下:

(1)加虛線:同一個(gè)父節(jié)點(diǎn)的相鄰兄弟節(jié)點(diǎn)之間加虛線

(2)抹實(shí)線:每個(gè)節(jié)點(diǎn)只保留它與最左子節(jié)點(diǎn)的連線,與其他字節(jié)點(diǎn)的連線都被抹掉。

(3)虛改實(shí):虛線改為實(shí)線

如圖就是多叉圖向二叉樹(shù)轉(zhuǎn)換的結(jié)果

forest_tree.PNG

圖中的虛線就是新增的“父子”關(guān)系。這個(gè)轉(zhuǎn)換結(jié)果來(lái)看,多叉樹(shù)1轉(zhuǎn)換為二叉樹(shù)的方法的關(guān)鍵思想就是:所有子節(jié)點(diǎn)只保留子節(jié)點(diǎn),其他子節(jié)點(diǎn)轉(zhuǎn)為左子節(jié)點(diǎn)的右子節(jié)點(diǎn)鏈。

按照這個(gè)轉(zhuǎn)換思路,森林也可轉(zhuǎn)換為二叉樹(shù)————只要把森林當(dāng)成一顆根節(jié)點(diǎn)被刪除的多叉樹(shù)即可。下圖示范了將森林轉(zhuǎn)換為二叉樹(shù)的結(jié)果。

forest_to_tree.PNG

反過(guò)來(lái),二叉樹(shù)也可恢復(fù)出對(duì)應(yīng)的多叉樹(shù),森林,恢復(fù)方法如下:

-(1)加虛線:若某節(jié)點(diǎn)I是父節(jié)點(diǎn)的左子節(jié)點(diǎn),則為該節(jié)點(diǎn)I的右孩子鏈的所有節(jié)點(diǎn)分別于節(jié)點(diǎn)I的父節(jié)點(diǎn)添加連線

(2)抹線:把有虛線的節(jié)點(diǎn)于原父節(jié)點(diǎn)的連線抹去

(3)整理:虛改實(shí)并按層排列

把二叉樹(shù)轉(zhuǎn)換為多叉樹(shù)

two_tree_more_tree.PNG

如果二叉樹(shù)的根節(jié)點(diǎn)有右子節(jié)點(diǎn)————右子節(jié)點(diǎn)就代表根節(jié)點(diǎn)的兄弟節(jié)點(diǎn),這種情況會(huì)轉(zhuǎn)換得到森林。

把二叉樹(shù)轉(zhuǎn)換為森林

tree_to_forest.PNG

樹(shù)的鏈表存儲(chǔ)

根據(jù)上面介紹的理論,二義樹(shù)可以和多叉樹(shù)之間進(jìn)行自由轉(zhuǎn)換,因此可以得到普通樹(shù)的另外一種保存方式:以二義樹(shù)的形式保存多叉樹(shù),實(shí)際需要的時(shí)候再將二叉樹(shù)轉(zhuǎn)換為普通樹(shù)。

至于到底以哪種方式來(lái)保存二叉樹(shù),完全是自由的。通常會(huì)選擇使用三叉鏈表存儲(chǔ)方式來(lái)保存二叉樹(shù),這樣得到的二叉樹(shù)操作起來(lái)更方便,進(jìn)行二叉樹(shù)和多叉樹(shù)之間轉(zhuǎn)換時(shí)也更方便。

哈夫曼樹(shù)

哈夫曼樹(shù)又被稱為最優(yōu)二叉樹(shù),是一種帶權(quán)路徑最短的二叉樹(shù)。哈夫曼樹(shù)是二叉樹(shù)的一種應(yīng)用,在信息檢索中很常用.

哈夫曼樹(shù)的定義和基本概念

在介紹哈夫曼樹(shù)之前先來(lái)介紹一些相關(guān)的概念。

節(jié)點(diǎn)之間的路徑長(zhǎng)度:從一個(gè)節(jié)點(diǎn)到另一個(gè)節(jié)點(diǎn)之間的分支數(shù)量稱為兩個(gè)節(jié)點(diǎn)之間的路徑長(zhǎng)度

樹(shù)的路徑長(zhǎng)度:從根節(jié)點(diǎn)到樹(shù)中的每一個(gè)節(jié)點(diǎn)的路徑長(zhǎng)度之和。

對(duì)于下圖所示的而二叉樹(shù),該樹(shù)的路徑長(zhǎng)度為17.即0+1+2+2+3+4+5==17.

hafuman.PNG

節(jié)點(diǎn)的帶權(quán)路徑長(zhǎng)度:從該節(jié)點(diǎn)到根節(jié)點(diǎn)之間的路徑長(zhǎng)度與節(jié)點(diǎn)的權(quán)的乘積

樹(shù)的帶權(quán)路徑長(zhǎng)度:樹(shù)中所有葉子節(jié)點(diǎn)的帶權(quán)路徑長(zhǎng)度之和。帶權(quán)路徑如圖:

daiquan.PNG

對(duì)于哈夫曼樹(shù),有一個(gè)很重要的定理:對(duì)于具有對(duì)n個(gè)葉子節(jié)點(diǎn)的哈夫曼樹(shù),一共需要2乘以n-1個(gè)節(jié)點(diǎn)。因?yàn)閷?duì)于二叉樹(shù)來(lái)說(shuō),有三種類型節(jié)點(diǎn),即度數(shù)為2的節(jié)點(diǎn)、度數(shù)為1的節(jié)點(diǎn)和度數(shù)為0的葉子節(jié)點(diǎn),而哈夫曼樹(shù)的非葉子節(jié)點(diǎn)都是由兩個(gè)節(jié)點(diǎn)合并產(chǎn)生的,所以不會(huì)出現(xiàn)度

數(shù)為1的節(jié)點(diǎn)。而生成的非葉子節(jié)點(diǎn)的個(gè)數(shù)為葉子節(jié)點(diǎn)個(gè)數(shù)-1因此n個(gè)葉子節(jié)點(diǎn)的哈夫曼樹(shù),一共需要Z乘以n-1個(gè)節(jié)點(diǎn)。

創(chuàng)建哈夫曼樹(shù)

創(chuàng)建哈夫曼樹(shù),可以按如下步驟進(jìn)行:

根據(jù)給定的。個(gè)權(quán)值{wl,w2,...,wn}構(gòu)造n棵二叉樹(shù)的集合F={T1,T2,...,Tn} },F集合中每棵二叉樹(shù)都只有一個(gè)根節(jié)點(diǎn)。

選取F集合中兩棵根節(jié)點(diǎn)的權(quán)值最小的樹(shù)作為左、右子樹(shù)以構(gòu)造一棵新的二叉樹(shù),且將新的二叉樹(shù)的根節(jié)點(diǎn)的權(quán)值設(shè)為左、右子樹(shù)上根節(jié)點(diǎn)的權(quán)值之和。

將新的二叉樹(shù)加入到F集合中,并刪除第2步中被選中的兩棵樹(shù)。

重復(fù)第2和3步,直到F集合中只剩下一棵樹(shù),這棵樹(shù)就是哈夫曼樹(shù)。

下圖顯示了創(chuàng)建哈夫曼樹(shù)的過(guò)程。

hafuman_tree.PNG

哈夫曼編碼

根據(jù)哈夫曼樹(shù)可以解決報(bào)文編碼問(wèn)題。假設(shè)需要對(duì)一個(gè)字符串如“a6cdabcaba”進(jìn)行編碼,將它轉(zhuǎn)換為唯一的二進(jìn)制碼,但要求轉(zhuǎn)換出來(lái)的二進(jìn)制碼的長(zhǎng)度最小。

假設(shè)每個(gè)字符在字符串中出現(xiàn)的頻率為W}其編碼長(zhǎng)度為L(zhǎng),編碼字符有n個(gè),則編碼后二進(jìn)制碼的總長(zhǎng)度為W1L1+W2L2+W3L3+...+WnLn,這正好符合哈夫曼樹(shù)的處理原則。因此可采用哈夫曼樹(shù)的原理構(gòu)造二進(jìn)制編碼,并使電文總長(zhǎng)最短。

對(duì)于“abcdabcaba”字符串,總共只有a,b,c,d,這四個(gè)字符,它們出現(xiàn)的次數(shù)是4,3,2,1次__這相當(dāng)于它們的權(quán)值。于是,將a,b,c,d四個(gè)字符以出現(xiàn)的次數(shù)為權(quán)值構(gòu)造哈夫曼樹(shù),得到如下圖結(jié)構(gòu):

hanfuman1.PNG

從哈夫曼樹(shù)根節(jié)點(diǎn)開(kāi)始,對(duì)左子樹(shù)分配代碼“0”,對(duì)右子樹(shù)分配代碼“1”,一直到達(dá)葉子節(jié)點(diǎn)。然后.將從樹(shù)根沿每條路徑到達(dá)葉子節(jié)點(diǎn)的代碼排列起來(lái),便得到了每個(gè)葉子節(jié)點(diǎn)的哈夫曼編碼。下圖顯示了對(duì)a, b, c, d四個(gè)字符編碼得到的哈夫曼編碼。

hanfuma2.PNG

排序二叉樹(shù)

排序二叉樹(shù)是一種特殊結(jié)構(gòu)的二叉樹(shù),通過(guò)它可以非常方便地對(duì)樹(shù)中的所有節(jié)點(diǎn)進(jìn)行排序和檢索

排序二叉樹(shù)要么是一顆空二叉樹(shù),要么是具有下列性質(zhì)的二叉樹(shù)

若它的左子樹(shù)不空,則左子樹(shù)上所有的節(jié)點(diǎn)的值均小于它的根節(jié)點(diǎn)的值

若它的右子樹(shù)不空,則右子樹(shù)上所有的節(jié)點(diǎn)均大于它的根節(jié)點(diǎn)的值

它的左右子樹(shù)分別為排序二叉樹(shù)。

下圖顯示了一棵排序二叉樹(shù).

對(duì)于排序二叉樹(shù),若按中序遍歷就可以得到由小到大的有序序列。中序遍歷得:

{2,3,4,8,9,9,10,13,15,18)

sort_tree.PNG

創(chuàng)建排序二義樹(shù)的步驟,就是不斷地向排序二義樹(shù)添加節(jié)點(diǎn)的過(guò)程,幾體如下。

以根節(jié)點(diǎn)為當(dāng)前節(jié)點(diǎn)開(kāi)始搜索

拿新節(jié)點(diǎn)的值和當(dāng)前節(jié)點(diǎn)開(kāi)始搜索

如果新節(jié)點(diǎn)的值更大,則以當(dāng)前的右子節(jié)點(diǎn)作為新的當(dāng)前節(jié)點(diǎn)的右子節(jié)點(diǎn)作為新的當(dāng)前節(jié)點(diǎn);如果新節(jié)點(diǎn)的值更小,則以當(dāng)前節(jié)點(diǎn)的右子節(jié)點(diǎn)作為新的當(dāng)前節(jié)點(diǎn)。

重復(fù)第2和3兩個(gè)步驟,直到搜索到合適的葉子節(jié)點(diǎn)。

將新節(jié)點(diǎn)添加為第4步找到的葉子節(jié)點(diǎn)的子節(jié)點(diǎn),如果新節(jié)點(diǎn)更大,則添加為右子節(jié)點(diǎn);否則,添加為左子節(jié)點(diǎn)。

當(dāng)程序從排序二叉樹(shù)中刪除一個(gè)節(jié)點(diǎn)之后,為了讓它依然保持為排序哭叉樹(shù),必須對(duì)該排序二叉樹(shù)進(jìn)行維護(hù)。維護(hù)可分為如下幾種情況。

被刪除節(jié)點(diǎn)是葉子節(jié)點(diǎn),只需將它從其父節(jié)點(diǎn)中刪除。

被刪除轉(zhuǎn)點(diǎn)p只有左子樹(shù)或只有右子樹(shù),如果p是它的父節(jié)點(diǎn)的左子節(jié)點(diǎn),則將p的左子樹(shù)或右子樹(shù)添加成p一節(jié)點(diǎn)的父節(jié)點(diǎn)的左子節(jié)點(diǎn)即可;如果p是它的父節(jié)點(diǎn)的右子節(jié)點(diǎn),則將p的左子樹(shù)或右子樹(shù)添加成P節(jié)點(diǎn)的父節(jié)點(diǎn)的右子節(jié)點(diǎn)即可。簡(jiǎn)單來(lái)說(shuō),如果要側(cè)除的節(jié)點(diǎn)只有一個(gè)子節(jié)點(diǎn),即可用它的子節(jié)點(diǎn)來(lái)代替要側(cè)除的節(jié)點(diǎn)。

被刪除的節(jié)點(diǎn)只有左子樹(shù)的情況

delete_only_left_tree.PNG

被刪除節(jié)點(diǎn)只有右子樹(shù)的情況

delete_only_right_tree.PNG

若被刪除節(jié)點(diǎn)p的左、右子樹(shù)均非空,則有以下兩種做法。

將pL設(shè)為P的父節(jié)點(diǎn)q的左或右子節(jié)點(diǎn)(取決于P是其節(jié)父點(diǎn)q的左、右子節(jié)點(diǎn)),

將pR設(shè)為P節(jié)點(diǎn)的中序前趨節(jié)點(diǎn)s的右子節(jié)點(diǎn)(s是pL最右下的節(jié)點(diǎn),也就是pL子樹(shù)中最大的節(jié)點(diǎn))。采用這種方式刪除節(jié)點(diǎn)的示意圖如下:

delete_left_right.PNG

以P節(jié)點(diǎn)的中序前趨或后繼替代P所指節(jié)點(diǎn),然后從原排序二叉樹(shù)中刪除中序前趨或后繼節(jié)點(diǎn)。簡(jiǎn)單來(lái)說(shuō),就是用大于p的最小節(jié)點(diǎn)或小于P的最大節(jié)點(diǎn)代替P節(jié)點(diǎn)點(diǎn),采

用這種方式刪除節(jié)點(diǎn)的示意圖如下圖:

delete_left_right_center.PNG

紅黑樹(shù)

排序二叉樹(shù)雖然可以快速檢索,但在最壞的情況下,如果插入的節(jié)點(diǎn)集本身就是有序的,要么是由小到大排列,要么是由大到小排列,那么最后得到的排序二義樹(shù)將變成鏈表:所有節(jié)點(diǎn)只有左節(jié)點(diǎn)(如果插入節(jié)點(diǎn)集合本身是由大到小排列的),或者所有節(jié)點(diǎn)只有右節(jié)點(diǎn)(如果

插入節(jié)點(diǎn)集合本身是由小到大排列的)。在這種情況下,排序二叉樹(shù)就變成了普通鏈表,其檢索效率就會(huì)很低。

為了改變排序二叉樹(shù)存在的不足,對(duì)二叉樹(shù)進(jìn)行改進(jìn)————紅黑樹(shù),他將這種排序二叉樹(shù)稱為“對(duì)稱二叉B樹(shù)”。

紅黑樹(shù)是一個(gè)更高效的檢索二叉樹(shù),因此常常用來(lái)實(shí)現(xiàn)關(guān)聯(lián)數(shù)組。典型的,JDK提供的集合類TreeMap本身就是一顆紅黑樹(shù)的實(shí)現(xiàn)。

紅黑樹(shù)在原有的排序二叉樹(shù)上增加如下幾個(gè)要求:

性質(zhì)l:每個(gè)節(jié)點(diǎn)要么是紅色,要么是黑色。

性質(zhì)2:根節(jié)點(diǎn)永遠(yuǎn)是黑色的。

除質(zhì)3:所有的葉子節(jié)點(diǎn)都是空節(jié)點(diǎn)(即null),并且是黑色的。

性質(zhì)4:每個(gè)紅色節(jié)點(diǎn)的兩個(gè)子節(jié)點(diǎn)都是黑色的。(從每個(gè)葉子到根的路徑上不會(huì)有兩個(gè)連續(xù)的紅色節(jié)點(diǎn)。)

性質(zhì)5:從任一節(jié)點(diǎn)到其子樹(shù)中每個(gè)葉子節(jié)點(diǎn)的路徑都包含相同數(shù)量的黑色節(jié)點(diǎn)。

java實(shí)現(xiàn)的紅黑樹(shù)結(jié)構(gòu)如下圖:

red_black_tree.PNG

根據(jù)性質(zhì)5,紅黑樹(shù)從根節(jié)點(diǎn)到每個(gè)葉子節(jié)點(diǎn)的路徑都包含相同數(shù)量的黑色節(jié)點(diǎn),因此從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)的路徑中包含的黑色節(jié)點(diǎn)數(shù)被稱為樹(shù)的“黑色高度(black-height)".

性質(zhì)4則保證了從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)的最長(zhǎng)路徑的一長(zhǎng)度不會(huì)超過(guò)任何其他路徑的2倍。假如有一棵黑色高度為3的紅黑樹(shù),從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)的最短路徑長(zhǎng)度是2,該路徑上全是黑色節(jié)點(diǎn)〔黑色節(jié)點(diǎn)-黑色節(jié)點(diǎn)-黑色節(jié)點(diǎn))。最長(zhǎng)路徑也只可能為4,在每個(gè)黑色節(jié)點(diǎn)之間插入一個(gè)紅色節(jié)點(diǎn)〔黑色節(jié)點(diǎn)-紅色節(jié)點(diǎn)-黑色書(shū)點(diǎn)-紅色節(jié)點(diǎn)-黑色節(jié)點(diǎn)),性質(zhì)4保證絕不可能插入更多的紅色節(jié)點(diǎn)。由此可見(jiàn),紅黑樹(shù)中最長(zhǎng)的路徑就是一條紅黑交替的路徑。

由此可以得出結(jié)論:對(duì)于給定的黑色高度為N的紅黑樹(shù),從根到葉子節(jié)點(diǎn)的最短路徑長(zhǎng)度為N-1,最長(zhǎng)路徑長(zhǎng)度為2*(N-1).

紅黑樹(shù)通過(guò)上面這種限制來(lái)保證它大致是平衡的—因?yàn)榧t黑樹(shù)的高度不會(huì)無(wú)限增高,這樣能保證紅黑樹(shù)在最壞的情況下都是高效的,不會(huì)出現(xiàn)普通排序二叉樹(shù)的情況。

由于紅黑樹(shù)只是一棵特殊的排序二叉樹(shù),因此對(duì)紅黑樹(shù)上的只讀操作與普通排序二叉樹(shù)上的只讀操作完全相同,只是紅黑樹(shù)保持了大致平衡,因此檢索性能更好.

但在紅黑樹(shù)上進(jìn)行插入操作和刪除操作會(huì)導(dǎo)致樹(shù)不再符合紅黑樹(shù)的特征,因此插入操作和刪除操作都需要進(jìn)行一定的維護(hù),以保證插入節(jié)點(diǎn)、刪除節(jié)點(diǎn)后的樹(shù)依然是紅黑樹(shù)。

插入操作

插入操作按如下步驟進(jìn)行:

以排序二叉樹(shù)的方法插入新節(jié)點(diǎn),并將它設(shè)為紅色。

進(jìn)行顏色調(diào)換和樹(shù)旋轉(zhuǎn)

這種顏色調(diào)換和樹(shù)旋轉(zhuǎn)就比較復(fù)雜了,下面將分情況進(jìn)行介紹。在介紹中,把新插入的節(jié)點(diǎn)定義為N節(jié)點(diǎn),把N節(jié)點(diǎn)的父節(jié)點(diǎn)定義為P節(jié)點(diǎn),把P節(jié)點(diǎn)的兄弟節(jié)點(diǎn)定義為U節(jié)點(diǎn),把P節(jié)點(diǎn)的父節(jié)點(diǎn)定義為G節(jié)點(diǎn)。

情形1:新節(jié)點(diǎn)N是樹(shù)的根節(jié)點(diǎn),沒(méi)有父節(jié)點(diǎn)。

在這種情形下,直接將它設(shè)置為黑色以滿足性質(zhì)2。

情形2:新節(jié)點(diǎn)的父節(jié)點(diǎn)P是黑色的

在這種情形下,新插入的節(jié)點(diǎn)是紅色的,因此依然滿足性質(zhì)4。而且因?yàn)樾鹿?jié)點(diǎn)N有兩個(gè)黑色葉子節(jié)點(diǎn),但是由于新節(jié)點(diǎn)N是紅色的,通過(guò)它的每個(gè)子節(jié)點(diǎn)的路徑依然保持相同的黑色節(jié)點(diǎn)數(shù),因此依然滿足性質(zhì)5

3.情形3:父節(jié)點(diǎn)P和父節(jié)點(diǎn)的兄弟節(jié)點(diǎn)U都是紅色的

在這種情形下,程序應(yīng)該將P節(jié)點(diǎn)、U節(jié)點(diǎn)都設(shè)置為黑色,并將P節(jié)點(diǎn)的父節(jié)點(diǎn)設(shè)置為紅色(用來(lái)保持性質(zhì)5)?,F(xiàn)在,新節(jié)點(diǎn)N有了一個(gè)黑色的父節(jié)點(diǎn)P。由于從P節(jié)點(diǎn)、U節(jié)點(diǎn)到根節(jié)點(diǎn)的任何路徑都必須通過(guò)G節(jié)點(diǎn),這些路徑上的黑色節(jié)點(diǎn)數(shù)目沒(méi)有改變(原來(lái)有葉子和G節(jié)點(diǎn)兩個(gè)黑色節(jié)點(diǎn),現(xiàn)在有葉子和P節(jié)點(diǎn)兩個(gè)黑色節(jié)點(diǎn))。

經(jīng)過(guò)上面處理后,紅色的G節(jié)點(diǎn)的父節(jié)點(diǎn)也有可能是紅色的,這就違反了性質(zhì)4,因此還需要對(duì)G節(jié)點(diǎn)遞歸地進(jìn)行整個(gè)過(guò)程〔把G節(jié)點(diǎn)當(dāng)成新插入的節(jié)點(diǎn)進(jìn)行處理)。

下圖顯示了處理過(guò)程:

red_black_tree_1.PNG

情形4:父節(jié)點(diǎn)P是紅色的,而其兄弟節(jié)點(diǎn)U是黑色的或缺少;且新節(jié)點(diǎn)N是父節(jié)點(diǎn)P的右子節(jié)點(diǎn),而父節(jié)點(diǎn)P又是其父節(jié)點(diǎn)G的左子節(jié)點(diǎn)。

在這種情形下,對(duì)新節(jié)點(diǎn)和其父節(jié)點(diǎn)進(jìn)行一次左旋轉(zhuǎn)。接著,按情形5處理以前的父節(jié)點(diǎn)P(也就是把P當(dāng)成新插入的節(jié)點(diǎn))。這將導(dǎo)致某些路徑通過(guò)它們以前不通過(guò)的新節(jié)點(diǎn)N或父節(jié)點(diǎn)P其中之一,但是這兩個(gè)節(jié)點(diǎn)都是紅色的,因此不會(huì)影響性質(zhì)5。

red_black_tree_2.PNG

情形5:父節(jié)點(diǎn)F是紅色的,而其兄弟節(jié)點(diǎn)U是黑色的或缺少:且新節(jié)點(diǎn)N是其父節(jié)點(diǎn)的左子節(jié)點(diǎn),而父節(jié)點(diǎn)F父是其父節(jié)點(diǎn)G的左子節(jié)點(diǎn)。

在這種情形下,需要對(duì)節(jié)點(diǎn)G進(jìn)行一次右旋轉(zhuǎn)口在旋轉(zhuǎn)產(chǎn)生的樹(shù)中,以前的父節(jié)點(diǎn)P現(xiàn)在是新節(jié)點(diǎn)N和節(jié)點(diǎn)G的父節(jié)點(diǎn)。由于以前的節(jié)點(diǎn)G是黑色的(否則父節(jié)點(diǎn)P就不可能是紅色的),切換以前的父節(jié)點(diǎn)P和節(jié)點(diǎn)G的顏色,使之滿足性質(zhì)4。性質(zhì)5也仍然保持滿足,因?yàn)橥ㄟ^(guò)這三個(gè)節(jié)點(diǎn)中任何一個(gè)的所有路徑以前都通過(guò)節(jié)點(diǎn)G,現(xiàn)在它們都通過(guò)以前的父節(jié)點(diǎn)P。在各自的情形下,這都是三個(gè)節(jié)點(diǎn)中唯一的黑色節(jié)點(diǎn)。

red_black_tree_3.PNG

刪除操作

紅黑樹(shù)的刪除操作比插入操作要稍微復(fù)雜一些,實(shí)際上也可按如下步驟進(jìn)行:

以排序二叉樹(shù)的方法刪除指定節(jié)點(diǎn)。

進(jìn)行顏色調(diào)換和樹(shù)旋轉(zhuǎn),使之滿足紅黑樹(shù)特征。

總結(jié)

以上是生活随笔為你收集整理的java 二叉树特点_疯狂java笔记之树和二叉树的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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