遍历算法应用
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
6.3.3 遍历算法应用
二叉树的遍历运算是一个重要的基础,对访问根结点操作的理解可包括各种各样的操作。从如下的应用实例中一是重点理解访问根结点操作的含义,二是注意对具体的实现问题是否需要考虑遍历的次序问题。
1.输出二叉树中的结点
遍历算法将走遍二叉树中的每一个结点,故输出二叉树中的结点并无次序要求,因此可用三种遍历中的任何一种算法完成,下面写出前序遍历顺序的实现算法。
void PreOrder(BiTree root)
/* 先序遍历输出二叉树结点, root为指向二叉树根结点的指针*/
{ if (root!=NULL)
{
printf (root ->data); /* 输出根结点*/
PreOrder(root ->LChild); /* 先序遍历左子树*/
PreOrder(root ->RChild); /* 先序遍历右子树*/ }
}
算法6.6 先序遍历输出二叉树中结点
思考:若要求统计二叉树中结点个数应如何去实现?
2.输出二叉树中的叶子结点
输出二叉树中的叶子结点要求与输出二叉树中的结点相比,是一个有条件的输出问题,条件是在遍历过程中走到每一个结点时须进行测试,看是否满足叶结点的条件。故只需改变算法 6.6 的黑体部分。
void PreOrder(BiTree root)
/* 先序遍历输出二叉树中叶子结点, root为指向二叉树根结点的指针*/
{ if (root!=NULL)
{
if (root ->LChild==NULL &&root ->RChild==NULL) printf (root ->data); /* 输出叶子结点*/
PreOrder(root ->LChild); /* 先序遍历左子树*/
PreOrder(root ->RChild); /* 先序遍历右子树*/
}
}
算法 6.7 先序遍历输出二叉树中叶结点
3.统计叶子结点数目
下面给出两种方法均可统计出二叉树叶子结点数目
/* LeafCount保存叶子结点的数目的全局变量,调用之前初始化值为0 */
void leaf(BiTree root)
{
if(root!=NULL)
{
leaf(root->LChild);
leaf(root->RChild);
if (root ->LChild==NULL && root
->RChild==NULL)
LeafCount++;
}
}
算法 6.8(a) 后序遍历统计叶子结点数目
/* 采用递归算法,如果是空树,返回0;如果只有一个结点,返回1;否则为左右子树的叶子结点数之和*/
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;
}
算法 6.8(b) 后序遍历统计叶子结点数目
思考:可否按中序统计二叉树中叶子结点个数?
4.建立二叉链表方式存储的二叉树
给定一棵二叉树,我们可以得到它的遍历序列;反过来,给定一棵二叉树的遍历序列,我们也可以创建相应的二叉链表。这里所说的遍历序列,是一种“扩展的遍历序列”。在通常的遍历序列中,均忽略空子树,而在扩展的遍历序列中,必须用特定的元素表示空子树。例如,图6.8 中二叉树的“扩展先序遍历序列”为: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));
}
}
算法6.9 用“扩展先序遍历序列”创建二叉链表5.求二叉树的高度
设函数表示二叉树bt的高度,则递归定义如下:
若bt为空,则高度为0
若bt非空,其高度应为其左右子树高度的最大值加1 二叉树的高度(深度)为二叉树中结点层次的最大值。即结点的层次自根结点起递推。设根结点为第1层的结点,所有h层的结点的左右孩子结点在h+1层。则可以通过先序遍历计算二叉树中的每个结点的层次,其中最大值即为二叉树的高度。给出后序遍历求二叉树的高度递归算法:
图6.12 二叉树高度示意图
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.10 后序遍历求二叉树的高度递归算法
思考:求二叉树的深度是否可用前序遍历的方式实现?若能,请写出实现算法,若不能,请说明原因。
6.按树状打印的二叉树
例:假设以二叉链表存储的二叉树中,每个结点所含数据元素均为单字母。要求实现如下图6.13。
图6.13树状打印的二叉树示意
这实际是一个二叉树的横向显示问题:因为二叉树的横向显示应是二叉树竖向显示的90。旋转,又由于二叉树的横向显示算法一定是中序遍历算法,所以把横向显示的二叉树算法改为先右子树再根结点再左子树的RDL结构,实现算法见6.11。
void PrintTree(TreeNode Boot,int nLayer) /* 按竖向树状打印的二叉树*/
{
if(Boot= =NULL) return;
PrintTree(Boot->pRight,nLayer+1);
for(int i=0;i printf(“”); printf(“%c\n”,Boot->ch);