题目描述
给出一个数据序列,建立二叉排序树,并实现删除功能
对二叉排序树进行中序遍历,可以得到有序的数据序列
输入
第一行输入t,表示有t个数据序列
第二行输入n,表示首个序列包含n个数据
第三行输入n个数据,都是自然数且互不相同,数据之间用空格隔开
第四行输入m,表示要删除m个数据
从第五行起,输入m行,每行一个要删除的数据,都是自然数
以此类推输入下一个示例
输出
第一行输出有序的数据序列,对二叉排序树进行中序遍历可以得到
从第二行起,输出删除第m个数据后的有序序列,输出m行
以此类推输出下一个示例的结果
输入样例1
1
6
22 33 55 66 11 44
3
66
22
77
输出样例1
11 22 33 44 55 66
11 22 33 44 55
11 33 44 55
11 33 44 55
NOTICE:
二叉排序树的删除:需要配合插入和查找操作完成,相比于原来的插入,我们需要为BiTreeNode增加私有属性parent,也就是结点的双亲,方便删除时修改指针;查找操作我们需要返回找到的结点的指针;删除操作有以下需要注意的点:
1、删除操作主要分三种情况:叶子结点、没有左孩子或没有右孩子、左右孩子都有;先用查找函数找到我们删除的结点;
2、叶子结点:其双亲中指向该结点的指针置为nullptr,然后再delete该结点;
3、没有左孩子:其双亲中指向该结点的指针更改为指向该结点的右孩子,然后再delete该结点;没有右孩子的同理;
4、左右孩子都有:首先找到该结点在中序序列中的直接前驱,但实际上不用去把树给中序遍历一遍,只需要取该节点的左孩子,然后再不断地取右孩子直到尽头,就找到了直接前驱;然后用直接前驱代替该节点(更改数据即可);最后删除前驱结点,前驱结点只可能有左孩子,因此只分两种情况,要么没孩子,要么只有左孩子,这两种情况按上面方法去删除;千万不要delete该结点,它只是被替换了,没有被删除;
代码有点长.....
#include <iostream>
using namespace std;
class BiTreeNode
{
private:
int data;
BiTreeNode* lchild;
BiTreeNode* rchild;
BiTreeNode* parent;
public:
BiTreeNode(int a, BiTreeNode* par)
{
data = a;
lchild = nullptr;
rchild = nullptr;
parent = par;
}
friend class BiTree;
};
class BiTree
{
private:
BiTreeNode* root;
void inorder(BiTreeNode* t)
{
if (t)
{
inorder(t->lchild);
cout << t->data << " ";
inorder(t->rchild);
}
}
public:
BiTree() :root(nullptr) {}
void insert(int num)
{
if (root == nullptr)
{
BiTreeNode* t = new BiTreeNode(num, nullptr);
root = t;
}
else
{
BiTreeNode* p = root;
BiTreeNode* q = nullptr;//指向p节点的双亲
while (1)
{
if (p == nullptr)
{
if (num < q->data)
{
BiTreeNode* t = new BiTreeNode(num, q);
q->lchild = t;
}
else if (num > q->data)
{
BiTreeNode* t = new BiTreeNode(num, q);
q->rchild = t;
}
break;
}
if (num < p->data)
{
q = p;
p = p->lchild;
}
else if (num > p->data)
{
q = p;
p = p->rchild;
}
}
}
}
BiTreeNode* search(int num)
{
BiTreeNode* p = root;
while (1)
{
if (p == nullptr)//没找到
{
return p;
}
if (p->data == num)//找到
{
return p;
}
if (num < p->data)
{
p = p->lchild;
}
else if (num > p->data)
{
p = p->rchild;
}
}
}
void Delete(int num)
{
BiTreeNode* t = search(num);
if (t == nullptr)
{
//无操作
}
else if (t->lchild == nullptr && t->rchild == nullptr)
{
if (t->parent->lchild == t)
t->parent->lchild = nullptr;
else
t->parent->rchild = nullptr;
delete t;
}
else if (t->lchild == nullptr)
{
if (t->parent->lchild == t)
{
t->parent->lchild = t->rchild;
delete t;
}
else
{
t->parent->rchild = t->rchild;
delete t;
}
}
else if (t->rchild == nullptr)
{
if (t->parent->lchild == t)
{
t->parent->lchild = t->lchild;
delete t;
}
else
{
t->parent->rchild = t->lchild;
delete t;
}
}
else
{
//找到直接前驱(转左,然后向右到尽头)
BiTreeNode* p = t->lchild;
while (p->rchild)
{
p = p->rchild;
}
//替换
t->data = p->data;
//删除直接前驱(只可能有左孩子)
if (p->lchild)//有左孩子
{
if (p->parent->lchild == p)
{
p->parent->lchild = p->lchild;
delete p;
}
else
{
p->parent->rchild == p;
delete p;
}
}
else//左右孩子都没有
{
if (p->parent->lchild == p)
{
p->parent->lchild = nullptr;
delete p;
}
else
{
p->parent->rchild = nullptr;
delete p;
}
}
}
}
void inorder()
{
inorder(root);
cout << endl;
}
};
int main()
{
int t;
cin >> t;
while (t--)
{
int n, m;
BiTree tree;
//创建二叉树(本质是多次插入)
cin >> n;
for (int i = 0; i < n; i++)
{
int num;
cin >> num;
tree.insert(num);
}
tree.inorder();
//删除
cin >> m;
for (int i = 0; i < m; i++)
{
int num;
cin >> num;
tree.Delete(num);
tree.inorder();
}
}
return 0;
}
1万+

被折叠的 条评论
为什么被折叠?



