计算二叉树带权路径和(WPL)

  • 前言
    二叉树的带权路径和,指的是二叉树的所有叶子节点的权值 * 其深度 之和。
    本次因为是完整的程序,所以包含
    1)输入前序、中序序列 创建二叉树
    2)层序遍历打印出二叉树
    3)计算WPL

  • 数据结构定义
    typedef struct Node* List;
    typedef struct Node{
    List l, r;
    int data;
    };

  • 创建二叉树
    1、变量说明
    int n; // n是二叉树的节点数
    vector preorder(9), inorder(9); //前序和中序
    List root = new Node(); //root
    unordered_map<int, int> mp;
    因为我们用前序和中序确定二叉树,思想是递归的(因为树是递归定义的),首先是通过前序,确定根部,然后再确定左子树和右子树节点数,以此递归。
    此无序map,便是用于将前序根部,在中序中确定位置。其key 是 权值;value是位置,也即下标。

    2、思路
    如上文所说,其创建是递归创建的。

List createTree(int pre_l, int pre_r, int in_l, int in_r){
    
    
    if (pre_l > pre_r) {
    
    
        return NULL;
    }
    // 定位根节点
    int pre_root = pre_l;
    int in_root = mp[preorder[pre_root]];

    List root = new Node();
    root->weight = preorder[pre_root];
    // cout<<"This root weight = "<<root->weight<<endl;

    int len_left = in_root - in_l;
    root->left = createTree(pre_l + 1, pre_l + len_left, in_l, in_root - 1);
    root->right = createTree(pre_l + 1 + len_left, pre_r, in_root + 1, in_r);
    return root;
}

如上代码所示,
在构建左子树时的四个参数如下图
在这里插入图片描述

在构建右子树时的四个参数如下图
在这里插入图片描述

如此递归创建便好。

  • 层序遍历打印
    一个简单的bfs即可。
void printT(List root){
    
    
    queue<List> q;
    q.push(root);
    int d = 0;
    while (!q.empty()) {
    
    
        List tmp = NULL;
        int num = q.size();
        for(int i = 0;i < h - d;i++) cout<<" ";
        for(int i = 0;i< num;i++){
    
    
            tmp = q.front(); q.pop();
            cout<<tmp->data<<" ";
            if(tmp->l != NULL) q.push(tmp->l);
            if(tmp->r != NULL) q.push(tmp->r);
        }
        d ++;
        cout<<endl;
    }
}
  • 计算WPL
    dfs即可,传参deepth,更新深度。每次遍历到叶子节点,也即左右子树都为空,便将ans加上权值 * 深度。
void dfs(List root,int deepth){
    
    
    if (root->left == NULL && root->right == NULL) {
    
    
        ans += deepth * root->weight;
        h = max(h, deepth);
    }
    if (root->left != NULL) {
    
    
        dfs(root->left, deepth + 1);
    }
    if (root->right != NULL) {
    
    
        dfs(root->right, deepth + 1);
    }
}
  • 完整代码:
#include "bits/stdc++.h"
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define pb push_back
typedef long long ll;
const int maxn = 1e4;
const int INF = INT_MAX;
const double EPS = 10;
#define _DEBUG

typedef struct Node* List;
typedef struct Node{
    
    
    List left, right;
    int weight;
};

int n;
// 前序和中序
vector<int> preorder, inorder;
// key 是 中序的值  value是位置
unordered_map<int, int> mp;
List root = NULL;
int ans = 0;
int h = 0;

void init(){
    
    
    int num;
    cin>>n;
    for(int i = 0;i < n; i++){
    
    
        cin>>num;
        preorder.pb(num);
    }
    for(int i = 0;i < n; i++){
    
    
        cin>>num;
        inorder.pb(num);
        mp[num] = i;
    }
}
List createTree(int pre_l, int pre_r, int in_l, int in_r){
    
    
    if (pre_l > pre_r) {
    
    
        return NULL;
    }
    // 定位根节点
    int pre_root = pre_l;
    int in_root = mp[preorder[pre_root]];

    List root = new Node();
    root->weight = preorder[pre_root];
    // cout<<"This root weight = "<<root->weight<<endl;

    int len_left = in_root - in_l;
    root->left = createTree(pre_l + 1, pre_l + len_left, in_l, in_root - 1);
    root->right = createTree(pre_l + 1 + len_left, pre_r, in_root + 1, in_r);
    return root;
}
void dfs(List root,int deepth){
    
    
    if (root->left == NULL && root->right == NULL) {
    
    
        ans += deepth * root->weight;
        h = max(h, deepth);
    }
    if (root->left != NULL) {
    
    
        dfs(root->left, deepth + 1);
    }
    if (root->right != NULL) {
    
    
        dfs(root->right, deepth + 1);
    }
}
void printT(List root){
    
    
    int d = 0;
    queue<List> q;
    q.push(root);
    while (!q.empty()) {
    
    
        for(int i = 0;i < h - d;i++) cout<<" ";
        int len = q.size();
        for (int i = 0; i < len; i++) {
    
    
            List tmp = q.front();
            cout<<tmp->weight<<" ";
            q.pop();
            if(tmp->left != NULL) q.push(tmp->left);
            if(tmp->right != NULL) q.push(tmp->right);
        }
        cout<<endl;
        d ++;
    }
}
int main(){
    
    
#ifdef _DEBUG
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif
    ios::sync_with_stdio(0);
    cin.tie(0);

    init();
    root = createTree(0, n-1, 0, n-1);

    dfs(root, 0);
    cout<<"The deep is "<<h<<endl<<endl;

    cout<<"The tree is :"<<endl;
    printT(root);

    cout<<endl<<"The wpl is "<<ans<<endl;
    return 0;
}

  • 遇到的问题
    在创建树时,一定要判断 pre_l 是否 < pre_r,如果不是则返回NULL。

Guess you like

Origin blog.csdn.net/qq_39763472/article/details/106976494