6.4遍历算法应用

6.4遍历算法应用

二叉树的遍历运算是一个重要的基础。一是重点理解访问根结点操作的含义,二 是注意对具体的实现时是否需要考虑遍历的次序选择要求

1.输出二叉树中的结点

算法思想
输出二叉树中的结点并无次序要求,因此可用三种遍历算法中的任何一种 完成,只需将访问操作具体变为输出操作即可。
下面给出采用先序遍历实现的算法。
算法描述

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

2.输出二叉树中的叶子结点

算法思想
输出二叉树中的叶子结点与输出二叉树中的结点相比,它是一个有条件的输出问题,即在遍历过程中走到每一个结点时需进行测试,看是否满足叶子结 点的条件。
算法描述

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

3.统计叶子结点数目

方法一

算法思想
统计二叉树中的叶子结点数目并无次序要求,因此可用三种遍历算法中的 任何一种完成,只需将访问操作具体变为判断是否为叶子结点及统计操作即可。
下面给出采用后序遍历实现的算法。
算法描述

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

算法思想
给出求叶子点数目的递归定义:
1)如果是空树,返回 0;
2)如果只有一个结点,返回 1;
3)否则为左右子树的叶子结点数之和。

算法描述

int leaf(BiTree root) 
{ 
	int LeafCount;  
	if(root==NULL)    
		LeafCount =0;  
	else if ((root->LChild==NULL)&&(root->RChild==NULL))       
		LeafCount =1;  
	else  /* 叶子数为左右子树的叶子数目之和 */ 
		LeafCount =leaf(root->LChild)+leaf(root->RChild);   
	return  LeafCount; 
} 

4.建立二叉链表方式存储的二叉树

给定一棵二叉树,我们可以得到它的遍历序列;反过来,给定一棵二叉树的 遍历序列,我们也可以创建相应的二叉链表。这里所说的遍历序列是一种“扩展 的遍历序列”。在通常的遍历序列中,均忽略空子树,而 在扩展的遍历序列中,必须用特定的元素表示空子树。

例如,左图中二叉树的“扩展先序遍历序列”为: AB.DF…G…C.E.H…。
其中用小圆点表示空子树。
利用“扩展先序遍历序列” 创建二叉链表的算法如下:在这里插入图片描述
算法思想
采用类似先序遍历的递归算法,首先读入当前根结点 的数据,如果是“.”则将当前树根置为空,否则申请一个新结点,存入当前根 结点的数据,分别用当前根结点的左子域和右子域进行递归调用,创建左、右子树。
算法描述

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));     
	} 
} 

5.求二叉树的高度

二叉树的高度(深度)为二叉树中结点层次的最大值,也可视为其左、右子 树高度的最大值加 1。
算法思想
二叉树 bt 高度的递归定义如下:

  • 若 bt 为空,则高度为 0。
  • 若 bt 非空,其高度应为其左、右子树高度的最大值加 1,如下图所示。
    在这里插入图片描述

算法描述

int PostTreeDepth(BiTree bt)   /* 后序遍历求二叉树 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 */ } 

求二叉树的高度是也可用前序遍历的方式实现

算法思想
二叉树的高度(深度)为二叉树中结点层次的最大值。设根结点为第一层的 结点,所有 h 层的结点的左、右孩子结点在 h+1 层。故可以通过遍历计算二叉树 中的每个结点的层次,其中最大值即为二叉树的高度。
算法描述

void PreTreeDepth(BiTeee 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);  /* 遍历右子树 */   
	} 
} 

6.按树状打印二叉树

假设以二叉链表存储的二叉树中,每个结点所含数据元素均为单字母。 要求实现二叉树的横向显示问题,如下图所示打印结果。
在这里插入图片描述

算法思想
(1)二叉树的横向显示应是二叉树竖向显示的 90。旋转。分析上图示可知, 这种树形打印格式要求先打印右子树,再打印根,最后打印左子树,按由上而下顺序看,其输出的结点序列为:CFEADB,这恰为逆中序顺序。解决二叉树的横 向显示问题采用“逆中序”遍历框架,所以横向显示二叉树算法为先右子树、再 根结点、再左子树的 RDL结构。

(2)在这种输出格式中,结点的左、右位置与结点的层深有关,故算法中 设置了一个表示当前根结点层深的参数,以控制输出结点的左、右位置,每当递归进层时层深参数加 1。这些操作应在访问根结点时实现。
算法描述

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); 
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值