DS树--带权路径和

Input

Copy

2
xA00tB00zC00D00
4 7 6 2 3
ab0C00D00
2 10 20
Output

Copy

34
40

二叉树的带权路径和APL等于叶子权值乘以根节点到叶子的分支数,然后求总和。

所以可以看出这道题需要求出每个叶子到根的高度就可以了,然后让权值与叶子到根的高度相乘。

求叶子节点到树高我们可以用dfs()

tips:千万不要给deep++,或者++deep,你就看这个地方,deep++了,假设递归左子树1->2,,那递归右子树的时候就是2->3了,因为你改变了,deep本身在这一层的时候

数组我存放的是按顺序存放的叶子节点,你们也可以用指针直接搞个结构体,然后到叶子的时候直接给叶子的高度赋值

这里我用前序找叶子,然后放入数组里。

tips:这里我为什么要用数组找叶子,明明结构体里面有权值和高度两个变量
1.本题输入特殊,虽然权值与叶子对应,但是是先全部输入完树的节点的,前序遍历建树。

2.如果不用数组存着叶子节点,我就需要构建到叶子的时候叶子输入权值,然后再找一次叶子高度计算和。
   即使我们先dfs找高度,到叶子的时候输入叶子权值计算和,这样子可能用的不习惯

3.所以还是分4步走,构建树,权值输入,求高度(中间两个可交换位置),计算和。

代码如下:

#include <iostream>
#include <queue>
using namespace std;
struct nodtree
{
    char value;///字符
    nodtree* left, * right;//左子节点指针,右子节点指针
    int length;///节点距离根节点的长度,就是高度
    int quanzhi;///字符的权值,就是叶子节点的权值
    nodtree()
    {
        left = NULL;
        right = NULL;
    }
    nodtree(char ch)
    {
        value = ch;
        left = NULL;
        right = NULL;
    }
};
queue<char>ss;///按顺序存取字符串然后依次取出字符
queue<nodtree*>p;用来构建树
//为什么喜欢用队列来当数组呢?
//个人习惯,因为你想想,我数组我需要指针tp++,但是我队列就每次取得都是第一个,然后把它pop就好了
//但是有个不好的就是这样子pop掉了,需要前面的数据就没了,看个人习惯和代码风格吧
nodtree* buildtree()
{
    if (ss.empty())///首先判断有没有节点给我建树
    {
        return NULL;
    }
    if (ss.front() == '0')///如果是权值为0的节点那就是空节点,不需要建立
    {
        ss.pop();
        return NULL;
    }
    nodtree* root;///这里就是常规建树了
    root = new nodtree(ss.front());
    ss.pop();
    root->left = buildtree();
    root->right = buildtree();
    return root;
}
void before(nodtree* root)///本人习惯会写一个先序遍历检查树是否建的对
{
    if (root == NULL)
    {
        return;
    }
    cout << root->value << " ";
    before(root->left);
    before(root->right);
}
vector<nodtree*>shuzu;
void qianxu(nodtree* root)///用前序遍历找叶子,因为节点也是前序遍历创建的,所以前序遍历找到的叶子跟字符串的叶子顺序是一样的
{
    ///例如字符串xA00tB00zC00D00
    ///可看出叶子是ABCD,所以前序遍历得到的叶子其实也是ABCD,顺序一样
    /// 这里是我最开始题没看好导致的处理可能稍微复杂了一点
    if (root == NULL)
    {
        return;
    }
    if (root->left == NULL && root->right == NULL)
    {
        shuzu.push_back(root);///这里是将叶子放进数组里
    }
    qianxu(root->left);
    qianxu(root->right);
}
int index=0;///这个是用来控制数组下标的,从0开始,存的是叶子,第一个叶子,index=0,第二个叶子,index=1;
void dfs(nodtree* root, int deep)
{
    if (root == NULL)///判断节点是不是空
    {
        return;
    }
    if (root->left == NULL && root->right == NULL)///判断是不是叶子节点
    {
        ///我很喜欢这样子判断叶子,主要是觉得这样子能保证代码正确性,判断是不是叶子节点

        shuzu[index]->length = deep;///叶子距离根的高度都存进数组里
        index++;
    }
    dfs(root->left, deep + 1);///左递归左子树
    dfs(root->right, deep + 1);///右递归右子树
}
int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        string ch;///输入字符串
        cin >> ch;
        int len = ch.length();///计算字符串长度
        for (int i = 0; i < len; i++)
        {
            ss.push(ch[i]);///将字符串中的每个字符取出
        }
        nodtree* root;///设立根节点
        root = buildtree();///建树
        qianxu(root);///用前序遍历找一遍叶子,将叶子存入数组里,这里后面就不用处理别的节点了
        int n;
        cin >> n;
        for (int i = 0; i < n; i++)
        {
            cin >> shuzu[i]->quanzhi;///输入每个叶子的权值
        }
        dfs(root, 0);///用dfs找一次高度,计算每次叶子到树根的高度
        int sum = 0;
        for (int i = 0; i < n; i++)///每次遍历叶子节点,将叶子节点的高度✖权值然后加到sum里
        {
            sum += shuzu[i]->quanzhi * shuzu[i]->length;
        }
        cout << sum << endl;
        index = 0;
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值