二叉树的几个基本算法

13 篇文章 0 订阅

二叉树的基本算法

1.二叉树的基本遍历算法(先序、中序、后序、层序)

2.二叉树的优化遍历算法(用栈实现)

3.求二叉树的深度算法

4.求二叉树的宽度算法

5.二叉树的构建算法


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

/** 
*	二叉树的基本算法
*	1.二叉树的基本遍历算法(先序、中序、后序、层序)
*	2.二叉树的优化遍历算法(用栈实现)
*	3.求二叉树的深度算法
*	4.求二叉树的宽度算法
*	5.二叉树的构建算法
*
*/

typedef struct BTNode{
	int data;
	struct BTNode * lchild;
	struct BTNode * rchild;
}BTNode;

/**
*	二叉树的三种遍历算法
*	1.先序、中序、后序、层序
*/
//先序
void Trave1(BTNode * root){
	if(root != NULL){
		printf("%d",root->data);
		Trave1(root ->lchild);
		Trave1(root ->rchild);
	}
}

//中序
void Trave2(BTNode * root){
	if(root != NULL){
		Trave2(root ->lchild);
		printf("%d",root->data);
		Trave2(root -> rchild);
	}
}

//后序
void Trave3(BTNode * root){
	if(root != NULL){
		Trave3(root->lchild);
		Trave3(root->rchild);
		printf("%d",root->data);
	}
}

#define maxSize 100
//二叉树的层序列遍历
void Trave4(BTNode * root){
	//用一个队列辅助遍历二叉树,左孩子和右孩子分别入队	
	BTNode * que[maxSize];
	int front = 0,rear = 0;
	if(root != NULL){
		//根结点入队
		rear = (rear + 1)%maxSize;
		que[rear] = root;
		while(front != rear){//队列不空则循环
			//出队
			front = (front +1)%maxSize;
			printf("%d",que[front]->data);
			//左右孩子进栈
			if(que[front]->lchild != NULL){
				rear = (rear + 1)%maxSize;
				que[rear] = que[front]->lchild;
			}
			if(que[front]->rchild != NULL){
				rear = (rear + 1)%maxSize;
				que[rear] = que[front]->rchild;
			}
		}
	}	
}

/**
*	二叉树的构建算法,通过'-1'表示结尾
*	思路:每次构建完成一个结点,再构建左右孩子,再返回该结点指针
*/
BTNode * createTree(){
	printf("请输入一个结点作为二叉树的一个结点\n");
	int data;
	scanf("%d",&data);
	if(data == -1){
		return NULL;
	}else{
		BTNode * root = (BTNode *)malloc(sizeof(BTNode));
		root->data = data;
		root -> lchild = createTree();
		root -> rchild = createTree();
		return root;
	}
}

/**
*	求二叉树的深度算法
*	思路:分别求二叉树的左右子树的深度,然后再加+1就是总深度,用递归算法即可完成
*/
int getDepth(BTNode * root){
	int ldepth,rdepth;
	if(root == NULL){
		return 0;
	}else{
		ldepth = getDepth(root->lchild);
		rdepth = getDepth(root->rchild);
		return (ldepth>rdepth?ldepth:rdepth) + 1;
	}
}

/**
*	求二叉树的宽度算法
*	思路:用层序遍历,将二叉树每层都标上号码,然后用迭代对其进行求最大值
*		标号的方式,这里我采用构建一个新的结构体,并定义一个队列数组来进行对每个结点标号
*		并且假设这个数组能够容纳下所有结点,这样才能方便在后面的迭代中求最大值
*/
typedef struct{
	BTNode * node;
	int flag;	//层号从1开始到n
}ST;

int getWidth(BTNode * root){
	//先构建一个顺序队列
	ST * que[maxSize];
	int front=0,rear=0;
	int flag = 1;
	if(root != NULL){
		//根节点入队,并标号为1,表示第1层
		ST * p = (ST *)malloc(sizeof(ST));
		p->flag = flag;
		p->node = root;
		rear ++;	
		que[rear] = p;	
		BTNode * q;
		while(root != NULL){
			front ++;	//这里出队,但是数据元素还是在数组中
			q = que[front]->node;
			if(que[front]->flag > flag){	//证明到达了下一层,那么flag也要增加,这里改写层flag = que[front]->flag也可以
				flag ++;	
			}
			if(que[front]->node->lchild != NULL){	//左孩子不空,则左孩子入队
				rear ++;
				/*
				que[rear]->node = q->lchild;
				que[rear]->flag = flag + 1;
				*/
				p = (ST *)malloc(sizeof(ST));
				p->node = q->lchild;
				p->flag = flag + 1;
				que[rear] = p;
			}
			if(que[front]->node->rchild != NULL){
				rear ++;
				/*
				que[rear]->node = q->rchild;
				que[rear]->flag = flag + 1;
				*/
				p = (ST *)malloc(sizeof(ST));
				p->node = q->rchild;
				p->flag = flag + 1;
				que[rear] = p;
			}
		}
		//下面求二叉树的最大宽度
		int i,j,max=0;
		for(i=1;i<=flag;i++){
			int n=0;
			for(j=1;j<=rear;j++){
				if(que[j]->flag == i){
					n++;
				}
			}
			if(max<n){
				max = n;
			}
		}
		return max;
	}
	return 0;
}
//不使用指针数组
int getWidth2(BTNode * root){
	ST que[maxSize];
	int flag = 1;
	int front=0,rear=0;
	if(root !=NULL){
		rear ++;
		que[rear].node = root;
		que[rear].flag = flag;
		BTNode * q;
		while(front != rear){
			front ++;
			q = que[front].node;
			flag = que[front].flag;
			if(q->lchild != NULL){
				rear ++;
				que[rear].node = q;
				que[flag].flag = flag + 1;
			}
			if(q->rchild != NULL){
				rear ++;
				que[rear].node = q;
				que[flag].flag = flag + 1;
			}
		}
		int max,n,i,j;
		for(i=1;i<=flag;i++){
			n = 0;
			for(j=1;j<=flag;j++){		
				if(que[j].flag == i){
					n++;
				}
			}
			if(max<n){
				max = n;
			}
		}
		return max;
	}
	return 0;
}

/**
*	用栈实现二叉树的先序遍历
*	思路:先序遍历的特点是遇到就输出,分别遍历其左右子树
*/
void traveByStack(BTNode * root){
	BTNode * stack[maxSize];
	BTNode * p;
	int top = -1;
	if(root != NULL){
		//根节点入栈
		stack[top] = root;
		while(top != -1){	//栈不空则循环
			//出栈
			p = stack[top--];
			printf("%d",p->data);
			if(p->rchild!=NULL){//右孩子不空,则右孩子入栈
				stack[++top] = p->rchild;
			}
			if(p->lchild!=NULL){//左孩子不空,则左孩子入栈,这里顺序跌倒的原因是因为在栈的输出中顺序是相反的
				stack[++top] = p->lchild;
			}
		}
	}
}

/**
*	用栈实现二叉树的中序遍历
*	思路:中序的实现根先序列有点不一样,不一样的地方在于,中序需要让左孩子先全进栈,直到没有左孩子就出栈并输出
*		出栈之后,将指针移向右孩子,那么就看他有没有右孩子,如果有右孩子,右孩子入栈,重复上面的操作
*		否则,就回滚,注意,回滚之后,循环条件又会判断是否还有左孩子,那么由于之前的指针是指向的p的右孩子,所以,这里
*		循环进入不了,直接判断是否栈空,栈不空就出栈,并让指针指向出栈元素的右孩子
*/
void traveByStack2(BTNode * root){
	BTNode * stack[maxSize];
	int top = -1;
	BTNode * p = root;
	//根结点入栈
	if(root != NULL){
		while(top!=-1||p!=NULL){	//这里加上||p!=null的原因是有可能p永远都是右孩子,那么在执行第一次循环就结束了,所以要加上
			while(p!= NULL){//如果左孩子不为空,那么左孩子就一直进栈
				stack[++top] = p;
				p=p->lchild;
			}
			//没有左孩子了就出栈,并让指针指向该结点的右孩子
			if(top != -1){
				printf("%d",stack[top]->data);
				p = stack[top--]->rchild;
			}
		}	
	}
}

int main(){
	printf("程序开始\n");
	BTNode * p;
	p = createTree();
	int width = getWidth2(p);
	printf("%d",width);
	return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值