我参考了“z-k”博主 点击->原文链接
和“半途行走”博主 点击->原文链接
发现都没有考虑到
排序二叉树 11 22 33 44 55 66 删除11根结点时只有一边结点的情况
改进了代码
删除结点一共有三种情况
1.删除结点是叶子结点,没有子树;
2.删除结点只有左子树或右子树;
3删除结点既有左子树也有右子树
第一种情况很简单
直接删除即可 让父结点指向NULL
if(!find->left && !find->right){ //该结点为叶子结点,直接删除
father->left == find ? father->left = NULL : father->right = NULL;
delete find;
}
第二种情况
让父亲结点指向余下结点即可
需要考虑特殊情况删除点是根结点且只有一边子树
if(!find->left){ //该结点只有右子树
if(!father){
node = node->right;
}else{
father->left == find ? father->left = find->right : father->right = find->right;
delete find;
}
}else if(!find->right){ //该结点只有左子树
if(!father){
node = node->left;
}else{
father->left == find ? father->left = find->left : father->right = find->left;
delete find;
}
第三种情况
不真正删除结点, 把要删除结点左子树的最大值替换到该节点, 然后把该结点清空
else{
father = find;
Node *max_left = find->left;
while(max_left->right != NULL){
father = max_left;
max_left = max_left->right;
}
find->data = max_left->data;
father->left = max_left->right;
delete max_left;
max_left = NULL;
}
题目描述
给出一个数据序列,建立二叉排序树,并实现删除功能
对二叉排序树进行中序遍历,可以得到有序的数据序列
输入
第一行输入t,表示有t个数据序列
第二行输入n,表示首个序列包含n个数据
第三行输入n个数据,都是自然数且互不相同,数据之间用空格隔开
第四行输入m,表示要删除m个数据
从第五行起,输入m行,每行一个要删除的数据,都是自然数
以此类推输入下一个示例
输出
第一行输出有序的数据序列,对二叉排序树进行中序遍历可以得到
从第二行起,输出删除第m个数据后的有序序列,输出m行
以此类推输出下一个示例的结果
样例输入
1
6
22 33 55 66 11 44
3
66
22
77
样例输出
11 22 33 44 55 66
11 22 33 44 55
11 33 44 55
11 33 44 55
#include <iostream>
using namespace std;
class Node {
public:
int data;
Node *left,*right;
Node() {
left = right =NULL;
}
Node(int _data){
data = _data;
left = right =NULL;
}
~Node(){
}
};
class Tree {
public:
Node *root;
Tree() {
root = NULL;
}
};
void insert(Node *&node,int data){
if(node == NULL){
node = new Node(data);
return ;
}
if(node->data < data){
insert(node->right,data);
}else{
insert(node->left,data);
}
}
void delete_node(Node *&node, int data){
if(!node->left && !node->right && node->data == data){ //头结点为删除点,且无子树
delete node;
node = NULL;
return ;
}
Node *father = NULL;
Node *find = node;
while(find){
if(find->data == data){
break ;
} else if(find->data < data){
father = find;
find = find->right;
}else {
father = find;
find = find->left;
}
}
if(find){ //说明找到了目标结点
if(!find->left && !find->right){ //该结点为叶子结点,直接删除
father->left == find ? father->left = NULL : father->right = NULL;
delete find;
} else if(!find->left){ //该结点只有右子树
father->left == find ? father->left = find->right : father->right = find->right;
delete find;
}else if(!find->right){ //该结点只有左子树
father->left == find ? father->left = find->left : father->right = find->left;
delete find;
}else{ //该结点同时有左右子树
father = find;
Node *max_left = find->left;
while(max_left->right != NULL){
father = max_left;
max_left = max_left->right;
}
find->data = max_left->data;
father->left = max_left->right;
delete max_left;
max_left = NULL;
}
}
return ;
}
void output(Node *node){
if(node == NULL) return ;
output(node->left);
cout<<node->data<<" ";
output(node->right);
return ;
}
int main() {
int t;
cin>>t;
Tree tree;
while(t--) {
int n;
cin>>n;
while(n--) {
int data;
cin>>data;
insert(tree.root,data);
}
output(tree.root);
cout<<endl;
int m;
cin>>m;
while(m--) {
int data;
cin>>data;
delete_node(tree.root,data);
output(tree.root);
cout<<endl;
}
}
return 0;
}