6、二叉排序树的基本操作(**)
任务: 编写算法实现对依次输入的关键字序列建立二叉排序树,并能实现二叉排序树的查找、插入和删除运算。
一、算法设计
1.建立二叉树的过程实际上就是一个一个结点的插入过程,将读入的第一个结点看作是根结点,第二个来时,与第一个结点进行比较,小的话作为左孩子,大的话作为右孩子。以此类推,第三个,第四个都是如此。查找过程也与此类似,从根结点开始,与所给的关键字数值进行比较,比根结点的值大,跑向右孩子,比根结点的数值小,跑向左孩子。一直比较,直到数值匹配符合,说明查找成功。若是当前结点左右孩子都为空,则证明这个数值并没有存入二叉排序树当中。插入运算的话,对于给定的数值,需要先进行一遍查找遍历,若当前数值已经存在就直接退出功能。否则,记录下最后一个查找的结点,即为需要插入的位置(当前结点的左孩子或者是右孩子)。删除运算需要分情况讨论,若是叶子结点,直接删除没有什么好说的,其他的都不变。若当前结点有单个孩子,不管是右孩子还是左孩子,此结点被删除之后,直接由孩子来替代。如果此结点有两个孩子,这里有两种方法可以用来处理。假设被删结点有右孩子还有左孩子,那么被删除之后,可以在其左子树上遍历,找到左子树上最大的数值结点来代替该节点。或者是右子树寻找数值最小的结点来代替。数值最大、数值最小的结点必为叶子节点。这样,整个二叉树的基本运算就结束了。在此基础上,可以通过树的中序遍历对该树进行打印,打印出来的数值肯定也是按照由小到大的顺序排列的。
各个函数之间的调用关系如下图所示:
main() | |||
mainjiemian() | |||
InsertBST() PrintBST() | SearchBST() PrintBST() | DeleteBST() PrintBST() | jieshu() |
mainjiemian() |
2.本程序中包含7个模块
(1)主函数:int main();
(2)主菜单函数:void mainjiemian();
(3)退出函数:void jieshu();
(4)中序遍历二叉树并进行打印:void PrintBST(BiTree T);
(5)删除结点:int DeleteBST(BiTree T, datatype value);
(6)插入节点:BiTNode * InsertBST(BiTNode *T, int kx);
(7)查找结点:int SearchBST(BiTNode *T, datatype kx);
3.元素类型、结点类型和指针类型
typedefstruct BiTNode
{
datatype key = -1;/*关键字*/
struct BiTNode *lchild = NULL, *rchild =NULL;/*左、右子树*/
}BiTNode,*BiTree;/*二叉排序树的结点与指向根节点的指针*/
二、实验测试
源代码:
#pragma warning(disable:4996)
#include<stdio.h>
#include<cstdio>
#include<string>
#include<string.h>
#include<vector>
#include<algorithm>
#include<queue>
#include<stack>
#include<math.h>
#include<iomanip>
#include<stdlib.h>
#include<iostream>
#include<list>
using namespace std;
typedef int datatype;
typedef struct BiTNode
{
datatype key = -1; /*关键字*/
struct BiTNode *lchild = NULL, *rchild = NULL; /*左、右子树*/
}BiTNode, *BiTree; /*二叉排序树的结点与指向根节点的指针*/
int SearchBST(BiTNode *T, datatype kx)/*查找*/
{
BiTNode *p;
p = T;
if (p == NULL)
{
return 0;
}
if (p->key == kx)
return 1;
else if (p->key > kx)
return SearchBST(p->lchild, kx);
else
return SearchBST(p->rchild, kx);
}
BiTNode * InsertBST(BiTNode *T, int kx)/*插入*/
{
BiTNode *parent, *node, *child;
/*树为空,创建根结点*/
if (T == NULL)
{
T = (BiTNode *)malloc(sizeof(BiTNode));
T->key = kx;
T->lchild = NULL;
T->rchild = NULL;
return T;
}
parent = T;/*记录下根结点的位置*/
node = T;
while (node != NULL)
{
/*待插数据存在,就返回*/
if (node->key == kx)
{
cout << "数据已经存在" << endl;
return T;
}
else
{
parent = node;
if (node->key < kx)
node = node->rchild;
else
node = node->lchild;
}
}
child = (BiTNode*)malloc(sizeof(BiTNode));
child->key = kx;
child->lchild = NULL;
child->rchild = NULL;
if (kx > parent->key)
parent->rchild = child;
else
parent->lchild = child;
return T;
}
int DeleteBST(BiTree T, datatype value)/*删除*/
{
BiTNode *p, *pre = NULL, *mid;
p = T;
if (T == NULL)
return 0;
/*找到该节点*/
while ((p != NULL) && (p->key != value))
{
pre = p;
if (p->key < value)
{
p = p->rchild;
}
else
p = p->lchild;
}
if (p == NULL)
return 0;
/*至少有一个子节点为空*/
if ((p->lchild == NULL) || (p->rchild == NULL))
{
if (pre->lchild == p)
{
pre->lchild = ((p->lchild == NULL) ? p->rchild : p->lchild);
}
else
pre->rchild = ((p->lchild == NULL) ? p->rchild : p->lchild);
free(p); /*释放节点*/
}
else
{
/*删除的节点有2个子女*/
mid = p->rchild;
pre = p;
/*寻找右子树上的最小值的结点*/
while (mid->lchild != NULL)
{
pre = mid;
mid = mid->lchild;
}
/*直接赋值,避免交换节点*/
p->key = mid->key;
/*将mid节点的子节点作为pre的子节点,并将mid所指向的节点删除*/
if (pre->rchild == mid)
pre->rchild = mid->rchild;
else
pre->lchild = mid->rchild;
free(mid);
}
return 1;
}
void PrintBST(BiTree T)/*中序遍历输出*/
{
if (T == NULL)
return;
PrintBST(T->lchild);
printf("%d ", T->key);
PrintBST(T->rchild);
}
void mainjiemian()
{
cout << " ★-----★---------★---------★-----★" << endl;
cout << endl;
cout << " ☆ 1 生成二叉排序树 ☆" << endl;
cout << " 2 查找数据 " << endl;
cout << " ☆ 3 删除数据 ☆" << endl;
cout << " 4 退出 " << endl;
cout << " ★-----★---------★---------★-----★" << endl;
cout << endl;
cout << endl;
cout << "请选择数字命令:";
}
void jieshu()//结束显示
{
cout << " ★-----★---------★---------★-----★" << endl;
cout << endl;
cout << " ☆ 感谢您的使用! ☆" << endl;
cout << endl;
cout << " ★-----★---------★---------★-----★" << endl;
cout << endl;
}
int main()
{
system("color 57");
char*end;/*末端指针*/
string order;
mainjiemian();
int t;
BiTNode *T = NULL;
while (cin >> order)
{
int a_order = static_cast<int>(strtol(order.c_str(), &end, 10));/*将输入进来的值转化为int类型*/
switch (a_order + 48)
{
case'1':
{
system("cls");
printf("请输入要排序的数据:(以输入-1作为结束标志)\n");
while (scanf("%d", &t) != EOF)
{
if (t != -1)
{
T = InsertBST(T, t);
}
else
break;
}
PrintBST(T);
cout << endl;
system("pause");
system("cls");
mainjiemian();
break;
}
case'2':
{
system("cls");
printf("请输入需要查找的数据:\n");
cin >> t;
if (SearchBST(T, t))
{
cout << "查找成功!" << endl;
}
else
{
cout << "查找失败!" << endl;
}
PrintBST(T);
cout << endl;
system("pause");
system("cls");
mainjiemian();
break;
}
case'3':
{
system("cls");
printf("请输入要删除的数据:\n");
cin >> t;
if (DeleteBST(T, t))
{
cout << "删除成功!" << endl;
}
else
{
cout << "数据不存在,删除失败!" << endl;
}
PrintBST(T);
cout << endl;
system("pause");
system("cls");
mainjiemian();
break;
}
case'4':
{
system("cls");
jieshu();
return 0;
break;
}
default:
{
cin.clear();
cin.sync();
cout << "输入错误,重新返回主界面。" << endl;
system("pause");
system("cls");
mainjiemian();
break;
}
}
}
cout << endl;
//printf("\n%d %s\n", T->key, SearchBST(T, 10) ? "yes" : "no");
return 0;
}