二叉树基本操作

二叉树基本操作

实验要求:
1.按先序序列构造一棵二叉链表表示的二叉树T;
2.对这棵二叉树进行递归遍历:先序、中序、后序以及层次遍历遍历序列,分别输出结点的遍历序列;
3. 对这棵树用非递归方式进行遍历:先序、中序以及后序遍历序列,分别输出结点的遍历序列;
4.求二叉树的深度/结点数目/叶结点数目;
5.将二叉树每个结点的左右子树交换位置;
6. 设计二叉树的双序遍历算法(双序遍历是指对于二叉树的每一个结点来说,先访问这个结点,再按双序遍历它的左子树,然后再一次访问这个结点,接下来按双序遍历它的右子树);
7. 计算二叉树最大宽度(二叉树的最大宽度是指二叉树所有层中结点个数的最大值);
8. 求二叉树中第一条最长的路径长度,并输出此路径上各结点。

#include<stdio.h>
#include<stdlib.h>

#define STACKSIZE 20

typedef struct tree_node{
	char data;
	struct tree_node *LC;
	struct tree_node *RC;
}TreeNode,*Tree;

typedef struct queue_node{
	struct tree_node *treenode;
	struct queue_node *next;
}QueueNode;

typedef struct queue{
	struct queue_node *front;
	struct queue_node *rear;
}Queue;


void CreatPre(Tree *b);
void ShowPre(Tree b);
void ShowIn(Tree b);
void ShowPost(Tree b);
void LevelShow(Tree T);
void DoubleShow(TreeNode *T);
void InitQueue(Queue *q);
int IsQueueEmpty(Queue *q);
void InQueue(Queue *q,QueueNode *p);
void OutQueue(Queue *q,QueueNode *p);
void PreOrder(TreeNode *bt);
void InOrder(TreeNode *bt);
void PostOrder(TreeNode *bt);
int TreeHeight(Tree root);
int LevelWidth(Tree root,int level);
int Width(Tree root);
int CountAll(Tree root);
int CountLeaf(Tree root);
void ShowLeaf(Tree root);
void ExChangeTree(Tree T);
int Find(Tree root);
void PrintLength(Tree root);



//按先序序列构造一棵二叉链表表示的二叉树T
void CreatPre(Tree *b){
	char ch;

	scanf("%c",&ch);

	if(ch=='*')
		*b=NULL;
	else{
		*b=(Tree)malloc(sizeof(TreeNode));
		(*b)->data=ch;

		CreatPre(&(*b)->LC);
		CreatPre(&(*b)->RC);
	}

}
//前序遍历
void ShowPre(Tree b){
	if(b){
		printf("%c ",b->data);
		ShowPre(b->LC);
		ShowPre(b->RC);
	}
}

//中序遍历
void ShowIn(Tree b){
	if(b){
		ShowIn(b->LC);
		printf("%c ",b->data);
		ShowIn(b->RC);
	}
	
}

//后序遍历
void ShowPost(Tree b){
	if(b){
		ShowPost(b->LC);
		ShowPost(b->RC);
		printf("%c ",b->data);
	}
	
}

//层次遍历
void LevelShow(Tree T){
	Queue *Q;
	Queue m_queue;
	QueueNode *p,*q;
	if(!T)
		return;
	
	Q=&m_queue;
	InitQueue(Q);

	p=(QueueNode *)malloc(sizeof(QueueNode));
	p->next=NULL;
	p->treenode=T;
	InQueue(Q,p);

	while(!IsQueueEmpty(Q)){
		OutQueue(Q,&q);
		printf("%c ",q->treenode->data);

		if(q->treenode->LC){
			p=(QueueNode *)malloc(sizeof(QueueNode));
			p->next=NULL;
			p->treenode=q->treenode->LC;
			InQueue(Q,p);
		}
		if(q->treenode->RC){
			p=(QueueNode *)malloc(sizeof(QueueNode));
			p->next=NULL;
			p->treenode=q->treenode->RC;
			InQueue(Q,p);
		}

	}

}

//双序遍历
void DoubleShow(TreeNode *T)
{
	if(T)
	{
		printf("%c ",T->data);
		DoubleShow(T->LC);
		printf("%c ",T->data);
		DoubleShow(T->RC);
	}
}

//队列操作
//初始化队列
void InitQueue(Queue *q){
	//简单初始化
	q->front=NULL;
	q->rear=NULL;
}

//队列是否为空
int IsQueueEmpty(Queue *q){
	if(q->front)
		return 0;
	else
		return 1;

}

//进队
void InQueue(Queue *q,QueueNode *p){
	if(IsQueueEmpty(q)){
		q->front=p;
		q->rear=p;
	}else{
		q->rear->next=p;
		q->rear=p;
	}
}

//出队
void OutQueue(Queue *q,QueueNode **p){
	*p=q->front;
	if(q->front==q->rear){
		q->front=NULL;
		q->rear=NULL;
	}else{
		q->front=q->front->next;
	}

}

//先序非递归遍历
void PreOrder(TreeNode *bt){
	TreeNode *s[STACKSIZE];
	int i=0;
	TreeNode *p;
	if(!bt)
		return;
	else
		p=bt;
	do{
		while(p){
			printf("%c ",p->data);
			s[i++]=p;
			p=p->LC;
		}
		if(i!=0){
			p=s[--i];
			p=p->RC;
		}
	}while(p||i!=0);
}

//中序非递归遍历
void InOrder(TreeNode *bt){
	TreeNode *s[STACKSIZE];
	int i=0;
	TreeNode *p;
	if(!bt)
		return;
	else
		p=bt;
	do{
		while(p){
			s[i++]=p;
			p=p->LC;
		}
		if(i!=0){
			p=s[--i];
			printf("%c ",p->data);
			p=p->RC;
		}
	}while(p||i!=0);
}

//后序非递归
void PostOrder(TreeNode *bt){

	TreeNode *s[STACKSIZE];
	TreeNode *r[STACKSIZE];
	int top1 = -1, top2=-1;
	s[++top1] = bt;
	while(top1!=-1){
		bt = s[top1--];
		r[++top2] = bt;  //只用来反向最后的一趟的结果
		/*
		由于栈的特点就是后进先出,所以左子树先入栈,然后出去的时候
		是右子树先出栈,故而这里就完成了第一次的左右子树的交换		
		*/ 
		if(bt->LC!=NULL){
			s[++top1] = bt->LC;
		}
		if(bt->RC!=NULL){
			s[++top1] = bt->RC;
		}
	}
	while(top2!=-1){
		bt = r[top2--];
		printf("%c ",bt->data);
	}
}

//4.求二叉树的深度/结点数目/叶结点数目

//二叉树深度
int TreeHeight(Tree root){
	int LCHeight,RCHeight;
	if(root==NULL)
		return 0;
    LCHeight=TreeHeight(root->LC);
    RCHeight=TreeHeight(root->RC);
	return (LCHeight>RCHeight)?(1+LCHeight):(1+RCHeight);
}

//某层宽度
int LevelWidth(Tree root,int level){
	if(!root)return 0;
	else
	{
		if(level==1)return 1;
		level=LevelWidth(root->LC,level-1)+LevelWidth(root->RC,level-1);
	}
	return level;
}

//取得二叉树最大宽度
int Width(Tree root){
	int width,i;
	int w[20];
	for(i=0;i<20;i++)w[i]=0;
	if(!root)width=0;
	else
	{
		for(i=0;i<=TreeHeight(root);i++)w[i]=LevelWidth(root,i+1);
	}
	i=0;
	while(w[i])
	{
		if(w[i]>width)width=w[i];
		i++;
	}
	return width;
}

//求所有结点的个数
int CountAll(Tree root){
	if(root==NULL)
		return 0;
	return CountAll(root->LC)+CountAll(root->RC)+1;
}

//求叶子结点的个数
int CountLeaf(Tree root){
	if(root==NULL)
		return 0;  
	if(root->LC==NULL&&root->RC==NULL)
		return 1;
	else{
		return CountLeaf(root->LC)+CountLeaf(root->RC);
	}
}


//输出叶子结点
void ShowLeaf(Tree root){
	if(root==NULL)
		return;
	if(root->LC==NULL&&root->RC==NULL)
    	printf("%c ",root->data);
	else{
		ShowLeaf(root->LC);
		ShowLeaf(root->RC);
	}
}

//将二叉树每个结点的左右子树交换位置
void ExChangeTree(Tree T){
 
    Tree temp;
    if (T)
    {
        temp = T->RC;
        T->RC = T->LC;
        T->LC = temp;
        ExChangeTree(T->LC);
        ExChangeTree(T->RC);
    }
    else
    {
        return;
    }
}

//为二叉树的节点赋层号
int Find(Tree root){
	if(!root->LC&&!root->RC){
		return 0;
	}else if(root->LC)
		return Find(root->LC)+1;
	else if(root->RC)
		return Find(root->RC)+1;
	else{
		if(Find(root->LC)>Find(root->RC))
			return Find(root->LC)+1;
		else
			return Find(root->RC)+1;
	}
}

//输出最长路径
void PrintLength(Tree root){
	if(root->LC&&root->RC){
		printf("%c ",root->data);
		if(Find(root->LC)>=Find(root->RC))
			PrintLength(root->LC);
		else
			PrintLength(root->RC);
	}
	else if(root->LC){
		printf("%c ",root->data);
		PrintLength(root->LC);
	}
	else if(root->RC){
		printf("%c ",root->data);
		PrintLength(root->RC);
	}
	else
		printf("%c ",root->data);
}

int main(){
	Tree T;
	printf("输入二叉树的前序遍历序列,用*代替空节点:\n");
	CreatPre(&T);

	printf("\n\n前序遍历:");
	ShowPre(T);
	printf("\n\n中序遍历:");
	ShowIn(T);

	printf("\n\n后序遍历:");
	ShowPost(T);

	printf("\n\n层次遍历:");
	LevelShow(T);

	printf("\n\n双序遍历:");
	DoubleShow(T);
	printf("\n\n");

	printf("\n先序非递归遍历:");
	PreOrder(T);
	
	printf("\n\n中序非递归遍历:");
	InOrder(T);

	printf("\n\n后序非递归遍历:");
	PostOrder(T);
	printf("\n");

	printf("\n第一条最长路径长度:");
	PrintLength(T);
	printf("\n");

	printf("\n二叉树深度为: %d",TreeHeight(T));
	printf("\n\n最大宽度: %d",Width(T));

	printf("\n\n二叉树结点数目: %d",CountAll(T));

	printf("\n\n二叉树叶结点:");
	ShowLeaf(T);

	printf("\n二叉树叶结点数目: %d",CountLeaf(T));
	printf("\n");

	printf("\n\n交换前二叉树先序遍历:");
	PreOrder(T);
	ExChangeTree(T);

	printf("\n\n交换二叉树左右子树完成!\n");

	printf("\n\n交换后二叉树先序遍历:");
	PreOrder(T);
	printf("\n");
	

	return 0;

}

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值