数据结构之排序二叉树操作

#include <stdio.h>
#include <malloc.h>  
#include <ctype.h>
# define MAXSIZE  40 // 待排顺序表最大长度 
int corect=0;
#define OK 1
#define ERROR 0
typedef  int  KeyType;  // 关键字类型为整数类型
typedef  int  ElemType;  // 数据类型为整数类型
//数据结构定义模块
typedef struct{          //记录类型
    KeyType  key;        // 关键字域
    ElemType data;       //  其它属性域,存储要存储的数据
}RcdType,*TRcdType;

typedef struct{              //数据表
	RcdType  r[MAXSIZE];   //数组中r[0]空出
	int length;              //数据表长度
}Arglist,*TArglist;

typedef struct  BiTNode{                 // 结点结构
    RcdType                 data;    //结点存储数据为记录类型
    struct BiTNode   *lchild,*rchild;   // 左右孩子指针
}BiTNode,*BiTree;
BiTree root,p,f,g;
//初始一个空二叉树
int createbitree(BiTree &T){
	//初始化二叉树T为空
	T=(BiTree)malloc(sizeof(BiTNode));
	if(!T) {
		printf("空间分配出错!\n");
		return 0;
	}
	T=NULL;	
	return 1;
}//createbitree

//数据表生成及显示模块
TArglist create(TArglist &L){
	//生成有n个数据元素的数据表,并返回数据表头指针	
	int i;
	L->r[0].data=L->r[0].key=0;
	printf("请输入数据表元素,格式为(关键字 数据)(注意:数据类型均为整型且各元素关键字需不同!):\n");
	for(i=1;i<=L->length;i++){
		scanf("%d %d",&L->r[i].key,&L->r[i].data);
	}
	return L;
}//create
int printarg(TArglist L){
	//打印出所生成的数据表
	int i;
	for(i=1;i<=L->length;i++)printf("%d %d \n",L->r[i].key,L->r[i].data);
	printf("\n");
	return 1;
}//printarg
int scanarg(TArglist &L){
	//数据表输入及打印函数
	printf("请您输入要创建的数据表的长度(请输入3~%d的整数!):\n",MAXSIZE);
	scanf("%d",&L->length);
	if(!(L->length<=MAXSIZE&&L->length>=3)){
		printf("输入非法!请重新输入!\n");
		scanarg(L);
	}
	L=create(L);          
	printf("生成的数据表为(关键字 数据):\n");
	printarg(L);
	return 1;
}//scanarg
//自动生成二叉排序树
int compare(BiTree &q,TArglist L,int i){
	//递归法建立二叉排序树
	if(L->r[i].key==q->data.key){
		printf("输入数据表中存在关键字相同的元素,请重新进行建树操作!\n");
		corect=0;
		return 0;
	}
	else if(L->r[i].key>q->data.key){     //若该结点关键字比r[i]大,且其右子树为空则创建其右子树为r[i];否则比较其右子树
		if(q->rchild==0){
			q->rchild=(BiTree)malloc(sizeof(BiTNode));
			if(!q->rchild){
				printf("程序运行出错!\n");
				return ERROR;
			}
			else{
				q->rchild->data=L->r[i];
				q->rchild->lchild=NULL;
				q->rchild->rchild=NULL;
			}
		}
		else compare(q->rchild,L,i);
	}
	else if(L->r[i].key<q->data.key){   //若该结点关键字比r[i]小,且其左子树为空则创建其左子树为r[i];否则比较其左子树
		if(q->lchild==0){
			q->lchild=(BiTree)malloc(sizeof(BiTNode));
			if(!q->lchild){
				printf("程序运行出错!\n");
				return 0;
			}
			else{
				q->lchild->data=L->r[i];
				q->lchild->lchild=NULL;
				q->lchild->rchild=NULL;
			}
		} 
		else compare(q->lchild,L,i);
	}
	return 1;
}//compare
int creatBiTree(BiTree &root,TArglist L)
{ //创建二叉排序树
	int i=1; 
	if (L->r[i].key){
		root=(BiTree)malloc(sizeof(BiTNode));
		root->data.key=L->r[i].key;
		root->data.data=L->r[i].data;
		root->lchild=root->rchild=NULL;
	}
	else
	{printf("程序运行出错!\n");return ERROR;}
	for(++i;i<=L->length;i++)compare(root,L,i);		
	if(corect)printf("建树操作已完成!\n");
	return 1;
}//creatBiTree
//查找模块
int SearchBST(BiTree T,KeyType k,BiTree &f,BiTree &p){
	//在根指针T所指二叉排序树中递归地查找其关键字等于k的数据元素,
	//若查找成功,则返回指针p指向该数据元素的结点,并返回函数值为OK; 
	//否则表明查找不成功,返回指针p指向查找路径上访问的最后一个结点,
    //并返回函数值为ERROR; 指针f指向当前访问的结点的双亲,其初始调用值为NULL。
	if(!T){              // 二叉排序树不为空 查找不成功
		p=f;
		return 0;
	} 
	else if(k==T->data.key){                                     // 查找成功
		p=T;
		g=f;
		printf("查找到了关键字为%d的元素:\n 关键字为:%d 数据为:%d \n",p->data.key,p->data.key,p->data.data);
		return OK;
	} 
	else if(k<T->data.key) SearchBST(T->lchild,k,T,p);  
   // 在左子树中继续查找	
	else SearchBST(T->rchild,k,T,p);      // 在右子树中继续查找
  } // SearchBST
  //二叉排序树的插入算法
int InsertBST(BiTree &T,TRcdType e,BiTree &f,BiTree &p){
	//当二叉排序树中不存在关键字等e.key的数据元素时,插入元素值为e的结点,并返回TRUE;否则,不进行插入并提示和返回FALSE
	BiTree s;
	if(!SearchBST(T,e->key,f,p)){
		s=(BiTree)malloc(sizeof(BiTNode));                           //为新结点分配空间
		s->data.data=e->data;
		s->data.key=e->key;  
		s->lchild=s->rchild=NULL;  
		if(!p)T=s;                  //插入s为新的根结点
		else if(e->key<p->data.key) 
			p->lchild=s;                 //插入*s为*p的左孩子
		else p->rchild=s;        //插入*s为*p的右孩子
		printf("插入操作已完成!\n");
		return OK;                  //插入成功                            
	}
	else {
		printf("要插入的数据已存在,插入操作失败!\n");
		return ERROR;
	}
} // InsertBST
  //二叉排序树的删除算法
int DeleteBST(BiTree &T,KeyType k){
	//若二叉排序树T中存在其关键字等于k的数据元素,则删除该数据元素结点,并返回函数值TRUE,否则返回函数值FALSE
	BiTree q;
	createbitree(q);
	if(!T||!SearchBST(T,k,f,p)){                           // 不存在关键字等于kval的数据元素
		printf("未找到要删除的元素。删除操作失败!\n");
		return ERROR;
	}
	else if(g->lchild==p){
		if(!p->rchild&&p->lchild){ //右子树为空树则只需重接其左子树
			g->lchild=p->lchild; 
			q=p;
			free(q);
			return OK;
		}
		else if(p->rchild&&!p->lchild){//左子树为空只需重接其右子树
			g->lchild=p->rchild;
			q=p;
			free(q);
			return OK;
		}
		else if(p->rchild&&p->lchild){
			q=p;
			free(q);
			return OK;
		}
	}
	else {
		if(!p->rchild&&p->lchild){            //右子树为空树则只需重接它的左子树
			g->rchild=p->lchild; 
			q=p;
			free(q);
			return OK;
		}
		else if(p->rchild&&!p->lchild){       // 左子树为空树只需重接它的右子树
			g->rchild=p->rchild;
			q=p;
			free(q);
			return OK;
		}
		else if(p->rchild&&p->lchild){
			q=p;
			free(q);
			return OK;
		}
	}  
}//DeleteBST 
int visit(BiTree &T){
	//对数据元素操作的应用函数
printf("%d %d \n",T->data.key,T->data.data);
return OK;
}//visit
int preordertraverse(BiTree &t){     //先序遍历
	if(t){
	if(visit(t))
		if(preordertraverse(t->lchild)) 
			if(preordertraverse(t->rchild)) return OK;
	return ERROR;
	}
	else return OK;
}//preordertraverse
int inordertraverse(BiTree &t){     //中序遍历
	if(t){
	if(inordertraverse(t->lchild))
		if(visit(t))
			if(inordertraverse(t->rchild)) return OK;
	return ERROR;
	}
	else return OK;
}//inordertraverse
int postordertraverse(BiTree &t){     //后序遍历
	if(t){                
	if(postordertraverse(t->lchild))
		if(postordertraverse(t->rchild))
			if(visit(t)) return OK;
	return ERROR;
	}
	else return OK;
}//postordertraverse
int menuselect(){	//菜单选择程序
	int n;	
printf("*********************************************\n");
	printf("*     欢迎进入二叉排序树相关操作演示系统!    *\n");
	printf("*                                            *\n");
	printf("*         您可进行的操作有:                  *\n");
	printf("*         1.建树操作;                       *\n");
    printf("*        2.查找操作;                       *\n");
	printf("*3.二叉排序树的遍历(a.先序遍历;b.中序遍历;c.后序遍历);*\n");
	printf("*         4.二叉树的插入操作;               *\n");
	printf("*         5.二叉树的删除操作;               *\n");
	printf("*         6.退出系统;                       *\n");
	printf("*                                           *\n");
	printf("**************************************8******\n");
	printf("请输入操作代码:\n");
	scanf("%d",&n);
	if(n<=6&&n>=1)return n;
	else return ERROR;
}//menuselect
int main(){
	//主程序显示操作界面 实现各功能调用
	TArglist L;                    //数据声明
	int i=0,k=0,n=0;	
	char q='a';
	TRcdType r,s;
	L=(TArglist)malloc(sizeof(Arglist));      //初始化数据表L
	L->length=0;
	for(i;i<=MAXSIZE;i++) L->r[i].key=L->r[i].data=0;
	createbitree(root);                        //建空树root p f g
	createbitree(p);
	createbitree(f);
	r=s=(TRcdType)malloc(sizeof(RcdType));      //初始化r s
	if(!r||!s)printf("数据初始化出错!\n");
	else r->data=r->key=s->data=s->key=0;
	for(;n=6;){
		switch(menuselect()){
		case 1:
			scanarg(L);            //输入数据表
			creatBiTree(root,L);   //创建二叉排序树
			printf("\n");
			break;
		case 2:
			printf("请输入要查找的数据的关键字:\n");
			scanf("%d",&k);
			if(!SearchBST(root,k,f,p))printf("未找到指定的元素!\n");      //查找
			printf("\n");
			break;
		case 3:
			{
				printf("请输入要进行的遍历类型代码(回到上一级菜单请输入‘e’!):\n");
				scanf("%s",&q);
				switch(q){
				case 'a':
					printf("则先序遍历二叉排序树的结果为(关键字 数据):\n");
					preordertraverse(root);
					printf("\n");
					break;
				case 'b':
					printf("则中序遍历二叉排序树的结果为(关键字 数据):\n");
					inordertraverse(root);
					printf("\n");
					break;
				case 'c':
					printf("则后序遍历二叉排序树的结果为(关键字 数据):\n");
					postordertraverse(root);
					printf("\n");
					break;
				case 'e':
					break;
				default:
					printf("操作代码输入错误!请输入“a”“b”“c”中的一个代码。\n");
					printf("\n");
					break;
				} 
				break;
			}
		case 4:
			printf("请输入要插入的数据(关键字 数据):\n");
			scanf("%d %d",&r->key,&r->data);
			InsertBST(root,r,f,p);     //插入二叉排序树中没有的元素
			printf("\n");
			break;
		case 5:
			printf("请输入要删除的数据(关键字 数据):\n");
			scanf("%d %d",&s->key,&s->data);   //删除二叉排序树中已有的指定元素
			if(DeleteBST(root,s->key))printf("指定元素已删除!\n");
			printf("\n");
			break;
		case 6:
			printf("已成功退出系统!\n");
			break;
		default:
			printf("操作代码输入错误!请重新输入!(请输入“1”“2”“3”“4”“5 ”“6””中的一个操作代码。)\n");
		}	
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值