二叉搜尋樹如何刪除節點
二叉搜尋樹如何刪除節點
一、怎麼刪除二叉搜尋樹節點
一般要分三種情況,一種是要被刪除的節點沒有子節點,這時直接刪除就可以了,第二種情況時有一個子節點,這時,如果左邊有節點就將左邊的節點給要被刪除的節點的父節點,如果右邊有節點就將右邊的節點給要被刪除的節點的父節點。其實可以看出,這兩種情況可以合併成一種,因為第一種情況可以當成有兩個空節點,選誰都沒事,可以相容第二種情況。
最主要的是第三種情況,當被刪除的節點有兩個子節點時,其實有兩個答案,一種是選擇右子樹中最小的節點來代替被刪除的節點,因為是右邊子樹最小的節點,那它必定沒有左子樹,直接簡化成了只有一個節點的情況。另一個答案是選擇左子樹中最大的節點,同理。
以下程式碼是選的右子樹最小節點來作為答案的
二、二叉搜尋樹刪除程式碼
程式碼如下:
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
struct Node{
int key;
Node *right,*left,*parent;
};
Node *root,*NIL;
//尋找傳入節點右邊最小值節點
Node *treeMinimum(Node *x){
while(x->left!=NIL)x=x->left;
return x;
}
//尋找節點
Node *find(Node *u,int k){
while(u!=NIL&&k!=u->key){
if(k<u->key) u=u->left;
else u=u->right;
}
return u;
}
//返回節點右邊最小節點
Node *treeSuccessor(Node *x){
return treeMinimum(x->right);
}
void treeDelete(Node *z){
Node *y;//要刪除的節點
Node *x;//y的子節點
if(z->left==NIL||z->right==NIL){
y=z;//包括了需要刪除的節點沒有子節點和只有一個子節點的情況
}else{
y=treeSuccessor(z);
//子節點有兩個時的情況
}
//當需要刪除的節點沒有子節點,預設選右邊空節點
//當有一個子節點時,左邊有就存左邊進x,右邊有就存右邊進x
//當有兩個節點時得到的y肯定左邊是空的。
if(y->left!=NIL){
x=y->left;
}else{
x=y->right;
}
//當沒有子節點的情況時,因為空節點不用管父母節點所以跳過
//不為空時,x開始選新的父節點
if(x!=NIL){
x->parent=y->parent;
}
if(y->parent==NIL){
root=x;
//當需要被刪除的點為頭節點時
}else{
if(y==y->parent->left){
y->parent->left=x;
//刪掉的是左節點時
}else{
y->parent->right=x;
//右節點時
}
}
if(y!=z){
z->key=y->key;
//有兩個節點時的情況,將值付到該到的位置
}
free(y);
}
void insert(int k){
Node *y=NIL;
Node *x=root;
Node *z;
z=(Node *)malloc(sizeof(Node));
z->key=k;
z->left=NIL;
z->right=NIL;
while(x!=NIL){
y=x;
if(z->key>x->key){
x=x->right;
}else{
x=x->left;
}
}
z->parent=y;
if(y==NIL){
root=z;
}else{
if(z->key>y->key){
y->right=z;
}else{
y->left=z;
}
}
}
void inorder(Node *u){
if(u==NIL) return;
inorder(u->left);
printf(" %d",u->key);
inorder(u->right);
}
void preorder(Node *u){
if(u==NIL) return;
printf(" %d",u->key);
preorder(u->left);
preorder(u->right);
}
int main()
{
int n,i,x;
string com;
scanf("%d",&n);
for(i=0;i<n;i++){
cin>>com;
if(com[0]=='f'){
scanf("%d",&x);
Node *t=find(root,x);
if(t!=NIL) printf("yes\n");
else printf("no\n");
}else if(com=="insert"){
scanf("%d",&x);
insert(x);
}else if(com=="print"){
inorder(root);
printf("\n");
preorder(root);
printf("\n");
}else if(com=="delete"){
scanf("%d",&x);
treeDelete(find(root,x));
}
}
return 0;
}
相關文章
- 二分搜尋樹系列之[ 節點刪除 (remove) ]REM
- 二分搜尋樹系列之「 節點刪除 (remove) 」REM
- Java實現二叉搜尋樹的插入、刪除Java
- leetcode 450. delete-node-in-a-bst 刪除二叉搜尋樹中的節點 python3LeetCodedeletePython
- 783. 二叉搜尋樹節點最小距離
- 程式碼隨想錄演算法訓練營第22天 |二叉樹part07:235. 二叉搜尋樹的最近公共祖先、701.二叉搜尋樹中的插入操作、450.刪除二叉搜尋樹中的節點演算法二叉樹
- Java中在二叉搜尋樹中查詢節點的父節點Java
- 程式碼隨想錄演算法訓練營第19天|235. 二叉搜尋樹的最近公共祖先 ,701.二叉搜尋樹中的插入操作,450.刪除二叉搜尋樹中的節點演算法
- 程式碼隨想錄演算法訓練營day19| 235. 二叉搜尋樹的最近公共祖先 701.二叉搜尋樹中的插入操作 450.刪除二叉搜尋樹中的節點演算法
- 程式碼隨想錄演算法訓練營day22 | leetcode 235. 二叉搜尋樹的最近公共祖先、701. 二叉搜尋樹中的插入操作、450. 刪除二叉搜尋樹中的節點演算法LeetCode
- 實現二叉搜尋樹的新增,查詢和刪除(JAVA)Java
- 程式碼隨想錄演算法訓練營第二十二天 | 235.二叉搜尋樹的最近公共祖先 701.二叉搜尋樹中的插入操作 450.刪除二叉搜尋樹中的節點演算法
- 二叉搜尋樹
- 每日一練(26):二叉搜尋樹的第k大節點
- 22天【程式碼隨想錄演算法訓練營34期】第六章 二叉樹part08 (● 235. 二叉搜尋樹的最近公共祖先 ● 701.二叉搜尋樹中的插入操作 ● 450.刪除二叉搜尋樹中的節點)演算法二叉樹
- 劍指 Offer 54. 二叉搜尋樹的第k大節點 mark
- 二叉搜尋樹的第 k 個結點
- 從二分搜尋到二叉搜尋樹
- 力扣 - 劍指 Offer 54. 二叉搜尋樹的第k大節點力扣
- Day20 | 654.最大二叉樹 、 617.合併二叉樹 、 700.二叉搜尋樹中的搜尋 98.驗證二叉搜尋樹二叉樹
- 二叉搜尋樹的2層結點統計
- 如何在 Java 中實現二叉搜尋樹Java
- 每日一題 - 劍指 Offer 54. 二叉搜尋樹的第k大節點每日一題
- 程式碼隨想錄day18 || 530 二叉搜尋樹最小差,501 二叉搜尋樹眾數,236 二叉搜尋樹最近公共祖先
- 二叉搜尋樹的結構
- 有序表和搜尋二叉樹二叉樹
- javascript實現二叉搜尋樹JavaScript
- 二叉搜尋樹的操作集
- 二叉搜尋樹和二叉樹的最近公共祖先二叉樹
- js實現完全排序二叉樹、二叉搜尋樹JS排序二叉樹
- Leetcode 700. 二叉搜尋樹中的搜尋(DAY 2)LeetCode
- 資料結構中的樹(二叉樹、二叉搜尋樹、AVL樹)資料結構二叉樹
- JavaScript 二叉搜尋樹以及實現翻轉二叉樹JavaScript二叉樹
- 96. 不同的二叉搜尋樹
- 手寫AVL平衡二叉搜尋樹
- 資料結構-二叉搜尋樹資料結構
- 二叉搜尋樹的python實現Python
- 演算法篇 - 二叉搜尋樹演算法