You are on page 1of 4

第四题

组员:韦畅(1/3) 孙越凡(1/3) 周长城(1/3)

1 解题思路与数据结构设计说明:
(1)设计一个算法求二叉树 b 中度为 2 的结点个数:遍历二叉树 b 的每个节点,
如果一个节点的左右子树均不为空,则该节点的度为 2。使用递归方法来实现。
算法步骤:如果根节点为空,则返回 0。否则,判断当前节点是否为度为 2 的
节点,即判断当前节点的左右子树是否都不为空。如果是,则计数加 1。递归
调用该算法,对当前节点的左子树和右子树分别进行操作,并将结果相加。返
回计数值作为结果。
(2)设计一个算法求二叉树 b 中第 k 层的结点个数:同样使用递归方法来实现。
算法步骤:如果根节点为空或 k 小于等于 0,则返回 0。如果 k 等于 1,则表示
找到了目标层级,返回 1。递归调用该算法,对当前节点的左子树和右子树分
别进行操作,并将结果相加。返回左子树和右子树的结果之和作为结果。
(3)设计一个算法求二叉树 b 的宽度(采用递归方法):
算法思路:对于二叉树 b 的宽度,可以通过计算每一层的结点个数,并记录最
大值来得到。使用递归方法,首先获取二叉树的高度,然后对每一层进行遍历,
计算结点个数。算法步骤:如果根节点为空,则返回 0。否则,获取二叉树的
高度 h。初始化宽度变量 width 为 0。对于每一层 i(从 1 到 h),调用算法 2 来
获取第 i 层的结点个数,并将结果赋给变量 count。如果 count 大于 width,则更
新 width 的值为 count。返回 width 作为结果。
(4)设计一个算法求二叉树 b 的宽度(采用层次遍历方法):算法思路:使用
层次遍历的方法,逐层统计每一层的结点个数,并记录最大值来得到二叉树的
宽度。算法步骤:果根节点为空,则返回 0。初始化宽度变量 width 为 0。创建
一个空队列 queue,并将根节点入队。进入循环,直到队列为空:获取当前队
列的长度 size。如果 size 大于 width,则更新 width 的值为 size。遍历当前队列中
的每个元素 node:如果 node 的左子节点不为空,则将其左子节点入队。如果
node 的右子节点不为空,则将其右子节点入队。出队 size 次,即将当前层的所
有节点出队。返回 width 作为结果。以上是对四个问题的解题思路说明。

2 算法源代码:
以下是用 C 语言实现二叉树数据结构的代码示例:
#include <stdio.h>
#include <stdlib.h>

// 定义二叉树节点结构
typedef struct TreeNode {
int data;
struct TreeNode* left;
struct TreeNode* right;
} TreeNode;
// 创建新的二叉树节点
TreeNode* createNode(int data) {
TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode));
if (newNode == NULL) {
printf("Memory allocation failed.\n");
exit(1);
}
newNode->data = data;
newNode->left = newNode->right = NULL;
return newNode;
}

// 1.统计度为 2 的节点个数
int countNodesWithDegreeTwo(TreeNode* root) {
if (root == NULL) {
return 0;
}//根为空则返回 0
int count = 0;
if (root->left != NULL && root->right != NULL) {
count++;
}
count += countNodesWithDegreeTwo(root->left);
count += countNodesWithDegreeTwo(root->right);
return count;
}

// 2.统计第 k 层的节点个数
int countNodesAtLevelK(TreeNode* root, int k) {
if (root == NULL || k <= 0) {
return 0;
}//根为空或 k 小于等于零则返回 0
if (k == 1) {
return 1;
}
Int count= countNodesAtLevelK(root->left,k-1) + countNodesAtLevelK(root->right, k
- 1);
return count;
}

// 3.递归方法求二叉树的宽度
int getTreeWidthRecursive(TreeNode* root) {
if (root == NULL) {
return 0;
}
int height = getTreeHeight(root);//得到二叉树的高度
int width = 0;
for (int i = 1; i <= height; i++) {
int levelWidth = countNodesAtLevelK(root, i);
if (levelWidth > width) {
width = levelWidth;
}//如果 count 大于 width,则更新 width 的值为 count。
}
return width;
}

// 辅助方法:计算二叉树的高度
int getTreeHeight(TreeNode* root) {
if (root == NULL) {
return 0;
}
int leftHeight = getTreeHeight(root->left);
int rightHeight = getTreeHeight(root->right);
return (leftHeight > rightHeight) ? (leftHeight + 1) : (rightHeight + 1);
}

// 4,层次遍历方法求二叉树的宽度(使用队列)
int getTreeWidthBFS(TreeNode* root) {
if (root == NULL) {
return 0;
}
TreeNode** queue = (TreeNode**)malloc(sizeof(TreeNode*) * 1000); // 假设最多
存储 1000 个节点
int front = 0, rear = 0;
queue[rear++] = root;
int width = 0;
while (front < rear) {
int levelNode

3 对实现的算法进行基本的算法效率(时间复杂度)分析,
可否进一步优化,如果可以,请简要阐述改进与优化思路:

对实现的算法进行基本的时间复杂度分析:
统计度为 2 的节点个数:
时间复杂度:O(n),其中 n 是二叉树中的节点数。需要遍历二叉树的每个节点,
判断其左右子树是否存在。
统计第 k 层的节点个数:
时间复杂度:O(n),其中 n 是二叉树中的节点数。需要遍历二叉树的每个节点,
递归查询第 k 层的节点个数。
递归方法求二叉树的宽度:
时间复杂度:O(n*h),其中 n 是二叉树中的节点数,h 是二叉树的高度。需要计
算每一层的节点个数,而计算每一层的时间复杂度为 O(n),总共有 h 层。
层次遍历方法求二叉树的宽度(使用队列):
时间复杂度:O(n),其中 n 是二叉树中的节点数。需要遍历二叉树的每个节点,
并将其入队和出队。
进一步优化的思路:
统计度为 2 的节点个数:
可以使用迭代的方式,采用后序遍历或中序遍历来遍历二叉树的节点。在遍历
过程中,记录度为 2 的节点个数。
统计第 k 层的节点个数:
可以使用迭代的方式,采用层次遍历来遍历二叉树的节点。在遍历过程中,记
录每一层的节点个数,直到达到目标层级。
递归方法求二叉树的宽度:
可以通过修改递归方法,将计算每一层的节点个数和二叉树高度的操作合并在
一起,避免重复遍历。
层次遍历方法求二叉树的宽度(使用队列):
当前实现已经是较优的解法。可以考虑使用循环队列来替代动态分配内存的做
法,提高空间利用效率。

You might also like