树的相关小测试 题解
第一题和第三题起初想法都是构建树的相关数据结构,但通过挖掘题目的性质,尤其是输出要求,无需搭建一棵完整的树。
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){ //pos为输入字符串的下标,rt表示当前子树的根节点
tree[rt] = str[pos];
if(str[pos] == '#') { //当str[pos]说明此时rt节点为叶节点
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);
}