




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第Java詳解AVL樹(shù)的應(yīng)用目錄一.什么是AVL樹(shù)1.二叉搜索樹(shù)2.為什么引入了AVL樹(shù)3.什么是AVL樹(shù)二.自己構(gòu)造AVL樹(shù)三.AVL樹(shù)的插入和刪除1.插入1.1.右單旋1.2.左單旋1.3.左右雙旋1.4.右左雙旋2.刪除
一.什么是AVL樹(shù)
在認(rèn)識(shí)AVL樹(shù)之前我們先認(rèn)識(shí)一下什么是二叉搜索樹(shù):
1.二叉搜索樹(shù)
二叉搜索樹(shù)又稱為二叉排序樹(shù),二叉搜索樹(shù)滿足所有的左孩子節(jié)點(diǎn)都小于其根節(jié)點(diǎn)的值,所有的右孩子節(jié)點(diǎn)都大于其根節(jié)點(diǎn)的值,二叉搜索樹(shù)上的每一棵子樹(shù)都是一棵二叉搜索樹(shù),因此二叉搜索樹(shù)通過(guò)中序遍歷可以獲得一個(gè)有序的序列(由小到大);
類似于這樣的樹(shù)就是一棵二叉搜索樹(shù);
2.為什么引入了AVL樹(shù)
二叉搜索樹(shù)看似很美好,但其卻有一些缺陷.對(duì)于二叉搜索樹(shù)而言,是和查找相關(guān)的,而不論是查找還是刪除,都需要先進(jìn)行查找,也就是對(duì)整棵樹(shù)來(lái)進(jìn)行遍歷,而對(duì)有n個(gè)結(jié)點(diǎn)的二叉搜索樹(shù),若每個(gè)元素查找的概率相等,則二叉搜索樹(shù)平均查找長(zhǎng)度是結(jié)點(diǎn)在二叉搜索樹(shù)的深度函數(shù),也就是結(jié)點(diǎn)越深,則比較次數(shù)越多.最優(yōu)的情況下是:二叉搜索樹(shù)為完全二叉樹(shù),其平均比較次數(shù)為:log2nlog_2{n}log2?n,但是如果二叉搜索樹(shù)退化成了一棵單分支的樹(shù),其平均比較次數(shù)為:n/2,就是最差的情況了
這就相當(dāng)于是一個(gè)順序表的查找了,這樣二叉搜索樹(shù)的優(yōu)勢(shì)就完全消失了,因此就引入了AVL樹(shù)!
3.什么是AVL樹(shù)
AVL樹(shù)又稱自平衡二叉查找樹(shù),是高度平衡的二叉搜索樹(shù),就是在二叉搜索樹(shù)的基礎(chǔ)上進(jìn)行了優(yōu)化,既當(dāng)向二叉搜索樹(shù)中插入新結(jié)點(diǎn)后,保證每個(gè)結(jié)點(diǎn)的左右子樹(shù)高度之差的絕對(duì)值不超過(guò)1(需要對(duì)樹(shù)中的結(jié)點(diǎn)進(jìn)行調(diào)整),也就是降低樹(shù)的高度,這樣就可以減少平均搜索長(zhǎng)度了,因此AVL樹(shù)滿足它的左右子樹(shù)都是AVL樹(shù),左右子樹(shù)高度之差(簡(jiǎn)稱平衡因子)的絕對(duì)值不超過(guò)1(-1/0/1),這就是AVL樹(shù)的優(yōu)勢(shì)所在,因此如果一棵二叉搜索樹(shù)是高度平衡的,它就是AVL樹(shù)。如果它有n個(gè)結(jié)點(diǎn),其高度可保持在,搜索時(shí)間復(fù)雜度O(log2nlog_2{n}log2?n)!!!
平衡因子=右子樹(shù)的高度-左子樹(shù)的高度
二.自己構(gòu)造AVL樹(shù)
這里的構(gòu)造還是和二叉搜索樹(shù)的構(gòu)造差不多的,只不過(guò)在這里插入元素的話就需要考慮平衡因子的事情了,因?yàn)橐欢ㄒWC插入元素后此樹(shù)還是一棵AVL樹(shù),就需要進(jìn)行相關(guān)調(diào)整,這里就先不過(guò)多介紹了,下面再詳細(xì)介紹,先來(lái)構(gòu)造一棵簡(jiǎn)單的AVL樹(shù):
publicclassAVLTree{
staticclassTreeNode{
//內(nèi)部類,表示AVL樹(shù)的每個(gè)節(jié)點(diǎn)
//val值
publicintval;
//左孩子的引用
publicTreeNodeleft;
//右孩子的引用
publicTreeNoderight;
//父親節(jié)點(diǎn)的引用
publicTreeNodeparent;
//平衡因子(每個(gè)節(jié)點(diǎn)都有)
publicintbf;
publicTreeNode(intval){
this.val=val;
//根節(jié)點(diǎn)
publicTreeNoderoot;
publicbooleaninsert(intval){
}
這樣一棵簡(jiǎn)單的AVL樹(shù)就構(gòu)造好了,下面就來(lái)寫一下AVL樹(shù)的插入!
三.AVL樹(shù)的插入和刪除
1.插入
首先就是將節(jié)點(diǎn)插進(jìn)來(lái),和二叉搜索樹(shù)一樣,先只看位置在哪,不關(guān)注平衡因子
這個(gè)為要插入節(jié)點(diǎn):
TreeNodenode=newTreeNode(val);
if(root==null){
//沒(méi)有根節(jié)點(diǎn),要插入的就是根節(jié)點(diǎn)
root=node;
returntrue;
//記錄每個(gè)節(jié)點(diǎn)的父節(jié)點(diǎn)
TreeNodeparent=null;
//要移動(dòng)的代節(jié)點(diǎn)
TreeNodecur=root;
//根據(jù)val的值和root進(jìn)行比較來(lái)確定應(yīng)該插入節(jié)點(diǎn)的位置
while(cur!=null){
if(cur.valval){
//大于證明此節(jié)點(diǎn)應(yīng)在左子樹(shù)
parent=cur;
cur=cur.left;
}elseif(cur.valval){
//大于證明此節(jié)點(diǎn)應(yīng)在右子樹(shù)
parent=cur;
cur=cur.right;
}else{
//不能有值一樣的節(jié)點(diǎn)
returnfalse;
//此時(shí)cur為空,需要找到對(duì)應(yīng)的位置
if(parent.valval){
parent.left=node;
}else{
parent.right=node;
此時(shí)節(jié)點(diǎn)就已經(jīng)插進(jìn)來(lái)了,此時(shí)就需要看其每個(gè)節(jié)點(diǎn)的平衡因子了
//而此時(shí)就需要對(duì)樹(shù)進(jìn)行平衡因子的調(diào)整了,保證樹(shù)是高度平衡的
//再反著回去寫
node.parent=parent;
cur=node;
//當(dāng)父親節(jié)點(diǎn)一直存在的時(shí)候,就表示沒(méi)有調(diào)到根節(jié)點(diǎn)就需要繼續(xù)調(diào)整
while(parent!=null){
if(cur==parent.right){
//在右邊右樹(shù)高度加一,因此bf+1
parent.bf++;
}else{
//再左邊,左樹(shù)高度加一,因此bf-1
parent.bf--;
//在這里就要進(jìn)行判斷了,如果此時(shí)的父親節(jié)點(diǎn)如果平衡因子為0了,那么就不需要再往上走了,因?yàn)樯厦娴亩际瞧胶獾?/p>
if(parent.bf==0){
returntrue;
}elseif(parent.bf==-1||parent.bf==1){
//此時(shí)父親節(jié)點(diǎn)的平衡因子為1、-1
//此時(shí)表示當(dāng)前樹(shù)平衡了,但是不表示整棵樹(shù)都平衡了,因此還需要繼續(xù)往上走
cur=parent;
parent=cur.parent;
}else{
//此時(shí)父親節(jié)點(diǎn)的平衡因子為2、-2
if(parent.bf==2){
//此時(shí)右樹(shù)高需要降低右樹(shù)的高度
if(cur.bf==1){
//左單旋
rotateLeft(parent);
}else{
//右左雙旋
rotateRL(parent);
}else{
//此時(shí)左樹(shù)高,需要降低左樹(shù)的高度
if(cur.bf==1){
//左右雙旋
rotateLR(parent);
}else{
//右單旋
rotateRight(parent);
//調(diào)整完就平衡了
break;
}
這是當(dāng)前會(huì)出現(xiàn)的問(wèn)題:
先來(lái)討論一下調(diào)整平衡因子會(huì)出現(xiàn)的一些情況,來(lái)分別看一下:
首先是平衡因子調(diào)整為0了,那么就不需要再往上走了,因?yàn)樯厦娴亩际瞧胶獾?,?dāng)前的父親節(jié)點(diǎn)的平衡因子為0了表示插入的這個(gè)元素只影響到了這一棵樹(shù),上面是沒(méi)有影響的,因此是0的話就結(jié)束了
因此是0的話就表示當(dāng)前已經(jīng)結(jié)束了,不需要再往上了,其他變?yōu)?的情況也是一樣的這里就不細(xì)畫了
而如果是1或者-1的話,表示當(dāng)前樹(shù)平衡了,但是不表示整棵樹(shù)平衡了,因此需要再往上走;
而如果是2或者-2的話,會(huì)以下四種情況,再來(lái)分別看一下:
1.1.右單旋
此時(shí)左樹(shù)高,需要降低左樹(shù)的高度,也就是右旋(parent.bf=-2,cur.bf=-1):
也就是如下的效果:
也就是這樣的調(diào)整過(guò)程:
下面寫一下代碼:
privatevoidrotateRight(TreeNodeparent){
//右單旋
//此時(shí)parent的平衡因子為-2,cur的平衡因子為-1
TreeNodecur=parent.left;
//記錄cur的右節(jié)點(diǎn)
TreeNodecurR=cur.right;
parent.left=curR;
cur.right=parent;
//如果cur有右節(jié)點(diǎn)需要賦給parent的左節(jié)點(diǎn),但是沒(méi)有就不需要給了
if(curR!=null){
curR.parent=parent;
//然后將cur的右孩子改變?yōu)閜arent
//需要記錄parent的根節(jié)點(diǎn)
TreeNodepParent=parent.parent;
parent.parent=cur;
//檢查當(dāng)前是不是根節(jié)點(diǎn),不是根節(jié)點(diǎn)需要看是左子樹(shù),還是右子樹(shù)
if(pParent!=null){
//改變之前的指向
cur.parent=pParent;
if(parent==pParent.right){
pParent.right=cur;
}else{
pParent.left=cur;
}else{
//此時(shí)parent就是root,因?yàn)闆](méi)有根節(jié)點(diǎn)
root=cur;
root.parent=null;
//最后記得一定要修改平衡因子
parent.bf=0;
cur.bf=0;
}
這樣一個(gè)簡(jiǎn)單的右單旋就結(jié)束了~
1.2.左單旋
這種情況就是最開(kāi)始的情況了
此時(shí)右樹(shù)高,需要降低右樹(shù)的高度,也就是左旋(parent.bf=2,cur.bf=1):
也就是如下的效果:
也就是這樣的調(diào)整過(guò)程:
代碼如下:
privatevoidrotateLeft(TreeNodeparent){
//左單旋
//此時(shí)parent平衡因子為2,cur的平衡因子為1
//需要記錄父親節(jié)點(diǎn)
TreeNodepParent=parent.parent;
TreeNodecur=parent.right;
//記錄cur的左節(jié)點(diǎn)
TreeNodecurL=cur.left;
parent.right=curL;
cur.left=parent;
//判斷左節(jié)點(diǎn)是不是空的,如果是空的就不需要管了,不是空的就需要將parent右節(jié)點(diǎn)指向它,并且它的父親節(jié)點(diǎn)為parent
if(curL!=null){
//改變指向
curL.parent=parent;
//改變cur的指向
parent.parent=cur;
//判斷如果pParent不為空,就表示parent不是root,就需要看其是左孩子還是右孩子
if(pParent!=null){
cur.parent=pParent;
if(parent==pParent.right){
pParent.right=cur;
}else{
pParent.left=cur;
}else{
//是根節(jié)點(diǎn)
root=cur;
root.parent=null;
cur.bf=0;
parent.bf=0;
}
這樣一個(gè)簡(jiǎn)單的左單旋就結(jié)束了~
1.3.左右雙旋
此時(shí)左樹(shù)高,需要降低左樹(shù)的高度,(parent.bf=-2,cur.bf=1):
而此時(shí)僅通過(guò)單旋是無(wú)法完成的,需要通過(guò)兩種旋轉(zhuǎn)才能完成:
上面左單旋和右單旋已經(jīng)介紹過(guò)了,這里就不詳細(xì)介紹了,
先左旋:
此時(shí)修改的平衡因子是沒(méi)有用的
再右旋:
兩次旋轉(zhuǎn)之后只需要進(jìn)行平衡因子的改變就可以了,
通過(guò)觀察curR的平衡因子,會(huì)決定最后其他節(jié)點(diǎn)的平衡因子
代碼如下:
privatevoidrotateLR(TreeNodeparent){
//左右雙旋
TreeNodecur=parent.left;
TreeNodecurR=cur.right;
//此時(shí)就需要看curR的平衡因子,再?zèng)Q定最后其他節(jié)點(diǎn)的平衡因子
intbf=curR.bf;
//先調(diào)用左旋再右旋
rotateLeft(cur);
rotateRight(parent);
//這里通過(guò)規(guī)律可以得到當(dāng)curR的bf值不同的時(shí)候,其需要改變的bf值也是不同的,因此里就需要做出修改
if(bf==-1){
//當(dāng)bf為-1時(shí),其應(yīng)修改的如下
curR.bf=0;
cur.bf=0;
parent.bf=1;
}elseif(bf==1){
//當(dāng)bf為1時(shí),其應(yīng)修改的如下
curR.bf=0;
cur.bf=-1;
parent.bf=0;
//另外當(dāng)bf為0的時(shí)候就已經(jīng)平衡了,就不需要改了,因?yàn)樵趦纱涡D(zhuǎn)的時(shí)候就已經(jīng)將其改為0了
這樣一個(gè)左右雙旋就結(jié)束了~
1.4.右左雙旋
此時(shí)右樹(shù)高,需要降低右樹(shù)的高度(parent.bf=2,cur.bf=-1):
而此時(shí)僅通過(guò)單旋是無(wú)法完成的,需要通過(guò)兩種旋轉(zhuǎn)才能完成:
先右旋:
再左旋:
通過(guò)觀察發(fā)現(xiàn)其需要改變的平衡因子和curL有關(guān)系:
因此
代碼如下:
privatevoidrotateRL(TreeNodeparent){
//右左雙旋
Tree
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 紡紗工藝參數(shù)優(yōu)化與調(diào)整考核試卷
- 幼兒園活動(dòng)設(shè)計(jì)要點(diǎn)
- 自行車配件市場(chǎng)供需分析考核試卷
- 網(wǎng)絡(luò)安全風(fēng)險(xiǎn)識(shí)別與防范考核試卷
- 《卓越發(fā)展》:課件展示
- 刀具的設(shè)計(jì)與性能評(píng)估方法考核試卷
- 電力設(shè)備中低壓配電柜設(shè)計(jì)與選型考核試卷
- 收藏品市場(chǎng)調(diào)研報(bào)告撰寫技巧考核試卷
- 航運(yùn)企業(yè)競(jìng)爭(zhēng)力評(píng)價(jià)考核試卷
- 節(jié)能環(huán)保與健康城市考核試卷
- 《肺結(jié)核的診斷與治療》課件
- 陜西省咸陽(yáng)市2025屆高三下學(xué)期高考模擬檢測(cè)(三)物理試題(含答案)
- 浙江省溫州市2023-2024學(xué)年高一下學(xué)期期末考試語(yǔ)文試卷(含答案)
- (高清版)DB3301∕T 0411-2023 公共汽電車維修車間建設(shè)與管理規(guī)范
- 激光應(yīng)用技術(shù)發(fā)展路徑試題及答案
- 期權(quán)開(kāi)戶考試題及答案
- 國(guó)家職業(yè)技能標(biāo)準(zhǔn)-(糧油)倉(cāng)儲(chǔ)管理員
- 無(wú)人駕駛技術(shù)在旅游景區(qū)的自動(dòng)駕駛巴士的創(chuàng)新實(shí)踐
- 人教版八下道德與法治教學(xué)設(shè)計(jì):2.2加強(qiáng)憲法監(jiān)督
- 血透患者的血壓管理
- 《自動(dòng)化生產(chǎn)線集成與應(yīng)用- Integration》課件-項(xiàng)目一 自動(dòng)化生產(chǎn)線概述
評(píng)論
0/150
提交評(píng)論