二叉查詢樹節點的刪除
阿新 • • 發佈:2019-01-28
簡介
本文將介紹如何從二叉查詢樹中刪除某個任意的節點。由於二叉樹特有的結構,即:
(1)所有左子樹中的節點小於等於根節點
(2)所有右子樹中的節點大於等於根節點
(3)對於任意節點滿足(1)(2)
所以二叉查詢樹節點刪除關鍵在於如何保證不破壞二叉查詢樹的性質。
問題分析
二叉查詢樹刪除節點可以分成三種情況:
(1)刪除葉子節點
葉子節點刪除是最簡單的情況,由於葉子節點沒有左右子樹,刪除後不會破壞原有的樹形結構,所以我們只需要找到節點並且把它置為null即可。
如圖:
(2)被刪除的節點只有一個子節點
比如我們要刪除上圖中3所在的節點,3只有一個左子樹1。
實際上我們只需要把5所在節點的左子樹指向原來3的左子樹即可。
如圖:
(3)被刪除的節點左右子樹都有
這種情況是比較複雜的,為了不破壞二叉查詢書的結構,我們可以按照以下操作進行:
- 找出左子樹中最大或者右子樹中最小的值val
- 將當前節點的值替換為val
在左子樹或者右子樹中找到val刪除
Note:
由於二叉查詢樹的性質,如果將當前節點替換為左子樹中最大的或者右子樹中最小的一定不會破壞二叉查詢樹的結構。
如圖:
程式碼
public TreeNode deleteNode(TreeNode root, int key) {
if(root == null){
return root;
}
if (key < root.val){
root.left = deleteNode(root.left, key);
return root;
}
if(key > root.val){
root.right = deleteNode(root.right, key);
return root;
}
//開始執行刪除操作
//(1)刪除根節點
if(root.left == null && root.right == null){
root = null;
return root;
}
//(2)只有一個child,只有左子樹
if(root.left == null && root.right != null){
root = root.right;
return root;
}
//(2)只有一個child,只有右子樹
if(root.right == null && root.left != null){
root = root.left;
return root;
}
//(3)有兩個child
if(root.left != null && root.right != null){
//挑選左子樹中最大的或者右子樹中最小的,替換當前節點,再將替換的節點置空
int val = findMaxInLeftTree(root.left);
root.val = val;
root.left = deleteNode(root.left, val);
return root;
}
return root;
}
//找到左子樹中最大的值
private int findMaxInLeftTree(TreeNode left) {
if(left == null){
return 0;
}
if(left.right == null){
return left.val;
}
if(left.right == null && left.left == null){
return left.val;
}
return findMaxInLeftTree(left.right);
}
}