编程题-二叉树的层平均值

题目:

给定一个非空二叉树的根节点 root , 以数组的形式返回每一层节点的平均值。与实际答案相差 10^{-5} 以内的答案可以被接受。

解题一(广度优先搜索):

从根节点开始搜索,每一轮遍历同一层的全部节点,计算该层的节点数以及该层的节点值之和,然后计算该层的平均值。使用队列存储待访问节点,只要确保在每一轮遍历时,队列中的节点是同一层的全部节点即可。

初始时将根节点加入到队列中,然后每一轮遍历时,将队列中的节点全部取出,计算这些节点的数量以及它们的节点值之和,并计算这些节点的平均值,然后将这些节点的全部非空子节点加入队列,重复上述操作直到队列为空,遍历结束。如下为笔者的代码:

class Solution {
public:
    vector<double> averageOfLevels(TreeNode* root) {
        queue<TreeNode*> Queue1;
        queue<TreeNode*> Queue2;
        vector<double> result;
        if(root==nullptr){
            return result;
        }
        Queue1.push(root);
        double sum=0;
        int a=0;
        while(!Queue1.empty() or !Queue2.empty()){
            TreeNode* root1 = Queue1.front();
            if(root1->left!=nullptr){
                Queue2.push(root1->left);
            }
            if(root1->right!=nullptr){
                Queue2.push(root1->right);
            }
            sum+=root1->val;
            a+=1;
            Queue1.pop();          
            if(Queue1.empty()){
                result.push_back((sum/a));
                sum=0;
                a=0;
                Queue1 = Queue2;
                while (!Queue2.empty()) {
                    Queue2.pop();
                }
            }
        }
        return result;
    }
};

解法二(深度优先搜索):

使用深度优先搜索计算二叉树的层平均值,需要维护两个数组,counts用于存储二叉树的每一层的节点数,sums用于存储二叉树的每一层的节点值之和。搜索过程中需要记录当前节点所在的层,如果访问到的节点在第i层,则将counts[i]的值加1,并将该节点的值添加到sum[i]中。

在遍历结束后,第i层的平均值即为sums[i]/counts[i]。如下代码为:

class Solution {
public:
    vector<double> averageOfLevels(TreeNode* root) {
        
        auto counts = vector<int>();
        auto sums = vector<double>();
        //初始时,root为根节点,0为根节点的层数
        dfs(root, 0, counts, sums);
        auto averages = vector<double>();
        int size = sums.size();
        //全部遍历完之后,再统一依次计算每一层的所有元素平均值
        for (int i = 0; i < size; i++) {
            averages.push_back(sums[i] / counts[i]);
        }
        return averages;
    }
    //深度优先搜索遍历二叉树的所有节点,嵌套函数的方法,dfs()函数中仍有dfs()函数,进行嵌套,counts和sums作为引用值,在执行嵌套函数中进行重复修改和赋值。
    void dfs(TreeNode* root, int level, vector<int> &counts, vector<double> &sums)                             
    {    
        if (root == nullptr) {
            return;
        }
        if (level < sums.size()) {
            sums[level] += root->val;
            counts[level] += 1;
        } else {
            sums.push_back(1.0 * root->val);
            counts.push_back(1);
        }
        dfs(root->left, level + 1, counts, sums);
        dfs(root->right, level + 1, counts, sums);
    }
};

笔者小记:vector(double) result;作为容器的定义,可以充当一维数组存储的数据结构,例如result[0],result[1]更实时灵活的处理每层树的平均值。dfs()函数内嵌套函数dsf()的利用可以反复的调用,类似与“递归”相同的操作,以及&counts, &sums引用的利用也可以在遍历树的过程中实时的修改和赋值。在后续代码编写中,可以更好的利用这些操作更快速的写出简洁漂亮的代码。

编程题实训中,树和二叉树有诸多综合应用场景。从数据存储与检索方面来看,二叉搜索树(BST)是一种重要的应用。它是一种特殊的二叉树,对于树中的每个节点,其左子树中的所有节点值都小于该节点值,右子树中的所有节点值都大于该节点值。这种特性使得在二叉搜索树中进行查找、插入和删除操作的平均时间复杂度为 $O(log n)$。以下是二叉搜索树插入操作的示例代码: ```python class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right def insert(root, val): if root is None: return TreeNode(val) if val < root.val: root.left = insert(root.left, val) else: root.right = insert(root.right, val) return root ``` 在文件系统的目录结构表示上,树结构也有广泛应用。文件系统的目录可以看作是树的节点,文件可以看作是叶子节点。通过树结构可以方便地管理文件和目录的次关系,实现文件的查找、创建和删除等操作。 在表达式求值方面,表达式树是一种常用的二叉树应用。表达式树的叶子节点是操作数,非叶子节点是运算符。通过对表达式树进行遍历(如后序遍历),可以方便地计算表达式的值。以下是表达式树后序遍历求值的示例代码: ```python class TreeNode: def __init__(self, val): self.val = val self.left = None self.right = None def evaluate_expression_tree(root): if root is None: return 0 if root.left is None and root.right is None: return int(root.val) left_val = evaluate_expression_tree(root.left) right_val = evaluate_expression_tree(root.right) if root.val == '+': return left_val + right_val elif root.val == '-': return left_val - right_val elif root.val == '*': return left_val * right_val elif root.val == '/': return left_val / right_val ``` 在哈夫曼编码中,哈夫曼树是一种特殊的二叉树。它通过构建一棵带权路径长度(WPL)最短的二叉树,实现对数据的压缩编码。如引用中给出了计算二叉树WPL的代码,这在哈夫曼树的构建中是一个重要的步骤。以下是计算二叉树WPL的代码示例(参考引用中的代码逻辑): ```cpp #include<iostream> using namespace std; typedef struct BiTNode { int weight; struct BiTNode *left, *right; } BiTNode, *BiTree; void CreateBiTree(BiTree &T) { int ch; cin >> ch; if (ch == 0) T = NULL; else { T = new BiTNode; T->weight = ch; CreateBiTree(T->left); CreateBiTree(T->right); } } int WPL(BiTree &T, int d) { int wpl = 0; if (T != NULL) { if (T->left == NULL && T->right == NULL) wpl += d * T->weight; wpl += WPL(T->left, d + 1); wpl += WPL(T->right, d + 1); } return wpl; } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值