相關介紹: 二叉查找樹的查找效率與二叉樹的形狀有關,對於按給定序列建立的二叉排序樹,若其左、右子樹均勻分佈,則查找過程類似於有序表的二分查找,時間複雜度變為O(log2n)。當若給定序列原來有序,則建立的二叉查找樹就蛻化為單鏈表,其查找效率同順序查找一樣,時間複雜度為O(n)。因此,在構 ...
相關介紹:
二叉查找樹的查找效率與二叉樹的形狀有關,對於按給定序列建立的二叉排序樹,若其左、右子樹均勻分佈,則查找過程類似於有序表的二分查找,時間複雜度變為O(log2n)。當若給定序列原來有序,則建立的二叉查找樹就蛻化為單鏈表,其查找效率同順序查找一樣,時間複雜度為O(n)。因此,在構造二叉查找樹的過程中,當出現左右子樹分佈不均勻時,若能對其進行調整,使其依然保持均勻,則就能有效的保證二叉查找樹仍具有較高的查找效率。而平衡二叉樹,正是這樣的一棵樹。
平衡二叉樹,又稱為AVL樹,它或是一棵空樹,或是一棵具有如下性質的二叉樹:它的左子樹和右子樹均為平衡二叉樹,且左子樹和右子樹深度之差的絕對值不超過1
在平衡二叉樹上插入或刪除節點後,可能使二叉樹失去平衡。因此,需要對失去平衡的二叉樹進行調整,以保持平衡二叉樹的性質。以下,主要介紹如何動態地使一棵二叉查找樹保持平衡,即對失去平衡的二叉查找樹進行平衡化調整。這裡引入了平衡因數的概念。
所謂的平衡因數,指的是二叉樹中某個節點的左子樹深度與右子樹深度之差,平衡因數也稱為平衡度。平衡二叉樹也就是樹中任意節點的平衡因數的絕對值小於等於1的二叉樹。在AVL樹中的節點的平衡因數有3種取值情況:1(左子樹深度大於右子樹深度),0(左子樹深度等於右子樹深度),-1(左子樹深度小於右子樹深度)
在以下給出的例子中,為了敘述方便,假設在AVL樹上因插入新節點而失去平衡的最小子樹的根節點為A,即A為距離插入節點最近的,平衡因數不是-1、0和1的節點。失去平衡後的操作可 依據失去平衡的原因(此處為便於記憶的訣竅的一個關鍵,如“LL型平衡旋轉”,指的是,在A的左孩子節點(L)的左孩子節點(L)中插入一個新的節點所導致的不平衡問題) 歸納為下列4種情況分別進行介紹:
- LL型平衡旋轉(單向右旋):由於在A的左孩子的左子樹上插入新節點,使得A的平衡度由1增加至2,致使以A為根的子樹失去平衡。此時,應該進行一次向右的順時針旋轉操作,“提升”B(即為A的左孩子)為新子樹的根節點,A下降為B的右孩子,同時將B原來的右子樹B-R調整為A的左子樹。其過程如下圖所示:
- RR型平衡旋轉(單向左旋):由於在A的右孩子的右子樹上插入新節點,使得A的平衡度由-1轉變為-2,致使以A為根的子樹失去平衡。此時,應該進行一次的向左的逆時針旋轉操作,“提升”B(即A的右孩子)為新子樹的根節點,A下降為B的左子樹,同時將B原來的左子樹B-L調整為A的右子樹。其過程如下圖所示:
- LR型平衡旋轉(先左旋後右旋):由於在A的左孩子的右子樹上插入新節點,使得A的平衡度由1變為2,致使以A為根的子樹失去平衡。此時,應當進行兩次選裝操作(先逆時針,後順時針)“提升”C(即A的左孩子的右孩子)為新子樹的根節點;A下降為C的右孩子;B變為C的左孩子;C原來的左子樹C-L調整為B現在的右子樹;C原來的右子樹C-R調整為A的左子樹。其過程如下圖所示:
或
- RL型平衡旋轉(先右旋後左旋):由於在A的右孩子的左子樹上插入新節點,使A的平衡度由-1變為-2,致使以A為根的子樹失去平衡,此時,應進行兩次旋轉操作(先順時針,後逆時針),“提升”C(即A的右孩子的左孩子)為新子樹的根節點;A下降為C的左孩子;B變為C的右孩子;C原來的左子樹C-L調整為A現在的右子樹;C原來的右子樹C-R調整為B的左子樹。其過程如下圖所示:
或
綜上所述:在平衡二叉查找樹T上插入一個新記錄x的演算法描述如下:
- 若AVL樹為空樹,則插入一個記錄為x的新節點作為T的根節點,樹的深度增加1。
- 若x的關鍵字值和AVL樹T的根節點的關鍵字值相等,則不進行插入操作。
若X的關鍵字值小於AVL樹的根節點的關鍵字值,則將x插入在該樹的左子樹上,並且當插入之後的左子樹深度增加1時,分別就下列不同情況進行處理:
若AVL樹的根節點的平衡因數為-1(右子樹的深度大於左子樹的深度),則將根節點的平衡因數調整為0,並且樹的深度不變
若AVL樹的根節點的平衡因數為0(左右子樹的深度相等)。則將根節點的平衡因數調整為1,樹的深度同時增加1
若AVL樹的根節點的平衡因數為1(左子樹的深度大於右子樹的深度),則當該樹的左子樹的根節點的平衡因數為1時需要進行LL型平衡旋轉;當該樹的左子樹的根節點的平衡因數為-1時需進行LR型平衡旋轉
若x的關鍵字值大於AVL樹的根節點的關鍵字值,則將x插入在該樹的右子樹上,並且當插入之後的右子樹深度增加1時,分別就下列不同情況進行處理:
- 若AVL樹的根節點的平衡因數為-1時(右子樹的深度大於左子樹的深度),則當該樹的右子樹的根節點的平衡因數為-1時需進行RR型平衡旋轉;當該樹的右子樹的根節點的平衡因數為1時需進行RL型平衡旋轉
2.若AVL樹的根節點的平衡因數為0時(左右子樹的深度相等),則將根節點的平衡因數調整為-1,樹的深度同時增加1
- 若AVL樹的根節點的平衡因數為1時(左子樹的深度大於右子樹的深度),則將根節點的平衡因數調整為0,並且樹的深度保持不變
平衡二叉樹的優缺點分析:
優點:使二叉樹的結構更好(即不會出現“偏拐”嚴重的情況),從而提高了查找操作的速度。
缺點:使插入和刪除操作複雜化,從而減低了插入和刪除操作的速度。
總結:平衡二叉樹適用於二叉查找樹一經建立就很少進行插入和刪除操作,而主要進行查找操作的應用場合上。由於其在查找過程中和給定值進行比較的關鍵字個數不超過樹的深度。因此,在平衡二叉樹上進行查找的時間複雜度為O(log2n)
相關操作示例代碼:
對於平衡二叉樹,其常見的操作有插入、刪除、查找操作。其中,插入和刪除某個節點時,需要對失去平衡的平衡二叉查找樹進行相應的旋轉操作,以使平衡二叉樹保持結構上的穩定。
下麵代碼定義了平衡二叉查找樹的節點:
相關代碼:
/**
* 該類用於定義平衡二叉樹的節點的相關數據
* @author 學徒
*
*/
class AVLTreeNode
{
//節點的關鍵字
Comparable key;
//節點的數據
Object data;
//節點的左子樹指針
AVLTreeNode left;
//節點的右子樹指針
AVLTreeNode right;
public AVLTreeNode(Comparable key,Object data)
{
this(key,data,null,null);
}
public AVLTreeNode(Comparable key,Object data,AVLTreeNode left,AVLTreeNode right)
{
this.data=data;
this.key=key;
this.left=left;
this.right=right;
}
}
對於查找操作,其先與根節點的關鍵字的值進行比較,根據比較所得的結果,選擇返回其相關的數據或者是遞歸的在該節點的左右子樹中進行查找
下麵代碼演示了查找的操作:
相關代碼:
/**
* 用於平衡二叉樹中的查找操作,並返回相應節點的相關數據,當未查找到時,返回null
* @param key 要進行查找的節點的關鍵字
* @return 得到要進行查找節點的相關數據
*/
public Object search(Comparable key)
{
if(key==null)
return null;
return getSearchResult(root,key);
}
/**
* 用於輔助平衡二叉樹的查找操作,並返回相應的相關節點的數據,當未查找到時,返回null
* @param root 要進行查找的二叉查找樹的根節點
* @param key 要進行查找的節點的關鍵字
* @return 得到要進行查找節點的相關數據
*/
private Object getSearchResult(AVLTreeNode root,Comparable key)
{
if(root==null)
return null;
int compare=key.compareTo(root.key);
if(compare==0)
return root.data;
else if(compare==1)
return getSearchResult(root.right,key);
else
return getSearchResult(root.left,key);
}
對於插入操作,先根據其關鍵字值的大小關係,在平衡二叉樹中插入相應的節點。之後,遍歷該新插入節點的路徑中各個根節點的平衡因數的情況,根據其平衡因數的值,選擇性的對其進行旋轉操作,需要註意的是在該路徑上最多只存在一次“失衡”的情況。為此,在對其路徑上的節點進行過旋轉操作之後,其平衡二叉樹整體便是處於“平衡”的狀態的
下麵代碼演示了插入操作:
相關代碼:
/**
* 用於往二叉樹中插入新的節點
* @param key 二叉樹中新節點的關鍵字
* @param data 二叉樹中新節點的數據
* @return 插入新節點的結果,如果成功插入一個新節點則返回true,否則返回false,當新增的節點存在於樹中時,返回false
*/
public boolean insert(Comparable key,Object data)
{
if(key==null)
return false;
else if(root!=null)
{
return insertAVLTreeNode(root,null,key,data);
}
else
{
root=new AVLTreeNode(key,data);
return true;
}
}
/**
* 輔助往二叉樹中插入新的節點
* @param node 要進行比較的二叉樹的節點
* @param parent 要進行比較的二叉樹的節點的父節點
* @param key 新增節點的關鍵字值
* @param data 新增節點的數據
* @return 新增的結果
*/
private boolean insertAVLTreeNode(AVLTreeNode node,AVLTreeNode parent,Comparable key,Object data)
{
//噹噹前比較的節點不為空的時候,進行比較操作
if(node!=null)
{
int compare=key.compareTo(node.key);
if(compare==0)
return false;
else if(compare>0)
return insertAVLTreeNode(node.right,node,key,data);
else
return insertAVLTreeNode(node.left,node,key,data);
}
//當前的節點為空的時候,進行從其父節點處插入節點的操作。同時,進行旋轉判斷和相應的操作
else
{
Comparable parentKey=parent.key;
AVLTreeNode newNode=new AVLTreeNode(key,data);
int comparable=parentKey.compareTo(key);
//插入新增節點
if(comparable>0)
parent.left=newNode;
else
parent.right=newNode;
//對插入完後的節點進行判斷,查看其是否需要進行旋轉操作,當需要時,對其進行進行旋轉調整平衡二叉樹相應的節點情況
rotate(root,null,newNode);
return true;
}
}
對於刪除操作,其只需要在二叉樹中找到要進行刪除的節點的父節點。之後移動相應的指針即可對其進行刪除操作,同時用其按照關鍵字有序的後繼節點對其進行補充即可,之後從對到其進行刪除節點的父節點的路徑上的所有節點進行遍歷,當存在因為刪除節點而導致其失去平衡的情況,則對其進行相應的平衡旋轉操作
下麵代碼演示了刪除操作:
相關代碼:
/**
* 用於進行刪除操作
* @param key 要進行刪除操作的節點的關鍵字值
* @return 返回所刪除節點的數據值,當無相關的刪除節點的時候,返回null
*/
public Object delete(Comparable key)
{
if(key==null)
return null;
else
return remove(root,key,null);
}
/**
* 用於輔助進行刪除操作的方法
* @param node 當前比較節點
* @param parent 當前比較節點的雙親節點
* @param key 需要進行刪除的節點的關鍵字值
* @return 返回所刪除節點的關鍵字
*/
public Object remove(AVLTreeNode node,Comparable key,AVLTreeNode parent)
{
if (node != null)
{
int compare = key.compareTo(node.key);
// 從左子樹中進行刪除
if (compare < 0)
{
return remove(node.left, key, node);
}
// 從右子樹中進行刪除
else if (compare > 0)
{
return remove(node.right, key, node);
}
// 當前節點即為要進行刪除的節點
else
{
// 當前要進行刪除的節點的數據
Object result = node.data;
// 當前要進行刪除的節點的左右子樹均存在
if (node.left != null && node.right != null)
{
// 尋找要進行刪除節點的替換節點
AVLTreeNode innext = node.right;
//要進行替換的節點的雙親節點
AVLTreeNode innextParent=node;
// 尋找右子樹下的最左孩子節點
while (innext.left != null)
{
innextParent=innext;
innext = innext.left;
}
// 改變刪除節點的相關數據
node.data = innext.data;
node.key = innext.key;
//遞歸的刪除其進行替換的節點
remove(node.right,innext.key,node);
//對從當前被刪除節點開始的到其相應的替換節點的父節點的路徑上判斷其是否“失衡”且進行相關的旋轉操作
rotate(node,null,innextParent);
}
// 以下考慮的情況均當前刪除節點缺少左子樹或者右子樹的情況
else
{
// 當前要進行刪除的節點不為根節點的時候
if (parent != null)
{
// 當左子樹不為空的時候
if (node.left != null && node.right == null)
{
// 當前節點為其左子樹節點的時候
if (node == parent.left)
{
parent.left = node.left;
}
// 當前節點為其右子樹節點的時候
else
{
parent.right = node.left;
}
if(node.left!=null)
{
//由於其刪除節點缺少左子樹或者右子樹。為此,其只需判斷當前刪除節點的父節點的失衡情況併進行相應的調整即可
rotate(parent,null,node.left);
}
}
// 當右子樹不為空的時候或為葉子節點的時候
else
{
// 當前節點為其左子樹節點的時候
if (node == parent.left)
{
parent.left = node.right;
}
// 當前節點為其右子樹節點的時候
else
{
parent.right = node.right;
}
if(node.right!=null)
{
//由於其刪除節點缺少左子樹或者右子樹。為此,其只需判斷當前刪除節點的父節點的失衡情況併進行相應的調整即可
rotate(parent,null,node.right);
}
}
}
// 當前刪除的節點為根節點的時候
else
{
if (node.left != null)
root = node.left;
else
root = node.right;
}
}
// 返回其進行刪除的節點的值
return result;
}
}
return null;
}
完整示例代碼如下:
相關代碼:
package all_in_tree;
/**
* 該類用於演示平衡二叉樹的相關操作
* @author 學徒
*
*/
public class AVLTree
{
//該平衡二叉樹的根節點
private AVLTreeNode root;
/**
* 對該平衡二叉樹進行後續遍歷操作(後序遍歷的結果是按序排序的),以便用於驗證其測試的結果
*/
public static void inTravel(AVLTreeNode root)
{
if(root!=null)
{
inTravel(root.left);
System.out.print(root.key+"-"+root.data+"\t");
inTravel(root.right);
}
}
/**
* 用於獲取該平衡二叉樹
* @return 該平衡二叉樹的根節點指針
*/
public AVLTreeNode getTree()
{
return this.root;
}
/**
* 用於得到一棵以root為根節點的樹的深度
* @param root 需要獲取的樹的深度的根節點指針
* @return 以root為根節點的樹的深度
*/
private int getDepth(AVLTreeNode root)
{
if(root==null)
return 0;
return Math.max(getDepth(root.left),getDepth(root.right))+1;
}
/**
* 用於判斷以root為根節點的二叉樹的平衡情況,true為平衡的,false表示並不平衡
* @param root 要判斷其平衡因數的子樹的根節點指針
* @return 以root為根節點的平衡二叉樹的平衡情況
*/
private boolean isBalance(AVLTreeNode root)
{
return Math.abs(getDepth(root.left)-getDepth(root.right))<=1;
}
/**
* 用於獲取以root為根節點的二叉樹的平衡因數
* @param root為求取其平衡因數的子樹的根節點的指針
* @return 平衡因數
*/
private int getBalance(AVLTreeNode root)
{
return getDepth(root.left)-getDepth(root.right);
}
/**
* 用於平衡二叉樹中的查找操作,並返回相應節點的相關數據,當未查找到時,返回null
* @param key 要進行查找的節點的關鍵字
* @return 得到要進行查找節點的相關數據
*/
public Object search(Comparable key)
{
if(key==null)
return null;
return getSearchResult(root,key);
}
/**
* 用於輔助平衡二叉樹的查找操作,並返回相應的相關節點的數據,當未查找到時,返回null
* @param root 要進行查找的二叉查找樹的根節點
* @param key 要進行查找的節點的關鍵字
* @return 得到要進行查找節點的相關數據
*/
private Object getSearchResult(AVLTreeNode root,Comparable key)
{
if(root==null)
return null;
int compare=key.compareTo(root.key);
if(compare==0)
return root.data;
else if(compare==1)
return getSearchResult(root.right,key);
else
return getSearchResult(root.left,key);
}
/**
* 以所傳入的節點的指針為根節點的二叉樹,進行右旋的操作
* @param node 要進行右旋的二叉樹的根節點
* @return 旋轉後的二叉樹的根節點的指針
*/
private AVLTreeNode rightRotate(AVLTreeNode node)
{
//用於記錄旋轉後的結果
AVLTreeNode result=node.left;
node.left=result.right;
result.right=node;
return result;
}
/**
* 以所傳入的節點的指針為根節點的二叉樹,進行左旋的操作
* @param node 要進行左旋的二叉樹的根節點
* @return 旋轉後的二叉樹的根節點的指針
*/
private AVLTreeNode leftRotate(AVLTreeNode node)
{
//用於記錄旋轉後的結果
AVLTreeNode result=node.right;
node.right=result.left;
result.left=node;
return result;
}
/**
* 用於往二叉樹中插入新的節點
* @param key 二叉樹中新節點的關鍵字
* @param data 二叉樹中新節點的數據
* @return 插入新節點的結果,如果成功插入一個新節點則返回true,否則返回false,當新增的節點存在於樹中時,返回false
*/
public boolean insert(Comparable key,Object data)
{
if(key==null)
return false;
else if(root!=null)
{
return insertAVLTreeNode(root,null,key,data);
}
else
{
root=new AVLTreeNode(key,data);
return true;
}
}
/**
* 輔助往二叉樹中插入新的節點
* @param node 要進行比較的二叉樹的節點
* @param parent 要進行比較的二叉樹的節點的父節點
* @param key 新增節點的關鍵字值
* @param data 新增節點的數據
* @return 新增的結果
*/
private boolean insertAVLTreeNode(AVLTreeNode node,AVLTreeNode parent,Comparable key,Object data)
{
//噹噹前比較的節點不為空的時候,進行比較操作
if(node!=null)
{
int compare=key.compareTo(node.key);
if(compare==0)
return false;
else if(compare>0)
return insertAVLTreeNode(node.right,node,key,data);
else
return insertAVLTreeNode(node.left,node,key,data);
}
//當前的節點為空的時候,進行從其父節點處插入節點的操作。同時,進行旋轉判斷和相應的操作
else
{
Comparable parentKey=parent.key;
AVLTreeNode newNode=new AVLTreeNode(key,data);
int comparable=parentKey.compareTo(key);
//插入新增節點
if(comparable>0)
parent.left=newNode;
else
parent.right=newNode;
//對插入完後的節點進行判斷,查看其是否需要進行旋轉操作,當需要時,對其進行進行旋轉調整平衡二叉樹相應的節點情況
rotate(root,null,newNode);
return true;
}
}
/**
* 用於輔助新插入節點是否旋轉的判斷,並作出相應的操作
* @param root 當前查找的節點的情況
* @param parent 當前查找節點的雙親節點
* @param node 進行旋轉操作的路徑的終止節點
*/
private void rotate(AVLTreeNode root,AVLTreeNode parent,AVLTreeNode node)
{
//由此得出當前查找節點的查找方向
int compare=root.key.compareTo(node.key);
//當找到該新增節點的時候,其路徑上的各個節點的平衡因數均不“失衡”則直接進行返回,不進行操作
if(compare==0)
{
return;
}
//當平衡且當前節點的關鍵字值小於新增節點的關鍵字值的時候,往右邊進行查找
else if(compare<0&&isBalance(root))
{
//當其路徑上的根節點平衡的時候,往右邊查找
rotate(root.right,root,node);
}
//當平衡且當前節點的關鍵字值大於新增節點的關鍵字值的時候,往左邊進行查找
else if(compare>0&&isBalance(root))
{
//當其路徑上的子樹的根節點平衡的時候,往左邊進行查找
rotate(root.left,root,node);
}
//當失衡的時候,對其進行旋轉操作
else
{
//當其父節點為null的時候,不需要對其進行旋轉操作,因為此時表示樹中的節點數目不超過3個,所以一定不會有失衡的情況產生
if(parent!=null)
{
//當其失衡的時候,對其進行旋轉操作
//用於判斷是從其父節點的左邊失衡的還是右邊
boolean isLeft=parent.left.key.compareTo(root.key)==0?true:false;
//用於獲取該失衡節點的平衡因數
int balance=getBalance(root);
//大於0的時候,要麼進行LL型旋轉,要麼進行LR型旋轉
if(balance>0)
{
//用於獲取其孩子節點的平衡因數,根據其平衡因數的情況,進行相應的旋轉操作
int childBalance=getBalance(root.left);
//對其相應的孩子節點為根節點的子樹進行左旋
if(childBalance<0)
{
root.left=leftRotate(root.left);
}
//對以失衡的樹的根節點為子樹的樹進行右旋操作
AVLTreeNode rotateNode=rightRotate(root);
if(isLeft)
parent.left=rotateNode;
else
parent.right=rotateNode;
}
//小於0的時候,要麼進行RR型旋轉,要麼進行RL型旋轉
else
{
//用於獲取其孩子節點的平衡因數,根據其平衡因數的情況,進行相應的旋轉操作
int childBalance=getBalance(root.right);
//對其相應的孩子節點為根的子樹進行右旋
if(childBalance>0)
{
root.right=rightRotate(root.right);
}
//對以失衡的樹的根節點為子樹的樹進行左旋操作
AVLTreeNode rotateNode=leftRotate(root);
if(isLeft)
parent.left=rotateNode;
else
parent.right=rotateNode;
}
}
}
}
/**
* 用於進行刪除操作
* @param key 要進行刪除操作的節點的關鍵字值
* @return 返回所刪除節點的數據值,當無相關的刪除節點的時候,返回null
*/
public Object delete(Comparable key)
{
if(key==null)
return null;
else
return remove(root,key,null);
}
/**
* 用於輔助進行刪除操作的方法
* @param node 當前比較節點
* @param parent 當前比較節點的雙親節點
* @param key 需要進行刪除的節點的關鍵字值
* @return 返回所刪除節點的關鍵字
*/
public Object remove(AVLTreeNode node,Comparable key,AVLTreeNode parent)
{
if (node != null)
{
int compare = key.compareTo(node.key);
// 從左子樹中進行刪除
if (compare < 0)
{
return remove(node.left, key, node);
}
// 從右子樹中進行刪除
else if (compare > 0)
{
return remove(node.right, key, node);
}
// 當前節點即為要進行刪除的節點
else
{
// 當前要進行刪除的節點的數據
Object result = node.data;
// 當前要進行刪除的節點的左右子樹均存在
if (node.left != null && node.right != null)
{
// 尋找要進行刪除節點的替換節點
AVLTreeNode innext = node.right;
//要進行替換的節點的雙親節點
AVLTreeNode innextParent=node;
// 尋找右子樹下的最左孩子節點
while (innext.left != null)
{
innextParent=innext;
innext = innext.left;
}
// 改變刪除節點的相關數據
node.data = innext.data;
node.key = innext.key;
//遞歸的刪除其進行替換的節點
remove(node.right,innext.key,node);
//對從當前被刪除節點開始的到其相應的替換節點的父節點的路徑上判斷其是否“失衡”且進行相關的旋轉操作
rotate(node,null,innextParent);
}
// 以下考慮的情況均當前刪除節點缺少左子樹或者右子樹的情況
else
{
// 當前要進行刪除的節點不為根節點的時候
if (parent != null)
{
// 當左子樹不為空的時候
if (node.left != null && node.right == null)
{
// 當前節點為其左子樹節點的時候
if (node == parent.left)
{
parent.left = node.left;
}
// 當前節點為其右子樹節點的時候
else
{
parent.right = node.left;
}
if(node.left!=null)
{
//由於其刪除節點缺少左子樹或者右子樹。為此,其只需判斷當前刪除節點的父節點的失衡情況併進行相應的調整即可
rotate(parent,null,node.left);
}
}
// 當右子樹不為空的時候或為葉子節點的時候
else
{
// 當前節點為其左子樹節點的時候
if (node == parent.left)
{
parent.left = node.right;
}
// 當前節點為其右子樹節點的時候
else
{
parent.right = node.right;
}
if(node.right!=null)
{
//由於其刪除節點缺少左子樹或者右子樹。為此,其只需判斷當前刪除節點的父節點的失衡情況併進行相應的調整即可
rotate(parent,null,node.right);
}
}
}
// 當前刪除的節點為根節點的時候
else
{
if (node.left != null)
root = node.left;
else
root = node.right;
}
}
// 返回其進行刪除的節點的值
return result;
}
}
return null;
}
/**
* 測試用例
* @param args 初始化參數數組
*/
public static void main(String[] args)
{
AVLTree tree=new AVLTree();
tree.insert(5,"A");
tree.insert(2,"B");
tree.insert(6,"D");
tree.insert(1,"E");
tree.insert(3,"C");
tree.insert(4,"F");
AVLTree.inTravel(tree.getTree());
System.out.println();
System.out.println(tree.delete(1));
AVLTree.inTravel(tree.getTree());
System.out.println();
System.out.println(tree.search(5));
}
}
運行結果如下:
1-E 2-B 3-C 4-F 5-A 6-D
E
2-B 3-C 4-F 5-A 6-D
A
其測試用例所用圖如下: