二叉搜尋樹的刪除操作(附例題)
阿新 • • 發佈:2018-12-23
。。。這一部分真心讓我懵逼,可能是我太笨的緣故吧。。。。
二叉搜尋樹的刪除操作。。。具體方法要分情況,
1. 若刪除的節點沒有孩子的時候,直接刪除此節點,然後將父節點NULL;
2.若刪除的節點有一個孩子的時候,直接將父節點連線到其孩子節點,然後刪除此節點。
3.若有兩個節點的時候,這時候就要找個節點代替它了,因為二叉搜尋樹具有左子樹比此節點的值都小,右子樹比此節點的值大,所以(1)可以找左子樹中節點最大的元素,也就是左子樹中最右端的元素,(2)也可以找右子樹中節點最小的元素,也就是右子樹中最左端的節點。讓此節點的值等於子樹中選出的值,然後刪除子樹中的節點,因為被刪除的節點不是在最右端就是在最左端,所以可知此節點只有一個孩子。。。。然後轉到第二種情況。。。
可以看出,這三種情況都需要記住父節點的地址。。。。
然後看浙大資料結構視訊這一節視訊給出的程式碼讓我好懵逼,好不容易才理解。。。
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; typedef struct tree { int data; struct tree *left,*right; }tree,*Tree; //建立二叉搜尋樹; Tree Create(Tree t,int data) { if(t) { if(t->data>=data) t->left=Create (t->left,data); else t->right=Create (t->right,data); } else { t=(Tree)malloc(sizeof(tree)); t->data=data; t->left=t->right=NULL; } return t; } //先序遍歷二叉搜尋樹; void Traverse (Tree t) { if(t) { printf("%d ",t->data); Traverse (t->left); Traverse (t->right); } } //找到子樹中最小的節點的地址; Tree FindMin(Tree t) { if(t) while (t->left) { if(t->left) t=t->left; } return t; } Tree Delete (Tree t,int data) { //要被刪除的節點 Tree temp=NULL; if(!t) printf("好像沒有此元素呢\n"); else if(t->data>data) t->left=Delete (t->left,data); else if(t->data<data) t->right=Delete (t->right,data); else { //有兩個子節點時 if(t->left&&t->right) { temp=FindMin(t->right); t->data=temp->data; //下面一定是t->data;因為要找到最小元素並刪除它... t->right=Delete (t->right,t->data); } else { //這裡挺讓人懵逼的,多想想就好了... temp=t; if(!t->left) t=t->right; else if(!t->right) t=t->left; free(temp); } } return t; } int main() { Tree t=NULL; int n,temp; scanf("%d",&n); for (int i=0;i<n;i++) { scanf("%d",&temp); t=Create(t,temp); } scanf("%d",&temp); t=Delete (t,temp); Traverse (t); return 0; }
例題為Leetcode的 Delete Node in a BST
給定一個二叉搜尋樹的根節點 root 和一個值 key,刪除二叉搜尋樹中的 key 對應的節點,並保證二叉搜尋樹的性質不變。返回二叉搜尋樹(有可能被更新)的根節點的引用。
一般來說,刪除節點可分為兩個步驟:
- 首先找到需要刪除的節點;
- 如果找到了,刪除它。
說明: 要求演算法時間複雜度為 O(h),h 為樹的高度。
示例:
root = [5,3,6,2,4,null,7] key = 3 5 / \ 3 6 / \ \ 2 4 7 給定需要刪除的節點值是 3,所以我們首先找到 3 這個節點,然後刪除它。 一個正確的答案是 [5,4,6,2,null,null,7], 如下圖所示。 5 / \ 4 6 / \ 2 7 另一個正確答案是 [5,2,6,null,4,null,7]。 5 / \ 2 6 \ \ 4 7
這裡用的是遞迴
Java程式碼:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
if(root==null)
return root;
if(root.val<key)
root.right=deleteNode (root.right,key);
else if(root.val>key)
root.left=deleteNode (root.left,key);
else
{
if(root.left==null||root.right==null)
{
if(root.left==null)
return root.right;
else
return root.left;
}
else
{
TreeNode t=root.left;
while (t.right!=null)
t=t.right;
root.val=t.val;
root.left=deleteNode (root.left,t.val);
}
}
return root;
}
}