实验内容:
一、编写一程序bst.cpp,包含二叉排序树的创建、查找和删除算法,在此基础上编写程序exp9-4.cpp,完成以下功能:
(1) 由关键字序列(16,74,60,45,43,67,31,29,88,77)创建一棵二叉排序树Bt;
(2) 将上述创建的二叉排序树执行树的中序遍历,并输出结果;
(3) 采用递归和非递归两种方法查找关键字为67的结点,并输出其查找路径(即所经过的点的序列);
(4) 删除Bt中关键字为43和77的结点,并输出删除后的二叉排序树,即中序遍历输 出结果;
二、二叉排序树的创建:
从空的二叉排序树开始的,每输入一个结点,经过查找操作将新结点插入到当前二叉排序树的合适位置。
使用CreatBST()方法创建新二叉排序树。
三、二叉排序树的插入:
二叉排序树的插入操作是以查找为基础的。要将一个关键字值为key的结点*S插入到二叉排序树中,则需要从根结点向下查找,当树中不存在关键字等于key的结点时才进行插入。新插入的结点一定是一个新添加的叶子结点,并且是查找不成功时查找路径上访问的最后一个结点的左孩子或右孩子结点。
使用InsertBST()方法插入新结点。
四、二叉排序树的查找:
因为二叉排序树可以看成是一个有序表,所以在二叉排序树上进行查找和折半查找类似。也是一个逐步缩小查找范围的过程。
使用SearchBST1()方法进行递归查找,使用SearchBST2()方法进行非递归查找。
五、二叉排序树的删除:
被删除的结点可能是二叉排序树中的任何结点,删除结点后要根据其位置不同修改其双亲结点及相关结点的指针,以保持二叉排序树的特性。
使用DeleteBST()方法进行结点删除。
程序代码exp
#include <stdio.h>
#include <malloc.h>
#define MaxSize 100
typedef int KeyType; //定义关键字类型
typedef char InfoType;
typedef struct node //记录类型
{
KeyType key; //关键字项
InfoType data; //其他数据域
struct node *lchild,*rchild; //左右孩子指针
}BSTNode;
int path[MaxSize]; //全局变量,用于存放路径
void InOrderTraverse(BSTNode *b); //函数说明
int InsertBST(BSTNode *&p,KeyType k) //在以*p为根节点的BST中插入一个关键字为k的节点
{
if (p==NULL) //原树为空, 新插入的记录为根节点
{
p=(BSTNode *)malloc(sizeof(BSTNode));
p->key=k;p->lchild=p->rchild=NULL;
return 1;
}
else if (k==p->key)
return 0;
else if (k<p->key)
return InsertBST(p->lchild,k); //插入到*p的左子树中
else
return InsertBST(p->rchild,k); //插入到*p的右子树中
}
BSTNode *CreatBST(KeyType A[],int n)
//由数组A中的关键字建立一棵二叉排序树
{
BSTNode *bt=NULL; //初始时bt为空树
int i=0;
while (i<n)
{
if (InsertBST(bt,A[i])==1) //将A[i]插入二叉排序树T中
{
printf(" 第%d步,插入%d:",i+1,A[i]);
InOrderTraverse(bt);printf("\n");
i++;
}
}
return bt; //返回建立的二叉排序树的根指针
}
void Delete1(BSTNode *p,BSTNode *&r)
//当被删*p节点有左右子树时的删除过程
{
BSTNode *q;
if (r->rchild!=NULL)
Delete1(p,r->rchild); //递归找最右下节点
else //找到了最右下节点*r
{
p->key=r->key; //将*r的关键字值赋给*p
q=r;
r=r->lchild; //将*r的双亲节点的右孩子节点改为*r的左孩子节点
free(q); //释放原*r的空间
}
}
void Delete(BSTNode *&p)
//从二叉排序树中删除*p节点
{
BSTNode *q;
if (p->rchild==NULL) //*p节点没有右子树的情况
{
q=p;p=p->lchild;free(q);
}
else if (p->lchild==NULL) //*p节点没有左子树的情况
{
q=p;p=p->rchild;free(q);
}
else
Delete1(p,p->lchild); //*p节点既有左子树又有右子树的情况
}
int DeleteBST(BSTNode *&bt,KeyType k)
//在bt中删除关键字为k的节点
{
if (bt==NULL) return 0; //空树删除失败
else
{
if (k<bt->key)
return DeleteBST(bt->lchild,k); //递归在左子树中删除关键字为k的节点
else if (k>bt->key)
return DeleteBST(bt->rchild,k); //递归在右子树中删除关键字为k的节点
else //k=bt->key的情况
{
Delete(bt); //调用Delete(bt)函数删除*bt节点
return 1;
}
}
}
void SearchBST1(BSTNode *bt,KeyType k,KeyType path[],int i)
//以递归方式输出从根节点到查找到的节点的路径
{
int j;
if (bt==NULL)
return;
else if (k==bt->key) //找到了节点
{
path[i+1]=bt->key; //输出其路径
for (j=0;j<=i+1;j++)
printf("%3d",path[j]);
printf("\n");
}
else
{
path[i+1]=bt->key;
if (k<bt->key)
SearchBST1(bt->lchild,k,path,i+1); //在左子树中递归查找
else
SearchBST1(bt->rchild,k,path,i+1); //在右子树中递归查找
}
}
int SearchBST2(BSTNode *bt,KeyType k)
//以非递归方式输出从根节点到查找到的节点的路径
{
if (bt==NULL)
return 0;
else if (k==bt->key)
{
printf("%3d",bt->key);
return 1;
}
else if (k<bt->key)
SearchBST2(bt->lchild,k); //在左子树中递归查找
else
SearchBST2(bt->rchild,k); //在右子树中递归查找
printf("%3d",bt->key);
}
void InOrderTraverse(BSTNode *bt)
//输出二叉排序树bt
{
if (bt!=NULL)
{
InOrderTraverse(bt->lchild);
printf("%d",bt->key);
printf(",");
InOrderTraverse(bt->rchild);
}
}
KeyType predt=-32767; //predt为全局变量,保存当前节点中序前趋的值,初值为-∞
int main()
{
BSTNode *bt;
KeyType k=67;
int a[]={16,74,60,45,43,67,31,29,88,77},n=10;
printf("(1)创建一棵BST树:");
printf("\n");
bt=CreatBST(a,n);
printf("\n(2)中序遍历表示BST:");InOrderTraverse(bt);printf("\n");
printf("\n(3)a.查找%d关键字(递归,顺序):",k);SearchBST1(bt,k,path,-1);
printf(" b.查找%d关键字(非递归,逆序):",k);SearchBST2(bt,k);printf("\n");
printf("\n(4)删除并输出操作:\n");
printf(" 原BST:");InOrderTraverse(bt);printf("\n");
printf(" 删除节点43:");
DeleteBST(bt,43);
InOrderTraverse(bt);printf("\n");
printf(" 删除节点77:");
DeleteBST(bt,77);
InOrderTraverse(bt);
printf("\n");
return 0;
}
程序代码bst
#include<stdio.h>
#include<stdlib.h>
#define MAX 20
#if 1
//二叉排序树的创建、查找、删除
typedef struct
{
KeyType key;
InfoType otherinfo;
}ElemType;
typedef struct BSTNode
{
ElemType data;
struct BSTNode *lchild,*rchild;
}BSTNode,*BSTree;
void CreatBST(BSTree &T)
{//依次读入一个关键字为key的结点,将此结点插入二叉排序树T中
T=NULL; //将二叉排序树T初始化为空树
cin>>e;
while(e.key!=ENDFLAG) //ENDFLAG为自定义常量,作为输入结束标志
{
InsertBST(T,e); //将此结点插入二叉排序树r中
cin>>e;
}
}
//中序遍历输出
void InOrderTraverse(BSTNode *bt)
//输出二叉排序树bt
{
if (bt!=NULL)
{
InOrderTraverse(bt->lchild);
printf("%d",bt->key);
printf(",");
InOrderTraverse(bt->rchild);
}
}
//查找
BSTree SearchBST(BSTree T,KeyType key)
{//在根指针T所指二叉排序树中递归地查找某关键字等于key的数据元案//若查找成功,则返回指向该数据元素结点的指针,否则返回空指针
if((!T)||key==T->data.key) return T;
else if(key<T->data.key) return SearchBST(T->lchild,key);
elsereturn SearchBST(T->rchild,key);
}
//删除一个结点
void DeleteBST(BSTree &T,KeyType key){
p=T;f=NULL;
while(p)
{
if(p->data.key==key) break; //找到关键字等于key的结点“p,结束循环f=p;
f=p;//*f为*p的双亲结点
if(p->data.key>key) p=p->lchild; //在*p的左子树中继续查找
else p=p->rchild; //在*p的右子树中继续查找
}
if(p) return; //找不到被删结点则返回
q=P;
if((p->lchild)&&(p->rchild)) //被删结点*p左右子树均不空
{
s=p->1child;
while (s->rchild) //在*p的左子树中继续查找其前驱结点,即最右下结点
{
q=s; s=s->rchild; //向右到尽头
}
p->data=s->data; //s指向被删结点的“前驱”
if(q!=p) q->rchild=s->lchild; //重接+q的右子树
else g->lchild=s->lchild; //重接*q 的左子树
delete s;
return;
}
else if(!p->rchild) //被删结点*p无右子树,只需重接其左子树
{
p=p->lchild;
}
else if(!p->lchild) //被删结点*p无左子树,只需重接其右子树
{
p=p->rchild;
}
if(!f) T=p; //被删结点为根结点
else if(g==f->lchild) f->1child=p; //挂接到*E的左子树位置delete q; //挂接到*f的右子树位置
else f->rchild=p;
delete q;
}