数据结构实验-C语言-二叉树的创建,前、中、后序遍历的递归算法和非递归算法,求叶子结点数目,求二叉树深度,判断二叉树是否相似,求二叉树左右子树互换,二叉树层序遍历的算法,判断二叉树是否是完全二叉树

1.实验目的

熟练掌握二叉树的二叉链表存储结构的C语言实现。掌握二叉树的基本操作-前序、中序、后序遍历二叉树的三种方法。了解非递归遍历过程中“栈”的作用和状态,而且能灵活运用遍历算法实现二叉树的其它操作。

2.实验内容

(1)二叉树的二叉链表的创建

(2)二叉树的前、中、后序遍历的递归算法和非递归算法的实现

(3)求二叉树中叶子结点数目的递归算法。

(4)编写求二叉树深度的递归算法。

(5)编写判断二叉树是否相似的递归算法

(6)编写求二叉树左右子树互换的递归算法

(7)编写二叉树层序遍历的算法

(8)编写判断二叉树是否是完全二叉树的算法

创建二叉树的二叉链表结构、进行先、中、后序的递归函数显示不同遍历序列,结合习题了解二叉树遍历的应用实例。编写前、中、后、层序遍历的非遍历函数,注意用以前做过的栈和队列作辅助存储结构。掌握用遍历算法求解其它问题的方法。

#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
#define OVERFLOW -1
#define TRUE 1
#define FALSE 0
#define LEN struct BiTNode
#define SIZEINIT 10
#define INCRESIZE 5

typedef int Status;
typedef char TElemType;
 
typedef struct BiTNode{
	TElemType data;
	struct BiTNode *lchild,*rchild;
}BiTNode ,*BiTree;

typedef struct SqStack{
	BiTree base;
	BiTree top;
	int stacksize;
	
}SqStack;

typedef struct SqQue{
	BiTree base;
	int front,rear;
}SqQue;

//前序创建二叉树 
Status CreatBiTree(BiTree &T){
	char ch;
	scanf("%c",&ch);
	if(ch==' '){
		T=NULL;
	}else{
		if(!(T = (BiTree)malloc(sizeof(LEN))))  exit(OVERFLOW);
		T->data = ch;
		CreatBiTree(T->lchild);
		CreatBiTree(T->rchild);
	}
	return OK;
}

//前序遍历的递归算法
Status PreOrderTraverse(BiTree T,Status (*Visit)(TElemType e)){
	if(T){
		if(Visit(T->data)){
			if(PreOrderTraverse(T->lchild,Visit)){
				if(PreOrderTraverse(T->rchild,Visit)) return OK;
			}
		}
		return ERROR;
	}
	return OK;
}
//中序遍历的递归算法
Status InOrderTraverse(BiTree T,Status (*Visit)(TElemType e)){
	if(T){
		if(InOrderTraverse(T->lchild,Visit)){
			if(Visit(T->data)){
				if(InOrderTraverse(T->rchild,Visit)) return OK;
			}
		}
		return ERROR;	
	}
	return OK;
}
//后序遍历的递归算法
Status PostOrderTraverse(BiTree T,Status (*Visit)(TElemType e)){
	if(T){
		if(PostOrderTraverse(T->lchild,Visit)){
			if(PostOrderTraverse(T->rchild,Visit)){
				if(Visit(T->data)) return OK;
			}
		}
		return ERROR;		
	}
	return OK;
}

//访问函数 
Status Visit(TElemType e){
	printf("%c",e);
	return OK; 
}

//递归算法求叶子节点的个数
int LBNode(BiTree T){
	static int num = 0;
	if(T){
		if(T->lchild==NULL&&T->rchild==NULL){
			num++;
		}else{
			LBNode(T->lchild);
			LBNode(T->rchild);
		}
	}
	return num;
}

//求二叉树的深度
int DepthBiTree(BiTree T){
	int ldepth,rdepth;
	if(T){
		ldepth = DepthBiTree(T->lchild);
		rdepth = DepthBiTree(T->rchild);
		return (ldepth>rdepth?ldepth:rdepth)+1;	
	}
	return 0;//如果是空树,结点数是0 
} 

//判断两个二叉树是否相同的递归算法
Status SimBiTree(BiTree T1,BiTree T2){
	if(T1==NULL&&T2==NULL)//二者都是空树 
		return TRUE;
	else if(T1==NULL||T2==NULL)//其中一个为空 另一个不为空 
		return FALSE;
	else{
		if(T1->data!=T2->data) return FALSE;
		int l1 = SimBiTree(T1->lchild,T2->lchild);//左支树是否相似  
		int l2 = SimBiTree(T1->rchild,T2->rchild);//右支树是否相似 
		return (l1&&l2);
	}
}

//左右子树交换位置的递归算法 
Status change(BiTree &T){
	if(T){
		BiTree temp = T->lchild;
		T->lchild = T->rchild;
		T->rchild = temp;
		change(T->lchild);
		change(T->rchild);
		return OK;
	}
}

//初始化一个栈
Status InitStack(SqStack &s){
	s.base = (BiTree)malloc(SIZEINIT*sizeof(TElemType));
	if(!s.base){
		printf("申请内存空间失败\n");
		exit(OVERFLOW);
	}
	s.top = s.base;
	s.stacksize = SIZEINIT;
}

//入栈
Status Push(SqStack &s,BiTNode e){
	if(s.top - s.base==s.stacksize){//内存空间不够 需要重新分配 
		s.base = (BiTree)realloc(s.base,(s.stacksize+INCRESIZE)*sizeof(TElemType));
		if(!s.base)exit(OVERFLOW);
		s.top = s.base+s.stacksize;
		s.stacksize += INCRESIZE;
	}
	*s.top++ = e;
	return OK;
} 

//出栈
Status Pop(SqStack &s,BiTree &p){
	if(s.base==s.top){
		printf("空栈!\n"); 
		return ERROR;
	}
	p = --s.top;
	return OK;
}

//中序遍历的非递归算法
Status InOrderTraverse2(BiTree T,Status(*Visit)(TElemType)){
	if(T){
		SqStack s;
		BiTree p = T;//指向结点的指针 
		InitStack(s); //初始化一个栈用来存放树结点 
		while(p||s.base!=s.top){//当结点不为空 或者栈不空的时候 = 不是空树 
			if(p){//如果p指向结点有左子树 应先访问他的左子树
				Push(s,*p);//将树的p所指结点数据入栈 
				p = p->lchild;
			}else{//说明没有左子树 那应该访问p指向的这一结点本身
				Pop(s,p);//将现在p所指结点的双亲出栈 并把他的的地址赋给p 也就是把栈顶元素返回给*p 即改变p的指向 
				Visit((*p).data);//没有左子树 就该访问其根结点了 
				p = p->rchild;//访问过根结点了 该开始遍历右子树 
			}
	}
	return OK;
	}
	return ERROR;
}
//初始化一个循环队列
Status InitSqQue(SqQue &q){
	q.base = (BiTree)malloc(SIZEINIT*sizeof(BiTNode));
	if(!q.base) exit(OVERFLOW);
	q.front = q.rear = 0;
	return OK;
}
//入队列
Status EnSqQue(SqQue &q,BiTree e){
	if((q.rear+1)%SIZEINIT==q.front){
		printf("队列已满!\n");
		return ERROR;
	}
	*(q.base + q.rear)= *e;
	q.rear = (q.rear+1)%SIZEINIT;
	return OK;
}
//出队列 
Status DeSqQue(SqQue &q,BiTree &p){//如果加上队列为空的判断条件的话 在层序遍历的时候会陷入死循环 
	p = q.base+q.front;
	q.front = (q.front+1)%SIZEINIT;
}

//二叉树层序遍历的非递归算法
Status printNodeByLevel(BiTree T,Status (*Visit)(TElemType e)){
	if(T){
		BiTree p = T;
		SqQue q;
		InitSqQue(q);
		EnSqQue(q,T);
		while(q.front!=q.rear){//当队列不为空的时候 
			DeSqQue(q,p);
			Visit(p->data);
			if(p->lchild) 
				EnSqQue(q,p->lchild);
			if(p->rchild)
				EnSqQue(q,p->rchild);
		}
	}
} 

//判断是否是完全二叉树
Status IsAbsoBiTree(BiTree T){
	if(!T){//空树 
		return TRUE; 
	}else if(T->lchild==NULL&&T->rchild==NULL){
		return TRUE;
	}else{//有一个或两个孩子 
		SqQue q;
		BiTree p = T;
		InitSqQue(q);
		EnSqQue(q,T);//先将根结点入队列
		while(q.front!=q.rear){
			DeSqQue(q,p);
			if(!p->data) break;//如果出队列的数为空 就跳出这个出队入队的循环 
			EnSqQue(q,p->lchild);//不管有没有左右孩子 都让他们入栈 
			EnSqQue(q,p->rchild);
		}
		while(q.front!=q.rear){//判断遇到空之后 队列里还有没有非空的元素 
			DeSqQue(q,p);//让队列里的元素一个一个出队列判断 
			if(p->data) return FALSE;//当出来的元素不为空的时候 说明不是完全二叉树 
		}
		return TRUE;//如果出来的元素全是控 也就是说队列里所剩的元素没有非空的 说明是完全二叉树 
	}
}

main(){
	BiTree T1,T2;
	int flag;
	
	printf("\n请前序创建第一棵树(空位置用空格来代替)\n");
	CreatBiTree(T1);
	
	
	printf("\n0.退出");
	printf("\n1.二叉树前序递归遍历的结果");
	printf("\n2.二叉树中序递归遍历的结果");
	printf("\n3.二叉树后序递归遍历的结果");
	printf("\n4.二叉树中序非递归遍历的结果");
	printf("\n5.二叉树层序遍历的结果");
	printf("\n6.二叉树叶子节点的个数");
	printf("\n7.二叉树二叉树的深度");
	printf("\n8.判断两个二叉树是否相同");
	printf("\n9.二叉树左右子树交换位置");
	printf("\n10.判断是否是完全二叉树");
	
	printf("\n请选择:");
	scanf("%d",&flag);
	
	while(flag){
		switch(flag){
			case 0: exit(0);
			case 1: PreOrderTraverse(T1,Visit);  
					break;
			case 2: InOrderTraverse(T1,Visit);   
					break;
			case 3: PostOrderTraverse(T1,Visit); 
					break;
			case 4: InOrderTraverse2(T1,Visit); 
					break;
			case 5: printNodeByLevel(T1,Visit);
					break; 
			case 6: printf("%d",LBNode(T1));
					break;
			case 7: printf("%d",DepthBiTree(T1));
					break;
			case 8:	getchar();//消化最后输入留在缓冲区的回车键 
					printf("\n请创建第二棵树\n");
					CreatBiTree(T2); 
					if(SimBiTree(T1,T2)) printf("相似\n");
					else printf("不相似\n");
					break;
			case 9: change(T1); 
					PreOrderTraverse(T1,Visit); 
					break; 
			case 10:if(IsAbsoBiTree(T1)) printf("是完全二叉树");
					else printf("不是完全二叉树");
					break;
			default:printf("输入有误 请重新输入:"); 
		}
		printf ("\n"); 
		scanf("%d",&flag);
	}
}

猜你喜欢

转载自blog.csdn.net/J_SUNV/article/details/84307692