实验题目: 二叉排序树。任意给定一组数据,设计一个算法,建立一棵二叉排序树,对它进行查找、插入、删除等操作。
实验说明:二叉排序树存储结构如下:
typedef struct BiTNode { // 结点结构
struct BiTNode *lchild, *rchild; // 左右孩子指针
} BiTNode, *BiTree;
二叉排序树插入算法伪代码如下:
1. 若root是空树,则将结点s作为根结点插入;否则
2. 若s->data<root->data,则把结点s插入到root的左子树中;否则
3. 把结点s插入到root的右子树中。
二叉排序树中删除一个结点f的左孩子结点p算法伪代码如下:
1. 若结点p是叶子,则直接删除结点p;
2. 若结点p只有左子树,则只需重接p的左子树;
若结点p只有右子树,则只需重接p的右子树;
3. 若结点p的左右子树均不空,则
3.1 查找结点p的右子树上的最左下结点s以及结点s的双亲结点par;
3.2 将结点s数据域替换到被删结点p的数据域;
3.3 若结点p的右孩子无左子树,则将s的右子树接到par的右子树上;
否则,将s的右子树接到结点par的左子树上;
3.4 删除结点s;
对于二叉树这样的一个特殊的树类结构,每个结点都可以看作根结点,因此我们可以采用递归的思想设计算法,首先我们需要建立一棵二叉排序树,二叉排序树的特点是,根结点的左子树均小于根结点,根结点的右子树均大于根结点,因此我们可以每次只对二叉树作插入操作,共循环n次(n是所给定的关键字的数量),每次插入如果待插入的结点小于根结点,就递归处理左子树,反之处理右子树,如果与根结点相等,则返回false(二叉排序树中不存在关键字一样的结点)。二叉排序树构造完毕后,对其实行插入操作,我们也同样使用递归来实现,当找到时,返回true。对于删除操作,根据不同的情况,我们可以采取不同的删除办法,上面的伪代码已经给出了大致思想,用代码实现即可。
下面给出两种代码,一种c语言写法,一种c++写法
c语言写法:
//二叉排序树。任意给定一组数据,设计一个算法,建立一棵二叉排序树,对它进行查找、插入、删除等操作。
#include<stdio.h>
#include<stdlib.h>
typedef struct node//元素类型
{
int key;//关键字
struct node *lchild;//左右孩子指针
struct node *rchild;
}BSTNode;
///*
bool InsertBST(BSTNode *&bt,int k)
{//在二叉排序树中插入一个关键字为k的结点,若插入成功返回真,否则返回假
if(bt==NULL)//若原树为空,新插入的结点为根节点
{
bt=(BSTNode*)malloc(sizeof(BSTNode));
bt->key=k;
bt->lchild=bt->rchild=NULL;
return true;
}
else if(k==bt->key)//数中存在相同关键字则无需插入,返回假
{
return false;
}
else if(k<bt->key)//若关键字小于根节点
{
return InsertBST(bt->lchild,k);//插入到左子树中
}
else//否则
return InsertBST(bt->rchild,k);//插入到右子树中
}
//*/
///*
BSTNode* CreateBST(int a[],int n)//创建二叉排序树算法,数组参数传递关键字序列,n传递关键字数量
//返回结点指针,这里要注意调用形式
{
BSTNode* bt=NULL;//初始时bt树为空,这里bt作为临时结点,调用插入函数插入到原先的节点上
int i=0;
while(i<n)
{
InsertBST(bt,a[i]);
i++;
}
return bt;//返回建立的二叉树
}
//*/
///*
BSTNode *SearchBST(BSTNode*bt,int k)//二叉排序树的查找,这里也要注意返回一个结点指针
//第一个参数是二叉排序树,第二个参数是要查找的关键字
{
if(bt==NULL||bt->key==k)//递归结束条件
{
return bt;
}
if(k<bt->key)
{
return SearchBST(bt->lchild,k);//在左子树中递归查找
}
else
return SearchBST(bt->rchild,k);//在右子树中递归查找
}
//*/
///*
void Deletel(BSTNode* p,BSTNode*&r)//结点p既有左子树也有右子树
//r指向左孩子
{
BSTNode *q;//临时结点q
if(r->rchild!=NULL)//递归找出结点r的最右下结点
{
Deletel(p,r->rchild);//
}
else //找到了最右下结点
{
p->key=r->key;//将r的值(左孩子值)存放到结点p(根节点)中
q=r; //原教材上下面两行代码为:
r->key=r->lchild->key;//r=r->lchild;
q->lchild=q->rchild=NULL;//free(q);但若按照这个代码,结点不会被消除,只是生成随机数,到时不好输出
}
}
void Delete(BSTNode *&p)//从二叉排序树删除结点p
{
BSTNode *q;
if(p->rchild==NULL)//若结点没有右子树
{
q=p;
//下面两行教材上的代码:
p->key=p->lchild->key; // p=p->rchild;//用结点p的左孩子代替
q->lchild=q->rchild=NULL;//free(q);但若按照这个代码,结点不会被消除,只是生成随机数,到时不好输出
//q被p取代,其孩子为空,相当于释放q,下面同理
}
else if(p->lchild==NULL)//结点p没有左孩子
{
q=p;
//下面两行教材上的代码:
p->key=p->rchild->key; //p=p->rchild;
q->rchild=q->lchild=NULL ; // free(q);但若按照这个代码,结点不会被消除,只是生成随机数,到时不好输出
}
else Deletel(p,p->lchild);
}
void DipBT(BSTNode *b)//输出二叉树
{
if(b!=NULL)
{
printf("%d",b->key);
if(b->lchild!=NULL || b->rchild!=NULL)
{
printf("(");
DipBT(b->lchild);
if(b->rchild!=NULL) printf(",");
DipBT(b->rchild);
printf(")");
}
}
}
int main()
{
BSTNode *p,*tp;
int a[9]={5,2,1,6,7,4,8,3,9};
p=CreateBST(a,9);
printf("创建二叉排序树:\n");
DipBT(p);
printf("\n\n\n");
printf("插入关键字为10的结点:\n");
InsertBST(p,10);
DipBT(p);
printf("\n\n\n");
printf("查找关键字为4的结点:\n");
tp=SearchBST(p,4);
printf("结点为%d\n\n\n",tp->key);
printf("删除关键字是4的结点:\n");
Delete(tp);
DipBT(p);
}
c++实现,本例与c语言思路是一样的,只是把结构体换成了类,不给出注释了
#include<iostream>
using namespace std;
class BSTNode {
public:
int key;
BSTNode* lchild, * rchild;
};
bool InsertNode(BSTNode*& b, int k) {
if (b == NULL) {
b = new BSTNode;
b->key = k;
b->lchild = NULL;b->rchild = NULL;
return true;
}
else if (k == b->key)return false;
else if (k < b->key)
return InsertNode(b->lchild, k);
else if (k > b->key)
return InsertNode(b->rchild, k);
}
void Display(BSTNode* b) {
if (b != NULL) {
cout << b->key;
if (b->lchild != NULL || b->rchild != NULL) {
cout << "(";
Display(b->lchild);
if (b->rchild != NULL)cout << ",";
Display(b->rchild);
cout << ")";
}
}
}
void Delete1(BSTNode* b, BSTNode*& r) {
BSTNode* p;
if (r->rchild != NULL)
Delete1(b, r->rchild);
else {
b->key = r->key;
p = r;
r = r->lchild;
delete p;
}
}
void Delete(BSTNode*& b) {
BSTNode* p;
if (b->lchild == NULL && b->rchild == NULL) {
b = NULL;
delete b;
}
else if (b->lchild != NULL && b->rchild == NULL) {
p = b;
b = b->lchild;
delete p;
}
else if (b->lchild == NULL && b->rchild != NULL) {
p = b;
b = b->rchild;
delete p;
}
else
Delete1(b, b->lchild);
}
bool Seek(BSTNode*& b, int k) {
if (b == NULL)
return false;
else {
if (k < b->key)
return Seek(b->lchild, k);
else if (k > b->key)
return Seek(b->rchild, k);
else {
Delete(b);
return true;
}
}
}//查找算法
void CreatBST(BSTNode*& b, int a[9]) {
int i;
b = NULL;
for (i = 0; i < 9; i++)
InsertNode(b, a[i]);
}
void Destroy(BSTNode*& b) {
if (b != NULL) {
Destroy(b->lchild);
Destroy(b->rchild);
delete b;
}
}
int main() {
BSTNode* b;
int k;
int a[9] = { 5,2,6,1,4,7,3,8,9 };
CreatBST(b, a);
Display(b);
cout << endl;
cout << "请输入要删除的结点:";
cin >> k;
Seek(b, k);
Display(b);
cout << endl;
cout << "———————————————" << endl;
Destroy(b);
}
0 条评论