Java-二叉排序樹的刪除

寧啊寧啊寧啊發表於2020-10-25

考慮情況

二叉排序樹的刪除情況比較複雜,有下面三種情況要考慮
1.刪除葉子節點
2.刪除只有一顆子樹的節點
3.刪除有兩顆子樹的節點

思路分析

第一種情況:刪除葉子節點

思路:
1.需求先去找到要刪除的節點targetNode
2.找到targetNode的父節點parent
3.確定targetNode是parent的左子節點還是右子節點
4.根據情況對應刪除

第二種情況:刪除只有一顆子樹的節點

思路:
1.需求先去找到要刪除的節點targetNode
2.找到targetNode的父節點parent
3.確定targetNode的子節點是左子節點還是右子節點
4.確定targetNode是parent的左子節點還是右子節點
5.如果targetNode有左子節點
5.1如果targetNode是parent的左子節點,parent.left=targetNode.left。
5.2如果targetNode是parent的右子節點,parent.right=targetNode.left。
6.如果targeyNode有右子節點
6.1如果targetNode是parent的左子節點,parent.left=targetNode.right.
6.2如果targetNode是parent的右子節點,parent.right=targetNode.right

第三種情況:刪除有兩顆子樹的節點

思路:
1.需求先去找到要刪除的節點targetNode
2.找到targetNode的父節點parent
3.從targetNode的右子樹找到最小的節點
4.用一個臨時變數,將最小節點的值儲存
5.刪除該最小節點
6.targetNode.value=temp

程式碼實現

//查詢要刪除的節點
	public Nodes search(int value) {
		if(value==this.value) {
			return this;
		}else if(value<this.value) {//如果查詢值小於當前節點,則向左子樹遞迴查詢
			//如果左子節點為空
			if(this.left==null) {
				return null;
			}
			return this.left.search(value);
		}else {
			if(this.right==null) {
				return null;
			}
			return this.right.search(value);
		}
		
	}
	//查詢要刪除節點的父節點
	public Nodes searchParent(int value) {
		//如果當前節點就是要刪除節點的父節點,就返回
		if((this.left!=null&&this.left.value==value)||(this.right!=null&&this.right.value==value)) {
			return this;
		}else {
			//如果查詢的值小於當前節點的值,並且當前節點的左子節點不為空
			if(value<this.value&&this.left!=null) {
				return this.left.searchParent(value);
			}else if(value>=this.value&&this.right!=null){
				return this.right.searchParent(value);
			}else {
				return null;//沒有找到父節點
			}
		}
		
	}
	public Nodes search(int value) {
		if(root==null) {
			return null;
		}else {
			return root.search(value);
		}
	}
	
	//查詢父節點
	public Nodes searchParent(int value) {
		if(root==null) {
			return null;
		}else {
			return root.searchParent(value);
		}
	}
	//刪除節點
	public void delNode(int value) {
		if(root==null) {
			return;
		}else {
			//先找到要刪除的節點
			Nodes targetNode=search(value);
			//如果沒有找到要刪除的節點
			if(targetNode==null) {
				return;
			}
			//如果我們發現當前的二叉樹只有一個節點
			if(root.left==null&&root.right==null) {
				root=null;
				return;
			}
			//去找到targetNode的父節點
			Nodes parent=searchParent(value);
			//如果要刪除的是葉子節點
			if(targetNode.left==null&&targetNode.right==null) {
				//判斷targetNode是父節點的左子節點還是右子節點
				if(parent.left!=null&&parent.left.value==value) {
					parent.left=null;
				}else if(parent.right==null&&parent.right.value==value) {
					parent.right=null;
				}
			}else if(targetNode.left!=null&&targetNode.right!=null) {//刪除有兩顆子樹的節點
				int minValue=delRightTreeMin(targetNode.right);
				targetNode.value=minValue;
			}else {//刪除只有一顆子樹的節點
				//如果要刪除的節點有左子節點
				if(targetNode.left!=null) {
					//如果targetNode是parent的左子節點
					if(parent.left.value==value) {
						parent.left=targetNode.left;
					}else {
						parent.right=targetNode.left;
					}
				}else {//要刪除的節點有右子節點
					if(parent.left.value==value) {
						parent.left=targetNode.right;
					}else {
						parent.right=targetNode.right;
					}
				}
			}
		}
	}
	//查詢最小節點
	public int delRightTreeMin(Nodes node) {
		Nodes target=node;
		while(target.left!=null) {
			target=target.left;
		}
		delNode(target.value);
		return target.value;
	}

相關文章