二叉排序樹的刪除情況比較復雜,有以下三種情況需要考慮
- 刪除葉子節點(比如:2,5,9,12)
- 刪除只有一棵子樹的節點(比如1)
- 刪除有兩棵子樹的節點(比如:7,3,10)
- 操作思路分析
第一種情況:刪除葉子節點
思路:
-
- 需要先找到待刪除的節點 targetNode
-
- 找到targetNode的父節點 parent
-
- 確定targetNode是parent的左節點還是右節點
-
- 根據左右來進行刪除
- 左子節點 parent.left = null
- 右子節點 parent.right = null
第二種情況:刪除只有一棵子樹的節點,比如1
思路:
-
- 需要先找到待刪除的節點targetNode
-
- 找到targetNode的父節點 parent
-
- 確定targetNode的子節點是左子節點還是又子節點
-
- targetNode是parent的左子節點還是右子節點
-
- 如果targetNode有左子節點
- 5.1. 如果targetNode是parent的左子節點 parent.left = targetNode.left
- 5.2. 如果targetNode是parent的右子節點 parent.right = targetNode.left
-
- 如果targetNode有右子節點
- 6.1. 如果targetNode是parent的左子節點 parent.left = targetNode.right
- 6.2 如果targetNode是parent的右子節點 parent.right = targetNode.right
第三種情況:刪除有兩棵子樹的節點(比如:7,3,10)
思路:
-
- 需要先找到待刪除的節點 targetNode
-
- 找到targetNode的父節點 parent
-
- 從targetNode的右子樹中找到最小的節點
-
- 用一個臨時變量,將最小的節點值保存在temp中
-
- 刪除該最小的節點
-
- targetNode.val = temp
public class BinarySortTreeDemo {
public static void main(String[] args) {
int[] arr = {7, 3, 10, 12, 5, 1, 9,2};
BinarySortTree binarySortTree = new BinarySortTree();
for (int i = 0; i < arr.length; i++) {
binarySortTree.addNode(new Node(arr[i]));
}
//遍歷
binarySortTree.midOrder();
//測試刪除節點
binarySortTree.delNode(5);
binarySortTree.delNode(9);
binarySortTree.delNode(10);
binarySortTree.delNode(12);
binarySortTree.delNode(7);
binarySortTree.delNode(1);
binarySortTree.delNode(2);
binarySortTree.delNode(3);
System.out.println("刪除后");
binarySortTree.midOrder();
}
}
class BinarySortTree {
private Node root;
//添加節點
public void addNode(Node node) {
if (root == null) {
root = node;
} else {
root.addNode(node);
}
}
//中序遍歷節點
public void midOrder() {
if (root == null) {
System.out.println("二叉排序樹為空");
} else {
root.midOrder();
}
}
//查找待刪除的節點
public Node searchNode(int val) {
if (this.root == null) {
return null;
} else {
return this.root.serachNode(val);
}
}
//查找待刪除的父節點
public Node searchParentNode(int val) {
if (this.root == null) {
return null;
} else {
return this.root.searchParentNode(val);
}
}
//在待查找二叉樹中找到最小的節點
public int searchRightMin(Node node){
while (node.left != null){
node = node.left;
}
delNode(node.val); //刪除最小的節點
return node.val; //返回最小的節點值
}
//刪除節點
public void delNode(int val) {
if (this.root == null) {
return;
} else {
//先拿到待刪除的節點
Node targetNode = searchNode(val);
if (targetNode == null) {
return;
}
//如果這棵二叉樹只有一個節點
if (this.root.left == null && this.root.right == null) {
if (root.val == val) {
root = null;
return;
}
}
//拿到待刪除節點的父節點
Node parent = searchParentNode(val);
//如果刪除的葉子節點
if (targetNode.left == null && targetNode.right == null) {
//判斷targetNode是parent的左節點還是右節點
if (parent.left != null && parent.left.val == val) {
parent.left = null;
} else if (parent.right != null && parent.right.val == val) {
parent.right = null;
}
} else if (targetNode.left != null && targetNode.right != null) { // 如果刪除的是帶有兩個葉子節點的節點
//從targetNode的右子樹中找到最小的節點
int temp = searchRightMin(targetNode.right);
targetNode.val = temp;
}else { //待刪除節點有一個分支
//如果待刪除的節點有左節點
if (targetNode.left !=null){
//待刪除的是根節點
if (parent == null){
this.root = targetNode.left;
}else {
//待刪除的節點是左節點
if (parent.left!=null && parent.left.val == val){
parent.left = targetNode.left;
}else if(parent.right!=null && parent.right.val == val){ // 待刪除的節點是右節點
parent.right = targetNode.left;
}
}
}else { //待刪除的節點有有分支
if (parent == null){
this.root = targetNode.right;
}else {
if (parent.left!=null && parent.left.val == val){
parent.left = targetNode.right;
}else if (parent.right!=null && parent.right.val == val){
parent.right = targetNode.right;
}
}
}
}
}
}
}
class Node {
int val;
Node left;
Node right;
public Node(int val) {
this.val = val;
}
@Override
public String toString() {
return "Node{" +
"val=" + val +
'}';
}
//查找待刪除節點的父節點
public Node searchParentNode(int val) {
if ((this.left != null && this.left.val == val) || (this.right != null && this.right.val == val)) {
return this;
} else {
if (this.val > val && this.left != null) {
return this.left.searchParentNode(val);
} else if (this.val <= val && this.right != null) {
return this.right.searchParentNode(val);
} else {
return null;
}
}
}
//查找到待刪除的節點
public Node serachNode(int val) {
if (this.val == val) {
return this;
} else if (this.val > val) {
if (this.left != null) {
return this.left.serachNode(val);
} else {
return null;
}
} else {
if (this.right != null) {
return this.right.serachNode(val);
} else {
return null;
}
}
}
//添加節點
public void addNode(Node node) {
if (this.val > node.val) {
//需要掛載到左邊
if (this.left == null) {
this.left = node;
} else {
this.left.addNode(node);
}
} else {
if (this.right == null) {
this.right = node;
} else {
this.right.addNode(node);
}
}
}
//中序遍歷
public void midOrder() {
if (this.left != null) {
this.left.midOrder();
}
System.out.println(this.val);
if (this.right != null) {
this.right.midOrder();
}
}
}