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

被折叠的 条评论
为什么被折叠?



