实验12 动态查找 二叉排序树
代码
#include <iostream>
using namespace std;
#define ENDFLAG '#'
struct ElemType
{
char key;
// Other info
};
struct BSTNode
{
ElemType data; //结点数据域
BSTNode *lchild, *rchild; //左右孩子指针
};
using BSTree = BSTNode *;
// 二叉排序树的递归查找
BSTree SearchBST(BSTree T, char key)
{
//在根指针T所指二叉排序树中递归地查找某关键字等于key的数据元素
//若查找成功,则返回指向该数据元素结点的指针,否则返回空指针
if (!T || T->data.key == key)
return T; //查找结束
else if (key < T->data.key)
return SearchBST(T->lchild, key); //在左子树中继续查找
else
return SearchBST(T->rchild, key); //在右子树中继续查找
}
// 二叉排序树的插入
void InsertBST(BSTree &T, ElemType e)
{
//当二叉排序树T中不存在关键字等于e.key的数据元素时,则插入该元素
if (!T)
{ //找到插入位置,递归结束
BSTNode *node = new BSTNode; //生成新结点*S
node->data = e; //新结点*S的数据域置为e
node->lchild = node->rchild = nullptr; //新结点*S作为叶子结点
T = node; //把新结点*S链接到已找到的插入位置
}
else if (e.key < T->data.key)
InsertBST(T->lchild, e); //插入左子树
else if (e.key > T->data.key)
InsertBST(T->rchild, e); //插入右子树
}
// 二叉排序树的创建
void CreateBST(BSTree &T)
{
T = nullptr;
ElemType e;
cin >> e.key;
while (e.key != ENDFLAG) //ENDFLAG为自定义常量,作为输入结束标志
{
InsertBST(T, e); //将此结点插入二叉排序树T中
cin >> e.key;
}
}
// 从二叉排序树T中删除关键字等于key的结点
void DeleteBST(BSTree &T, char key)
{
BSTree target = T; // 要删除的结点
BSTree parent = nullptr; // 要删除结点的父节点
while (target) // 从根开始查找关键字等于key的结点
{
if (target->data.key == key)
break; // 找到了
parent = target; // 记录父节点
if (target->data.key > key)
target = target->lchild;
else
target = target->rchild;
}
if (!target)
return; // 找不到要删结点
// 被删结点左右子树均不空
if ((target->lchild) && (target->rchild))
{
// 找到待删除结点中序遍历的前驱结点, 即左子树中最右下的结点
BSTree pre = target->lchild; // 前驱结点
BSTree parent_of_pre = nullptr; // 前驱结点的父节点
while (pre->rchild)
{
parent_of_pre = pre;
pre = pre->rchild;
}
target->data = pre->data; // 偷天换日, 把前驱结点的值扔到待删除的结点里面
parent_of_pre->rchild = pre->lchild; // 如果前驱结点有左子树(不可能有右子树), 把它换到前驱结点的位置(右边)
delete pre; // 把前驱删掉即可
return;
}
// 其它两种情况
BSTree to_replace = nullptr;
if (!target->lchild) // 如果要被删除的结点没有左子树, 用其右子树代替它的位置
to_replace = target->rchild;
else if (!target->rchild) // 如果没有右子树, 用左子树代替它的位置
to_replace = target->lchild;
if (!parent) // 没有父节点就取代根结点位置
T = to_replace;
else if (target == parent->lchild) // 如果要被删除的结点是左边的
parent->lchild = to_replace; // 取代左边的位置
else if (target == parent->rchild) // 如果被删除结点是右边的
parent->rchild = to_replace; // 取代右边的位置
delete target; // 删掉目标结点
}
// 中序遍历
void InOrderTraverse(BSTree &T)
{
if (T)
{
InOrderTraverse(T->lchild);
cout << T->data.key << '\t';
InOrderTraverse(T->rchild);
}
}
int main()
{
BSTree T;
cout << "请输入若干字符(#表示输入结束): ";
CreateBST(T);
cout << "中序遍历结果为" << endl;
InOrderTraverse(T);
cout << endl;
char key; //待查找或待删除内容
cout << "请输入待查找字符: ";
cin >> key;
if (SearchBST(T, key))
cout << "找到字符" << key << endl;
else
cout << "未找到" << key << endl;
cout << "请输入待删除的字符: ";
cin >> key;
DeleteBST(T, key);
cout << "中序遍历结果为" << endl;
InOrderTraverse(T);
cout << endl;
}
截图