1. 程式人生 > 實用技巧 >樹的相關小測試 題解

樹的相關小測試 題解

第一題和第三題起初想法都是構建樹的相關資料結構,但通過挖掘題目的性質,尤其是輸出要求,無需搭建一棵完整的樹。

1. 從下至上按層遍歷二叉樹

題意

給定一顆二叉樹,要求從下至上按層遍歷二叉樹,每層的訪問順序是從左到右,每一層單獨輸出一行。輸入形式為廣義表,它表示的二叉樹,結點元素型別為整型,且都大於0,例如:1( 2( 3 ( 4, 5 ) ), 6( 7, 8( 9, 10 ) ) )。現要你從下至上,列印每一層的結點元素值,且每層訪問順序是從左到右。

分析

題目要求的廣義表輸入,可以聯絡括號匹配。通過層數來將節點分類儲存,既能夠適應廣義表,又能夠直接層次遍歷。

#include <iostream>
#include <cstdio>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
const int MAXN = 1e5;
string str;
vector<int> tree[MAXN]; //tree[i]表示第i層(從0計數)的一串節點
int main(){
    cin >> str;
    int dep = 0, maxdep = -1, sum = 0;
    for (int i = 0; i < (int)str.length(); i++){
        if('0' <= str[i] && str[i] <= '9'){ /*注意,輸入數字不一定為個位數!*/
            sum = sum * 10 + str[i] - '0';
        } 
        else{
            if(sum > 0) tree[dep].push_back(sum);
            sum = 0; //重置sum
            if (str[i] == '(') dep++; 
            else if (str[i] == ')') dep--;
        }
        maxdep = max(maxdep, dep); //記錄最大深度
    }
    for (int i = maxdep; i >= 0; i--){
        for(int j = 0; j < (int)tree[i].size(); j++)
            printf("%d ", tree[i][j]);
        printf("\n");
    }
    return 0;
}

2. 使用前序字串構建一個二叉樹,並中序遍歷這棵樹。

題意

使用前序字串構建一個二叉樹,並輸出這棵樹中序遍歷。字串使用“#”表示孩子為空的情況。eg: abd#g###ce##f##

分析

題目中的前序遍歷序列,與以往不同的是已經給定空節點。由此得到的序列與深搜方向基本一致(順序不一定完全吻合),一開始對字串向右遍歷,實際上就是往樹的左側鏈進行遍歷,一旦遍歷過程中遇到#就立即轉向到其兄弟節點(即右節點),繼續深入搜尋。

#include <iostream>
#include <cstdio>
#include <vector>
#include <string>
#include <queue>
#include <algorithm>
using namespace std;
const int MAXN = 1e5;
string str;
char tree[MAXN];
int Build(int pos, int rt){
    tree[rt] = str[pos];
    if(str[pos] == '#') {
        tree[rt] = str[pos];
        return pos;
    }
    int last = Build(pos + 1, rt << 1); 
    last = Build(last + 1, rt << 1 | 1); //回溯最新訪問到的字元
    return last;
}
void dfs(int rt){
    if(tree[rt] == '#' || tree[rt] == '\0') return;
    dfs(rt << 1);
    cout << tree[rt];
    dfs(rt << 1 | 1);
}
int main(){
    cin >> str;
    Build(0, 1);
    dfs(1);
    return 0;
}

3. 求節點的哈夫曼的帶權路徑長度

題意

已知輸入一串正整數,正整數之間用空格鍵分開,請建立一個哈夫曼樹,以輸入的數字為葉節點,求這棵哈夫曼樹的帶權路徑長度。

分析

往上建樹的模擬過程中,對每一次節點合併得到的新節點權值進行累加,其實就是對帶權路徑累加

#include <iostream>
#include <cstdio>
#include <vector>
#include <string>
#include <queue>
#include <algorithm>
using namespace std;
const int MAXN = 100;
priority_queue< int, vector<int>, greater<int> > myque;
int tot = 0;
int main(){
    int n; scanf("%d", &n);
    for (int i = 1; i <= n; i++){
        int tmp; scanf("%d", &tmp);
        myque.push(tmp);
    }
    int sum = 0;
    while(myque.size() > 1){
        int lc = myque.top();
        myque.pop();
        int rc = myque.top();
        myque.pop();
        myque.push(lc + rc);
        sum += (lc + rc);
    }
    printf("%d\n", sum);
}