输出二叉树中的结点 |
【算法思想】
输出二叉树中的结点并无次序要求,因此可用三种遍历算法中的任何一种完成,只需将访问操作具体变为输出操作即可。下面给出采用先序遍历实现的算法。
【算法描述】
void PreOrder(BiTree root)
/* 先序遍历输出二叉树结点, root 为指向二叉树根结点的指针 */
{
if (root != NULL)
{
printf("%c", root->data); /* 输出根结点 */
PreOrder(root->LChild); /* 先序遍历左子树 */
PreOrder(root->RChild); /* 先序遍历右子树 */
}
}
输出二叉树中的叶子结点 |
【算法思想】
输出二叉树中的叶子结点与输出二叉树中的结点相比,它是一个有条件的输出问题,即在遍历过程中走到每一个结点时需进行测试,看是否满足叶子结点的条件。
【算法描述】
void PreOrder(BiTree root)
/* 先序遍历输出二叉树中的叶子结点 , root 为指向二叉树根结点的指针 */
{
if (root != NULL)
{
if (root->LChild == NULL && root->RChild == NULL)
printf("%c", root->data); /* 输出叶子结点 */
PreOrder(root->LChild); /* 先序遍历左子树 */
PreOrder(root->RChild); /* 先序遍历右子树 */
}
}
统计叶子结点数目 |
- 方法一
【算法思想】
统计二叉树中的叶子结点数目并无次序要求,因此可用三种遍历算法中的任何一种完成,只需将访问操作具体变为判断是否为叶子结点及统计操作即可。
【算法描述】
/* 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;
}
建立二叉链表方式存储的二叉树 |
- 给定一棵二叉树,我们可以得到它的遍历序列;
- 反过来,给定一棵二叉树的遍历序列,我们也可以创建相应的二叉链表。
这里所说的遍历序列是一种“扩展的遍历序列”。在通常的遍历序列中,均忽略空子树,而在扩展的遍历序列中,必须用特定的元素表示空子树。例如,图中二叉树的“扩展先序遍历序列”为: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));
}
}
求二叉树的高度 |
二叉树的高度(深度)为二叉树中结点层次的最大值,也可视为其左、右子树高度的最大值加 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); /* 遍历右子树 */
}
}
按树状打印二叉树 |
【算法思想】
(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);
}