二叉搜索树的删除(AldDS1_8_C:Binary Search Tree III)
程序员文章站
2022-06-03 13:57:50
...
从二叉搜索树T中删除包含给定键值K的结点z。删除z时需要跟据下述算法讨论三种情况,以确保在更新链接(指针)后仍保有二叉搜索树的性质。
1.z没有子节点时,删除其父节点p的子节点(也就是z)
2.z拥有一个子节点时,将z父节点的子节点变更为该子结点,同时将该子结点的父节点变更为z的父节点,然后将z从树中删除
3.z拥有两个子节点时,将z的后一个结点y的键值复制到z,然后删除y。“z的后一个结点”指的是中序遍历时排在z后面的第一个结点。
z没有子节点(case1)或有一个子结点(case2)时,y就是z。
相对的,当z拥有2个子节点(case3)时,y时z的后一个结点。这里“z的后一个结点”指的是中序遍历时排在z后面的第一个结点。
接下来找出y的子节点,更改y的子节点的父节点
然后更改y的父节点的子节点
最后针对case3有一种赋值的情况
node *treeminimum(node *x)
{
//一直找出最左边的点
while(x->left!=NIL){
x=x->left;
}
return x;
}
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);//有两个子节点
}
//找出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);
}
#include<iostream>
#include<cstdio>
#include<string>
#include<cstdlib>
using namespace std;
struct node{
int key;
node *right,*left,*parent;
};
node *root,*NIL;
void insert(int k)
{
node *y=NIL;
node *x=root;
node *z;
z=(node*)malloc(sizeof(node));
z->key=k;
z->left=NULL;
z->right=NULL;
while(x!=NULL){
y=x;
if(z->key<x->key){
x=x->left;
}else{
x=x->right;
}
}
z->parent=y;
if(y==NIL){
root=z;
}else{
if(z->key<y->key){
y->left=z;
}else{
y->right=z;
}
}
}
void inorder(node *u)
{
if(u==NULL){
return ;
}
inorder(u->left);
printf(" %d",u->key);
inorder(u->right);
}
void preorder(node *u)
{
if(u==NULL){
return ;
}
printf(" %d",u->key);
preorder(u->left);
preorder(u->right);
}
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 *treeminimum(node *x)
{
//一直找出最左边的点
while(x->left!=NIL){
x=x->left;
}
return x;
}
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);//有两个子节点
}
//找出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);
}
int main()
{
int n,k;
string com;
scanf("%d",&n);
for(int i=0;i<n;i++){
cin>>com;
if(com=="insert"){
scanf("%d",&k);
insert(k);
}else if(com=="print"){
inorder(root);
printf("\n");
preorder(root);
printf("\n");
}else if(com=="find"){
scanf("%d",&k);
node *t=find(root,k);
if(t!=NULL){
printf("yes\n");
}else{
printf("no\n");
}
}else{
scanf("%d",&k);
treedelete(find(root,k));
}
}
return 0;
}
/*
18
insert 8
insert 2
insert 3
insert 7
insert 22
insert 1
find 1
find 2
find 3
find 4
find 5
find 6
find 7
find 8
print
delete 3
delete 7
print
*/
推荐阅读
-
荐 Java刷题笔记15:不同的二叉搜索树( Unique Binary Search Trees)
-
【leetcode】-700. Search in a Binary Search Tree 查找二叉搜索树
-
LeetCode 235--二叉搜索树的最近公共祖先 ( Lowest Common Ancestor of a Binary Search Tree ) ( C语言版 )
-
LeetCode 235. Lowest Common Ancestor of a Binary Search Tree 二叉搜索树
-
leetcode 235. Lowest Common Ancestor of a Binary Search Tree(二叉树的最低共同祖先)
-
二叉搜索树 (binary search tree)
-
二叉搜索树(Binary Search Tree)
-
荐 Java刷题笔记15:不同的二叉搜索树( Unique Binary Search Trees)
-
二叉搜索树(Binary Search Tree)(Java实现)
-
convert-sorted-array-to-binary-search-tree 将有序数组转换为二叉搜索树