-
前言
二叉樹的帶權路徑和,指的是二叉樹的所有葉子節點的權值 * 其深度 之和。
本次因爲是完整的程序,所以包含
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。