2019.6.24-2019.6.28(实训数据结构) 书籍:《数据结构项目实训教程》 赵君喆,戴文华
9.2.1二叉排序树
要求开发一个二叉排序树的操作程序,要求程序至少具备以下操作接口:
初始化、销毁、查找、插入、删除、遍历
#include<cstdio> #include<stdlib.h> #include<string.h> //#include<cunity> #include<iostream> #include<string> #include<fstream> #include<iomanip> #include<algorithm> using namespace std; #define N 10 typedef int KeyType; typedef int Status; typedef struct{ KeyType key; int others; }ElemType; //数据元素类型 typedef ElemType TElemType; typedef struct BiTNode{ TElemType data; struct BiTNode *lchild,*rchild; //左右孩子指针 }BiTNode, *BiTree; //二叉树的二叉链表存储表示 #define EQ(a, b) ((a) == (b)) #define LT(a, b) ((a) < (b)) #define LQ(a, b) ((a) <= (b)) #define InitDSTable InitBiTree //与初始化二叉树操作同 #define DestroyDSTable DestroyBiTree //与销毁二叉树操作同 #define TraverseDSTable InOrderTraverse //与中序遍历操作同 Status InitBiTree(BiTree &T){ T=NULL; return true; } void DestroyBiTree(BiTree &T){ if(T){ if(T->lchild) DestroyBiTree(T->lchild); if(T->rchild) DestroyBiTree(T->rchild); free(T); T=NULL; } } Status BiTreeEmpty(BiTree T){ if(T) return false; else return true; } //中序遍历 void InOrderTraverse(BiTree T,void(*Visit)(TElemType)){ if(T){ InOrderTraverse(T->lchild,Visit); //先中序遍历左子树 Visit(T->data); //再中序访问根结点 InOrderTraverse(T->rchild,Visit); // 最后中序遍历右子树 } printf("\n"); } // 初始条件:二叉树T存在,Visit是对结点操作的应用函数 // 操作结果:后序递归遍历T,对每个结点调用函数Visit一次且仅一次 void PostOrderTraverse(BiTree T,void(*Visit)(TElemType)) { if(T) // T不空 { PostOrderTraverse(T->lchild,Visit); // 先后序遍历左子树 PostOrderTraverse(T->rchild,Visit); // 再后序遍历右子树 Visit(T->data); // 最后访问根结点 } } // 初始条件:二叉树T存在,Visit是对结点操作的应用函数 // 操作结果:先序递归遍历T,对每个结点调用函数Visit一次且仅一次 void PreOrderTraverse(BiTree T,void(*Visit)(TElemType)) { if(T) // T不空 { Visit(T->data); // 先访问根结点 PreOrderTraverse(T->lchild,Visit); // 再先序遍历左子树 PreOrderTraverse(T->rchild,Visit); // 最后先序遍历右子树 } } Status SearchBST(BiTree &T,KeyType key,BiTree f,BiTree &p){ /*在根指针T所指二叉排序树中递归地查找其关键字等于key的数据元素,若查找 成功,则指针p指向该数据元素结点,并返回TRUE,否则指针p指向查找路径上 访问的最后一个结点并返回FALSE,指针f指向T的双亲,其初始调用值为NULL*/ if(!T){ //查找不成功 p=f; return false; } else if EQ(key,T->data.key){ // 查找成功 p=T; return true; } else if LT(key,T->data.key){ // 在左子树中继续查找 return SearchBST(T->lchild,key,T,p); } else{ // 在右子树中继续查找 return SearchBST(T->rchild,key,T,p); } } BiTree SearchBST(BiTree T,KeyType key){ /*在根指针T所指二叉排序树中递归地查找某关键字等于key的数据元素, 若查找成功,则返回指向该数据元素结点的指针,否则返回空指针*/ if(!T||EQ(key,T->data.key)) return T; //查找结果 else if(LT(key,T->data.key)) //在左子树中继续寻找 return SearchBST(T->lchild,key); else //在右子树中继续寻找 return SearchBST(T->rchild,key); } Status InsertBST(BiTree &T,ElemType e){ /*当二叉排序树T不存在关键字等于e.key的数据元素时, 插入e并返回TRUE,否则返回FALSE*/ BiTree p,s; if(!SearchBST(T,e.key,NULL,p)){ // 查找不成功 s=(BiTree)malloc(sizeof(BiTNode)); s->data=e; s->lchild=s->rchild=NULL; if(!p) T=s; //被插入的结点*s为新的根结点 else if LT(e.key,p->data.key) p->lchild=s; //被插入的结点*s为左孩子 else p->rchild=s; //被插入的结点*s为右孩子 return true; } else return false; //树中已有关键字相同的结点,不再插入 } void Delete(BiTree &p){ //从二叉排序树中删除结点p,并重接它的左或右子树 BiTree q,s; if(!p->rchild){ //p的右子树空,只需重接它的左子树 q=p; p=p->lchild; free(q); } else if(!p->lchild){ //p的左子树空,只需重接它的右子树 q=p; p=p->rchild; free(q) ; } else{ //p的左右子树均不为空 q=p; s=p->lchild; while(s->rchild){ //转左,然后向右直到尽头 q=s; s=s->rchild; } p->data=s->data; //s指向被删除结点的"前驱 " if(q!=p){ //情况1 q->rchild=s->lchild; //重接q的右子树 } else{ //情况2 q->lchild=s->lchild; //重接q的左子树 } free(s); } } Status DeleteBST(BiTree &T,KeyType key){ /*若二叉排序树T中存在关键字等于key的数据元素, 则删除该数据元素结点,并返回true;否则返回false*/ if(!T) return false; //不存在关键字等于key的数据元素 else{ if EQ(key,T->data.key) Delete(T); //找到关键字等于Key的元素 else if LT(key,T->data.key) DeleteBST(T->lchild,key); else DeleteBST(T->rchild,key); return true; } } void print(ElemType c){ printf("(%d,%d) ",c.key,c.others); } int main(){ int choose; BiTree dt,p; int i,n; KeyType j; ElemType r[N]={{45,1},{12,2},{53,3},{3,4},{37,5},{24,6},{100,7},{61,8},{90,9},{78,10}}; cout<<" 欢迎来到二叉树排序操作程序!!!!!" <<endl; cout<<" 请按以下数字操作" <<endl; cout<<"----------------------------------1.初始化----------------------------------"<<endl; cout<<"----------------------------------2.销毁----------------------------------"<<endl; cout<<"----------------------------------3.插入------------------------------------"<<endl; cout<<"----------------------------------4.查找------------------------------------"<<endl; cout<<"----------------------------------5.删除----------------------------------"<<endl; cout<<"----------------------------------6.遍历--------------------------------------"<<endl; cout<<"----------------------------------0.退出程序------------------------------------"<<endl<<endl; choose=-1; while(choose!=0){ cout<<"--------------------------------------------------------------------------------"<<endl; cout<<"请选择:"<<endl; cin>>choose; switch(choose){ case 0: cout<<"您已经成功退出系统,欢迎您下次再来!"<<endl; break; case 1: InitDSTable(dt); cout<<"您已经成功初始化!"<<endl; break; case 2: DestroyDSTable(dt); printf("您已经成功销毁二叉排序树!\n"); break; case 3: int n ; /*printf("请输入要插入的元素个数:\n"); //scanf("%d",&n); //ElemType r[n]={}; printf("请依次输入要插入元素的关键字和变量:\n"); //for(i=0;i<n;i++){ // cin>>r[i].key>>r[i].others; //}*/ for(i=0;i<N;i++) InsertBST(dt,r[i]); printf("您已经成功插入元素!\n"); break; case 4: printf("请输入要查找的值:\n"); scanf("%d",&j); p=SearchBST(dt,j); if(p) printf("表中存在此值。\n"); else printf("表中不存在此值。\n"); break; case 5: printf("请输入要删除的元素:\n"); scanf("%d",&j); p=SearchBST(dt,j); if(p){ printf("表中存在此值,可以删除。\n"); DeleteBST(dt,j); printf("删除此值后:\n"); TraverseDSTable(dt,print); printf("\n"); } else printf("表中不存在此值,无法删除。\n"); break; case 6: printf("遍历二叉排序树:\n"); TraverseDSTable(dt,print); printf("您已经成功遍历!\n"); break; } } return 0; }
s