树——统计完全二叉树的节点数目

题目要求

实现时间复杂度低于O(N)的解法。

遍历整棵树求节点个数时间复杂度为O(N)。


这里利用了完全二叉树的性质:通过比较左右子树的最左结点的高度来看哪边是满的,然后递归计算。

1.首先遍历左子树最左节点找到二叉树的层数h(头节点在第1层);

2.遍历右子树最左节点看是否在第h层,若在第h层,说明左子树该完全二叉树左子树是满的;否则其右子树是满的,不过叶子节点都在第h-1层;

3.递归计算

//计算左子树最左节点的层数
public int mostLeftLevel(TreeNode root)
{
	if(root == null)
		return 0;
	return mostLeftLevel(root.left)+1;
}
//递归计算完全二叉树节点个数
public int countNodes(TreeNode root)
{
	if(root == null)
		return 0;
	int left=mostLeftLevel(root.left);
	int right=mostLeftLevel(root.right);
	if(left == right)//左子树是满的
		return (1<<left)+countNodes(root.right);
	else //right < left 右子树是满的,且层数少一层
		return (1<<right)+countNodes(root.left);
}


### 叶子结点的统计方法 在一个二叉中,叶子结点是指没有左孩子也没有右孩子的结点。为了统计叶子结点的数量,可以采用递归的方式实现。具体逻辑如下: 当当前结点为空时返回 `0`;如果当前结点既无左孩子也无右孩子,则该结点是一个叶子结点,此时返回 `1` 并加上其左右子中的叶子结点数量[^5]。 以下是用于统计叶子结点个数的代码示例: ```c int LeafCount(BiTree T) { if (!T) return 0; if (!(T->lchild) && !(T->rchild)) return 1; // 当前结点为叶子结点 return LeafCount(T->lchild) + LeafCount(T->rchild); } ``` --- ### 输出所有叶子结点的方法 要按某种顺序输出所有的叶子结点,可以选择不同的遍历方式来访问这些结点。通常情况下会使用 **先序遍历** 或者其他形式的深度优先搜索(DFS)。对于每棵子,判断当前结点是否为叶子结点,如果是就将其打印出来[^4]。 下面是基于先序遍历输出叶子结点的代码实现: ```c void PreorderPrintLeaves(BiTree T) { if (!T) return; if (!(T->lchild) && !(T->rchild)) { // 判断是否为叶子结点 printf(" %c", T->data); // 打印叶子结点的数据部分 } PreorderPrintLeaves(T->lchild); // 遍历左子 PreorderPrintLeaves(T->rchild); // 遍历右子 } ``` 上述代码通过递归调用实现了对整个二叉的扫描,在遇到叶子结点时执行相应的操作(这里是打印)。 --- ### 结合功能的完整程序框架 下面提供了一个完整的 C 程序框架,其中包含了两个主要的功能模块——统计叶子结点数目以及按照先序遍历输出所有叶子结点的内容。 ```c #include <stdio.h> #include <stdlib.h> typedef struct TreeNode { char data; struct TreeNode *lchild, *rchild; } BiTreeNode, *BiTree; // 功能一:计算叶子结点个数 int LeafCount(BiTree T) { if (!T) return 0; if (!(T->lchild) && !(T->rchild)) return 1; return LeafCount(T->lchild) + LeafCount(T->rchild); } // 功能二:先序遍历输出叶子结点 void PreorderPrintLeaves(BiTree T) { if (!T) return; if (!(T->lchild) && !(T->rchild)) { printf(" %c", T->data); } PreorderPrintLeaves(T->lchild); PreorderPrintLeaves(T->rchild); } // 测试函数 int main() { // 假设已经构建好了一颗二叉 root BiTree root = NULL; // 初始化根节点 // 构建测试用的简单二叉... int leafNum = LeafCount(root); printf("\nLeaf count is: %d\n", leafNum); printf("Leaves in preorder:"); PreorderPrintLeaves(root); printf("\n"); return 0; } ``` 此代码片段展示了如何定义基本的二叉结构体类型,并提供了两种核心算法的具体实现。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值