二叉树的遍历,深度求解以及竖向打印详析

二叉树是每个节点最多有两个子树的有序树。二叉树常被用于实现二叉查找树二叉堆。值得注意的是,二叉树不是树的特殊情形。在图论中,二叉树是一个连通的无环图,并且每一个顶点的度不大于2。有根二叉树还要满足根结点的度不大于2。有了根结点后,每个顶点定义了唯一的根结点,和最多2个子结点。然而,没有足够的信息来区分左结点和右结点。二叉树详细请看本文:二叉树


所谓遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问。访问结点所做的操作依赖于具体的应用问 题。 遍历是二叉树上最重要的运算之一,是二叉树上进行其它运算之基础。

代码如下:

#include<iostream>
#include<cstdlib>
using namespace std;
typedef char ElemType;
typedef struct Node
{
	ElemType data;
	struct Node* LChild;
	struct Node* RChild;
}BiTNode,*BiTree;
int LeafCount;
int Depth;

void Visit(ElemType T)//用于遍历的输出
{
	cout<<T;
}

//1.建立二叉树
void CreateBiTree(BiTree *bt)
{
	char ch; 
	ch = getchar();
	if(ch=='.') *bt=NULL;
	else 
	{
		*bt=(BiTree)malloc(sizeof(BiTNode)); //生成一个新结点
		(*bt)->data=ch;
		CreateBiTree(&((*bt)->LChild)); //生成左子树
		CreateBiTree(&((*bt)->RChild)); //生成右子树
	}
}

//2.二叉树遍历

void  PreOrder(BiTree root) 
/*先序遍历二叉树, root为指向二叉树(或某一子树)根结点的指针*/
{
	if (root!=NULL)
	{
		Visit(root ->data);  /*访问根结点*/
		PreOrder(root ->LChild);  /*先序遍历左子树*/
		PreOrder(root ->RChild);  /*先序遍历右子树*/
	}
	else
		cout<<".";
}
void  InOrder(BiTree root)  
/*中序遍历二叉树, root为指向二叉树(或某一子树)根结点的指针*/
{
	if (root!=NULL)
	{
		InOrder(root ->LChild);   /*中序遍历左子树*/
		Visit(root ->data);        /*访问根结点*/
		InOrder(root ->RChild);   /*中序遍历右子树*/
	}
	else
		cout<<".";
}
void  PostOrder(BiTree root)  
/* 后序遍历二叉树,root为指向二叉树(或某一子树)根结点的指针*/
{
	if(root!=NULL)
	{
		PostOrder(root ->LChild); /*后序遍历左子树*/
		PostOrder(root ->RChild); /*后序遍历右子树*/
		Visit(root ->data);       /*访问根结点*/
	}
	else
		cout<<".";
}



//3.输出二叉树上的“叶子”节点(三种方法,只写了先序,中后请参考前面的2.二叉树遍历)

void  leafPreOrder(BiTree root) 
/*先序遍历二叉树, root为指向二叉树根结点的指针*/
{
	if (root!=NULL)
	{
		if (root ->LChild==NULL && root ->RChild==NULL)
			Visit(root->data);  /*输出叶子结点*/
		PreOrder(root ->LChild);  /*先序遍历左子树*/
		PreOrder(root ->RChild);  /*先序遍历右子树*/
	}
}

//4.统计叶子节点数目(两个方法)

/* LeafCount保存叶子结点的数目的全局变量,调用之前初始化值为0 */
void leaf_a(BiTree root)//统计叶子节点数目法1
{
	if(root!=NULL)
	{
		leaf_a(root->LChild);
		leaf_a(root->RChild);
		if (root ->LChild==NULL && root ->RChild==NULL)
			LeafCount++;
	}
}

int leaf_b(BiTree root)//统计叶子节点数目法2
{
	int LeafCount2;
	if(root==NULL)	
		LeafCount2 =0;
	else 
		if((root->LChild==NULL)&&(root->RChild==NULL))
			LeafCount2 =1;
		else 
			LeafCount2 =leaf_b(root->LChild)+leaf_b(root->RChild);
		/* 叶子数为左右子树的叶子数目之和 */
		return LeafCount2;
}

//6.后序遍历求二叉树的高度递归算法

int PostTreeDepth(BiTree bt)   
{
	int hl,hr,max;
	if(bt!=NULL)
	{
		hl=PostTreeDepth(bt->LChild);  /* 求左子树的深度 */
		hr=PostTreeDepth(bt->RChild);  /* 求右子树的深度 */
		max=hl>hr?hl:hr;              /* 得到左、右子树深度较大者*/
		return(max+1);               /* 返回树的深度 */
	}
	else return(0);             /* 如果是空树,则返回0 */
}

//6.前序遍历求二叉树的高度递归算法

void PreTreeDepth(BiTree bt, int h)
/* 前序遍历求二叉树bt高度的递归算法,h为bt指向结点所在层次,初值为1*/
/*depth为当前求得的最大层次,为全局变量,调用前初值为0 */
{
	if(bt!=NULL)
	{
		if(h>Depth)
			Depth = h;     /*如果该结点层次值大于depth,更新depth的值*/
		PreTreeDepth(bt->LChild, h+1);  /* 遍历左子树 */
		PreTreeDepth(bt->RChild, h+1);  /* 遍历右子树 */
	}
}

//7.“竖向”打印二叉树

void PrintTree(BiTree bt,int nLayer)  /* 按竖向树状打印的二叉树 */
{
	if(bt == NULL) return;
	PrintTree(bt->RChild,nLayer+1);
	for(int i=0;i<nLayer;i++)
		printf("  ");
	printf("%c\n",bt->data);
	PrintTree(bt->LChild,nLayer+1);
}





int main()
{
	LeafCount =0;Depth=0;
	BiTree T=NULL;
	cout<<"请以先序输出的形式输入二叉树构造二叉链表:"<<endl;
	CreateBiTree(&T);
	cout<<"先序遍历二叉树为:"<<endl;
	PreOrder(T);
	cout<<endl<<"中序遍历二叉树为:"<<endl;
	InOrder(T); 
	cout<<endl<<"后序遍历二叉树为:"<<endl;
	PostOrder(T);
	cout<<endl<<"先序输出二叉树叶子节点为:"<<endl;
	leafPreOrder(T);
		cout<<endl<<"叶子节点数目为:"<<endl;
	leaf_a(T);
	cout<<endl<<"方法一显示共有"<<LeafCount<<"个叶子节点"<<endl;

	cout<<endl<<"方法二显示共有"<<leaf_b(T)<<"个叶子节点"<<endl;
	
	cout<<endl<<"后序遍历求二叉树的高度为"<<PostTreeDepth(T)<<endl;
	PreTreeDepth(T,1);
	cout<<endl<<"前序遍历求二叉树的高度为"<<Depth<<endl;
	
	cout<<endl<<"竖状打印二叉树为:"<<endl;
	PrintTree(T,1);
	return 0;
}

附带二叉树遍历的非递归算法:

/* 中后非递归遍历二叉树,作为遍历方法的参考*/

//8.中序遍历二叉树非递归算法(三个)

/*算法a*/
void inorder(BiTree root);
{
	int top=0; p=bt;
L1: if (p!=NULL)       /* 遍历左子树 */       
	{ 
		top=top+2;    
		if(top>m) return;       /*栈满溢出处理*/
		s[top-1]=p;            /* 本层参数进栈 */    
		s[top]=L2;             /* 返回地址进栈 */
		p=p->LChild;           /* 给下层参数赋值 */
		goto L1;               /* 转向开始 */
L2:  Visit(p->data);     /* 访问根 */
     top=top+2;
     if(top>m) return;       /*栈满溢出处理*/;
     s[top-1]=p;            /* 遍历右子树 */
     s[top]=L3;
     p=p->RChild;
     goto L1;
	}
L3: if(top!=0)      
	{ 
		addr=s[top];
		p=s[top-1];            /* 取出返回地址 */
		top=top-2;             /* 退出本层参数 */
		goto addr;
	}
}

/*算法b*/
void inorder(BiTree root)   /* 中序遍历二叉树,root为二叉树的根结点 */
{
	int top=0; 
	BiTree p;
	BiTree s[Stack_Size];
	int m;
	m = Stack_Size-1;
	p = root;
	do
	{
		while(p!=NULL)
		{ 
			if (top>m) return;
			top=top+1;  
			s[top]=p;
			p=p->LChild;
		};  /* 遍历左子树 */
		if(top!=0)
		{ 
			p=s[top];
			top=top-1;
			Visit(p->data);  /* 访问根结点 */
			p=p->RChild;  /* 遍历右子树 */
		}   
	}
	while(p!=NULL || top!=0);
}


/*算法c*/
void  InOrder(BiTree root) /* 中序遍历二叉树的非递归算法 */
{
	SeqStack S;
	BiTree p;
	InitStack (&S);
	p=root;
	while(p!=NULL || !IsEmpty(&S))
	{ 
		if (p!=NULL)  /* 根指针进栈,遍历左子树 */
		{
			Push(&S,p);
			p=p->LChild;
		}
		else
		{  /*根指针退栈,访问根结点,遍历右子树*/
			Pop(&S,&p); 
			Visit(p->data);  
			p=p->RChild;
		}
	}
}


//9.后序遍历二叉树的非递归算法

void PostOrder(BiTree root)
{
	BiTNode *p,*q;
	BiTNode **s;
	int top=0;
	q=NULL;
	p=root;
	s=(BiTNode**)malloc(sizeof(BiTNode*)*NUM);
	/* NUM为预定义的常数 */
	while(p!=NULL || top!=0)
	{
		while(p!=NULL)
		{
			top++; 
			s[top]=p; 
			p=p->LChild; 
		}  /*遍历左子树*/
		if(top>0) 
		{	
			p=s[top];
			if((p->RChild==NULL) ||(p->RChild==q))	/* 无右孩子,或右孩子已遍历过 */
			{
				visit(p->data);        /* 访问根结点*/
				q=p;            	/* 保存到q,为下一次已处理结点前驱 */
				top--;
				p=NULL;
			} 
			else	
				p=p->RChild;
		}
	}
	free(s);
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值