文章目录
A. DS二叉树–二叉树构建与遍历
题目描述
给定一颗二叉树的逻辑结构如下图,(先序遍历的结果,空树用字符‘0’表示,例如AB0C00D00),建立该二叉树的二叉链式存储结构,并输出该二叉树的先序遍历、中序遍历和后序遍历结果
输入
第一行输入一个整数t,表示有t个二叉树
第二行起输入每个二叉树的先序遍历结果,空树用字符‘0’表示,连续输入t行
输出
输出每个二叉树的先序遍历、中序遍历和后序遍历结果
输入样例
2
AB0C00D00
AB00C00
输出样例
ABCD
BCAD
CBDA
ABC
BAC
BCA
C++ 代码
#include <iostream>
using namespace std;
string str;
int pos;
struct TreeNode{
char val;
TreeNode* left;
TreeNode* right;
TreeNode():left(NULL), right(NULL){}
TreeNode(char ch):val(ch), left(NULL), right(NULL){}
};
TreeNode* make_tree(TreeNode* h){
char ch = str[pos++];
if (ch == '0') return NULL;
else {
h = new TreeNode(ch);
h->left = make_tree(h->left);
h->right = make_tree(h->right);
}
return h;
}
void PreOrder(TreeNode* h){
cout << h->val;
if (h->left) PreOrder(h->left);
if (h->right) PreOrder(h->right);
}
void InOrder(TreeNode* h){
if (h->left) InOrder(h->left);
cout << h->val;
if (h->right) InOrder(h->right);
}
void PosOrder(TreeNode* h){
if (h->left) PosOrder(h->left);
if (h->right) PosOrder(h->right);
cout << h->val;
}
int main(){
int t;
cin >> t;
while (t--){
TreeNode* head;
cin >> str;
pos = 0;
head = make_tree(head);
PreOrder(head);
cout << endl;
InOrder(head);
cout << endl;
PosOrder(head);
cout << endl;
}
return 0;
}
B. DS二叉树–叶子数量
题目描述
计算一颗二叉树包含的叶子结点数量。
提示:叶子是指它的左右孩子为空。
建树方法采用“先序遍历+空树用0表示”的方法,即给定一颗二叉树的先序遍历的结果为AB0C00D00,其中空节点用字符‘0’表示。则该树的逻辑结构如下图。
输入
第一行输入一个整数t,表示有t个测试数据
第二行起输入二叉树先序遍历的结果,空树用字符‘0’表示,输入t行
输出
逐行输出每个二叉树的包含的叶子数量
输入样例
3
AB0C00D00
AB00C00
ABC00D00E00
输出样例
2
2
3
C++ 代码
#include <iostream>
using namespace std;
string str;
int pos;
int ans;
struct TreeNode{
char val;
TreeNode* left;
TreeNode* right;
TreeNode():left(NULL), right(NULL){}
TreeNode(char ch):val(ch), left(NULL), right(NULL){}
};
TreeNode* make_tree(TreeNode* h){
char ch = str[pos++];
if (ch == '0') return NULL;
else {
h = new TreeNode(ch);
h->left = make_tree(h->left);
h->right = make_tree(h->right);
}
return h;
}
void PreOrder(TreeNode* h){
if (h->left) PreOrder(h->left);
if (h->right) PreOrder(h->right);
if (!h->left && !h->right) ans++;
}
int main(){
int t;
cin >> t;
while (t--){
ans = 0;
TreeNode* head;
cin >> str;
pos = 0;
head = make_tree(head);
PreOrder(head);
cout << ans;
cout << endl;
}
return 0;
}
C. DS二叉树——二叉树之父子结点
题目描述
给定一颗二叉树的逻辑结构如下图,(先序遍历的结果,空树用字符‘0’表示,例如AB0C00D00),建立该二叉树的二叉链式存储结构。
编写程序输出该树的所有叶子结点和它们的父亲结点
输入
第一行输入一个整数t,表示有t个二叉树
第二行起,按照题目表示的输入方法,输入每个二叉树的先序遍历,连续输入t行
输出
第一行按先序遍历,输出第1个示例的叶子节点
第二行输出第1个示例中与叶子相对应的父亲节点
以此类推输出其它示例的结果
输入样例
3
AB0C00D00
AB00C00
ABCD0000EF000
输出样例
C D
B A
B C
A A
D F
C E
C++ 代码
#include <iostream>
using namespace std;
string str;
string son, fa;
int pos;
int ans;
struct TreeNode{
char val;
TreeNode* left;
TreeNode* right;
TreeNode():left(NULL), right(NULL){}
TreeNode(char ch):val(ch), left(NULL), right(NULL){}
};
TreeNode* make_tree(TreeNode* h){
char ch = str[pos++];
if (ch == '0') return NULL;
else {
h = new TreeNode(ch);
h->left = make_tree(h->left);
h->right = make_tree(h->right);
}
return h;
}
void PreOrder(TreeNode* h){
if (h->left){
if (!h->left->left && !h->left->right){
fa += h->val;
son += h->left->val;
}
PreOrder(h->left);
}
if (h->right){
if (!h->right->left && !h->right->right){
fa += h->val;
son += h->right->val;
}
PreOrder(h->right);
}
}
int main(){
int t;
cin >> t;
while (t--){
son.clear();
fa.clear();
ans = 0;
TreeNode* head;
cin >> str;
pos = 0;
head = make_tree(head);
PreOrder(head);
for (int i = 0; son[i]; ++i) cout << son[i] << " ";
cout << endl;
for (int i = 0; fa[i]; ++i) cout << fa[i] << " ";
cout << endl;
}
return 0;
}
D. DS树–二叉树高度
题目描述
给出一棵二叉树,求它的高度。二叉树的创建采用前面实验的方法。
注意,二叉树的层数是从1开始
输入
第一行输入一个整数t,表示有t个二叉树
第二行起输入每个二叉树的先序遍历结果,空树用字符‘0’表示,连续输入t行
输出
每行输出一个二叉树的高度
输入样例
1
AB0C00D00
输出样例
3
C++ 代码
#include <iostream>
using namespace std;
string str;
int pos;
int high;
struct TreeNode{
char val;
TreeNode* left;
TreeNode* right;
TreeNode():left(NULL), right(NULL){}
TreeNode(char ch):val(ch), left(NULL), right(NULL){}
};
TreeNode* make_tree(TreeNode* h){
char ch = str[pos++];
if (ch == '0') h = NULL;
else {
h = new TreeNode(ch);
h->left = make_tree(h->left);
h->right = make_tree(h->right);
}
return h;
}
void Level(TreeNode* h){
TreeNode* q[100];
int hh = 0, tt = -1;
q[++tt] = h;
while (hh <= tt){
int sz = tt-hh + 1;
while (sz--){
auto t = q[hh++];
if (t->left) q[++tt] = t->left;
if (t->right) q[++tt] = t->right;
}
high++;
}
}
int main(){
int t;
cin >> t;
while (t--){
cin >> str;
pos = 0;
high = 0;
TreeNode* head = make_tree(head);
Level(head);
cout << high << endl;
}
return 0;
}
E. DS二叉树——二叉树之数组存储
题目描述
二叉树可以采用数组的方法进行存储,把数组中的数据依次自上而下,自左至右存储到二叉树结点中,一般二叉树与完全二叉树对比,比完全二叉树缺少的结点就在数组中用0来表示。,如下图所示
从上图可以看出,右边的是一颗普通的二叉树,当它与左边的完全二叉树对比,发现它比完全二叉树少了第5号结点,所以在数组中用0表示,同样它还少了完全二叉树中的第10、11号结点,所以在数组中也用0表示。
结点存储的数据均为非负整数
输入
第一行输入一个整数t,表示有t个二叉树
第二行起,每行输入一个数组,先输入数组长度,再输入数组内数据,每个数据之间用空格隔开,输入的数据都是非负整数
连续输入t行
输出
每行输出一个示例的先序遍历结果,每个结点之间用空格隔开
输入样例
3
3 1 2 3
5 1 2 3 0 4
13 1 2 3 4 0 5 6 7 8 0 0 9 10
输出样例
1 2 3
1 2 4 3
1 2 4 7 8 3 5 9 10 6
提示
注意从数组位置和二叉树深度、结点位置进行关联,或者父子结点在数组中的位置存在某种管理,例如i, i+1, i/2, i+1/2…或者2i, 2i+1…仔细观察哦
C++ 代码
#include <iostream>
using namespace std;
const int N = 1e5+10;
int n;
int nums[N];
struct TreeNode{
int val;
TreeNode* left;
TreeNode* right;
TreeNode():val(-1), left(NULL), right(NULL){}
TreeNode(int x):val(x), left(NULL), right(NULL){}
};
TreeNode* make_tree(int u){
TreeNode* t;
if (nums[u] == 0) t = NULL;
else {
t = new TreeNode(nums[u]);
if (2*u <= n) t->left = make_tree(2*u);
if (2*u+1 <= n) t->right = make_tree(2*u+1);
}
return t;
}
void PreOrder(TreeNode* h){
cout << h->val << " ";
if (h->left) PreOrder(h->left);
if (h->right) PreOrder(h->right);
}
int main(){
int t;
cin >> t;
while (t--){
cin >> n;
for (int i = 1; i <= n; ++i) cin >> nums[i];
TreeNode* head;
head = make_tree(1);
PreOrder(head);
cout << endl;
}
return 0;
}
F. DS二叉树–赫夫曼树的构建与编码(含代码框架)
题目描述
给定n个权值,根据这些权值构造huffman树,并进行huffman编码
参考课本算法,注意数组访问是从位置1开始
要求:赫夫曼的构建中,默认左孩子权值不大于右孩子权值
代码框架参考如下:
输入
第一行输入t,表示有t个测试实例
第二行先输入n,表示第1个实例有n个权值,接着输入n个权值,权值全是小于1万的正整数
依此类推
输出
逐行输出每个权值对应的编码,格式如下:权值-编码
即每行先输出1个权值,再输出一个短划线,再输出对应编码,接着下一行输入下一个权值和编码。
以此类推
输入样例
1
5 15 4 4 3 2
输出样例
15-1
4-010
4-011
3-001
2-000
C++ 代码
#include <iostream>
#include <queue>
using namespace std;
const int N = 1e5+10;
int n;
int a[N];
int cnt;
struct TreeNode{
int id;
int val;
TreeNode(int id = 0, int val = 0):id(id), val(val){}
bool operator < (const TreeNode &r) const{
if (val == r.val) return id > r.id;
return val > r.val;
}
};
struct Tree{
int lch;
int rch;
}tree[N];
string str[N];
void dfs(int u, string path){
if (u == -1) return ;
if (u < n) str[u] = path;
dfs(tree[u].lch, path + '0');
dfs(tree[u].rch, path+'1');
}
int main(){
int t;
cin >> t;
while (t--){
cin >> n;
priority_queue<TreeNode> heap;
for (int i = 0; i < n; ++i){
cin >> a[i];
heap.push(TreeNode(i, a[i]));
tree[i].lch = tree[i].rch = -1;
}
cnt = n-1;
while (!heap.empty()){
bool two = false;
TreeNode op[2];
if (!heap.empty()){
op[0] = heap.top();
heap.pop();
}
if (!heap.empty()){
op[1] = heap.top();
heap.pop();
two = true;
}
if (!two) break;
heap.push(TreeNode(++cnt, op[0].val+op[1].val));
tree[cnt].lch = op[0].id;
tree[cnt].rch = op[1].id;
}
dfs(cnt, "");
for (int i = 0; i < n; ++i) cout << a[i] << "-" << str[i] << endl;
}
return 0;
}
G. DS二叉树–赫夫曼树解码(含代码框架)
题目描述
已知赫夫曼编码算法和程序,在此基础上进行赫夫曼解码
在赫夫曼树的类定义中增加了一个公有方法:
int Decode(const string codestr, char txtstr[]);//输入编码串codestr,输出解码串txtstr
该方法如果解码成功则返回1,解码失败则返回-1,本程序增加宏定义ok表示1,error表示-1
解码方法的代码框架如下:
输入
第一行输入t,表示有t个测试实例
第二行先输入n,表示第1个实例有n个权值,接着输入n个权值,权值全是小于1万的正整数
第三行输入n个字母,表示与权值对应的字符
第四行输入k,表示要输入k个编码串
第五行起输入k个编码串
以此类推输入下一个示例
输出
每行输出解码后的字符串,如果解码失败直接输出字符串“error”,不要输出部分解码结果
输入样例
2
5 15 4 4 3 2
A B C D E
3
11111
10100001001
00000101100
4 7 5 2 4
A B C D
3
1010000
111011
111110111
输出样例
AAAAA
ABEAD
error
BBAAA
error
DCD
C++ 代码
#include <algorithm>
#include <iostream>
#include <queue>
using namespace std;
const int N = 1e5 + 5;
int cnt, a[N], n;
char ch[N];
struct Tree {
int lch, rch;
}t[N<<1];
struct node {
int id, val;
node(int id=0, int v=0): id(id), val(v) {}
bool operator < (const node& r) const {
if (val == r.val) return id > r.id;
return val > r.val;
}
};
string s[N], str, ans;
void dfs(int u, string path) {
if (u == -1) return ;
if (u <= n) s[u] = path;
dfs(t[u].lch, path + "0");
dfs(t[u].rch, path + "1");
}
void Decode(int u, int c, string& ans) {
if (u == - 1) return;
if (u <= n && str[c]) {
ans += ch[u];
Decode(cnt, c, ans);
}
if (str[c] == 0) {
if (u > n) {
ans = "error";
return ;
}else {
ans += ch[u];
return ;
}
}
if (str[c] == '1') Decode(t[u].rch, c+1, ans);
if (str[c] == '0') Decode(t[u].lch, c+1, ans);
}
int main() {
int T; cin >> T;
while (T --) {
cin >> n;
priority_queue<node> q;
for (int i = 1; i <= n; i ++) {
cin >> a[i];
q.push(node(i, a[i]));
t[i].lch = t[i].rch = -1;
s[i] = "";
}
for (int i = 1; i <= n; i ++) cin >> ch[i];
cnt = n;
while (! q.empty()) {
bool two = false;
node op[2];
if (! q.empty()) {
op[0] = q.top();
q.pop();
}
if (! q.empty()) {
op[1] = q.top();
q.pop(), two = true;
}
if (! two) break;
q.push(node(++ cnt, op[1].val + op[0].val));
t[cnt].lch = op[0].id, t[cnt].rch = op[1].id;
}
dfs(cnt, "");
int k; cin >> k;
for (int i = 0; i < k; i ++) {
cin >> str;
Decode(cnt, 0, ans="");
cout << ans << endl;
}
}
return 0;
}
H. DS树–带权路径和
题目描述
计算一棵二叉树的带权路径总和,即求赫夫曼树的带权路径和。
已知一棵二叉树的叶子权值,该二叉树的带权案路径和APL等于叶子权值乘于根节点到叶子的分支数,然后求总和。如下图中,叶子都用大写字母表示,权值对应为:A-7,B-6,C-2,D-3
树的带权路径和 = 71 + 62 + 23 + 33 = 34
本题二叉树的创建参考前面的方法
输入
第一行输入一个整数t,表示有t个二叉树
第二行输入一棵二叉树的先序遍历结果,空树用字符‘0’表示,注意输入全是英文字母和0,其中大写字母表示叶子
第三行先输入n表示有n个叶子,接着输入n个数据表示n个叶子的权值,权值的顺序和前面输入的大写字母顺序对应
以此类推输入下一棵二叉树
输出
输出每一棵二叉树的带权路径和
输入样例
2
xA00tB00zC00D00
4 7 6 2 3
ab0C00D00
2 10 20
输出样例
34
40
C++ 代码
#include <iostream>
using namespace std;
string str;
int pos;
int sum;
struct TreeNode{
char val;
TreeNode* left;
TreeNode* right;
TreeNode(char val = 0):val(val), left(NULL), right(NULL){}
};
TreeNode* make_tree(){
char ch = str[pos++];
TreeNode* h;
if (ch == '0') h = NULL;
else {
h = new TreeNode(ch);
h->left = make_tree();
h->right = make_tree();
}
return h;
}
void PreOrder(TreeNode* h, int u){
if (h->left) PreOrder(h->left, u+1);
if (h->right) PreOrder(h->right, u+1);
if (!h->left && !h->right){
int x;
cin >> x;
sum += x*u;
}
}
int main(){
int t;
cin >> t;
while (t--){
sum = 0;
pos = 0;
TreeNode* head;
cin >> str;
head = make_tree();
int x;
cin >>x;
PreOrder(head, 0);
cout << sum << endl;
}
return 0;
}
I. DS二叉树–基于数组存储的构建
题目描述
任意二叉树可以根据完全二叉树性质保存在一个数组中。已知二叉树的数组存储,用程序构建该二叉树。
提示:用递归方法或非递归都可以
递归方法的代码框架如下:
输入
第一行输入一个整数t,表示有t个测试数据
第二行起输入二叉树的数组存储结果,空树用字符‘0’表示,输入t行
数组的数据由大写字母和0表示
输出
逐行输出每个二叉树的先序结果
输入样例
3
ABC0D
ABCDEF000G
ABEC0F0D0
输出样例
ABDC
ABDEGCF
ABCDEF
C++ 代码
#include <iostream>
using namespace std;
string str;
struct TreeNode{
char val;
TreeNode* left;
TreeNode* right;
TreeNode(char ch = 0):val(ch), left(NULL), right(NULL){}
};
TreeNode* make_tree(int u){
char ch = str[u];
TreeNode* h;
if (ch == '0') h = NULL;
else {
h = new TreeNode(ch);
if (2*u < str.size()) h->left = make_tree(2*u);
if (2*u+1 < str.size()) h->right = make_tree(2*u+1);
}
return h;
}
void PreOrder(TreeNode* h){
cout << h->val;
if (h->left) PreOrder(h->left);
if (h->right) PreOrder(h->right);
}
int main(){
int t;
cin >> t;
while (t--){
TreeNode* head;
cin >> str;
str.insert(str.begin(), ' ');
head = make_tree(1);
PreOrder(head);
cout << endl;
}
return 0;
}
J. DS二叉树判断–同一棵二叉树?
题目描述
二叉树分别以数组存储方式创建、以先序遍历序列创建。输入二叉树的数组存储、先序遍历结果,判断根据它们创建的二叉树是否是同一棵二叉树。
输入
测试次数t
每组测试数据两行:
第一行:二叉树的数组存储(英文字母表示树结点,#表示空树)
第二行:二叉树的先序遍历结果(英文字母表示树结点,#表示空树)
输出
对每组测试数据,如果两种方式创建的是同一棵二叉树,输出YES,否则,输出NO。
输入样例
3
ABCDE
ABD##E##C
ABC##DE####W##F
AB##CDW###E#F##
abc##d
ab##c#d
输出样例
YES
YES
NO
C++ 代码
#include <iostream>
using namespace std;
string str;
int pos;
bool flag;
struct TreeNode{
char val;
TreeNode* left;
TreeNode* right;
TreeNode(char ch = 0):val(ch), left(NULL), right(NULL){}
};
TreeNode* make_tree(int u){
char ch = str[u];
TreeNode* h;
if (ch == '#') h = NULL;
else {
h = new TreeNode(ch);
if (2*u < str.size()) h->left = make_tree(2*u);
if (2*u+1 < str.size()) h->right = make_tree(2*u+1);
}
return h;
}
void PreOrder(TreeNode* h){
if (h){
if (h->val != str[pos++]) flag = false;
PreOrder(h->left);
PreOrder(h->right);
}
else {
if (pos < str.size() && str[pos++] != '#') flag = false;
}
}
int main(){
int t;
cin >> t;
while (t--){
flag = true;
pos = 0;
TreeNode* head;
cin >> str;
str.insert(str.begin(), ' ');
head = make_tree(1);
cin >> str;
PreOrder(head);
if (flag) cout << "YES" << endl;
else cout << "NO" << endl;
flag = true;
}
return 0;
}
K. DS树–二叉树之最大路径
题目描述
给定一颗二叉树的逻辑结构(先序遍历的结果,空树用字符‘0’表示,例如AB0C00D00),建立该二叉树的二叉链式存储结构
二叉树的每个结点都有一个权值,从根结点到每个叶子结点将形成一条路径,每条路径的权值等于路径上所有结点的权值和。编程求出二叉树的最大路径权值。如下图所示,共有4个叶子即有4条路径,
路径1权值=5 + 4 + 11 + 7 = 27路径2权值=5 + 4 + 11 + 2 = 22
路径3权值=5 + 8 + 13 = 26路径4权值=5 + 8 + 4 + 1 = 18
可计算出最大路径权值是27。
该树输入的先序遍历结果为ABCD00E000FG00H0I00,各结点权值为:
A-5,B-4,C-11,D-7,E-2,F-8,G-13,H-4,I-1
输入
第一行输入一个整数t,表示有t个测试数据
第二行输入一棵二叉树的先序遍历,每个结点用字母表示
第三行先输入n表示二叉树的结点数量,然后输入每个结点的权值,权值顺序与前面结点输入顺序对应
以此类推输入下一棵二叉树
输出
每行输出每棵二叉树的最大路径权值,如果最大路径权值有重复,只输出1个
输入样例
2
AB0C00D00
4 5 3 2 6
ABCD00E000FG00H0I00
9 5 4 11 7 2 8 13 4 1
输出样例
11
27
C++ 代码
#include <iostream>
using namespace std;
string str;
int pos;
int sum;
struct TreeNode{
char ch;
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int val = 0, char ch = 0):val(val), ch(ch), left(NULL), right(NULL){}
};
TreeNode* make_tree(){
char ch = str[pos++];
TreeNode* h;
if (ch == '0') h = NULL;
else {
int x;
cin >> x;
h = new TreeNode(x, ch);
h->left = make_tree();
h->right = make_tree();
}
return h;
}
void dfs(TreeNode* h, int u){
if (h->left) dfs(h->left, u+h->val);
if (h->right) dfs(h->right, u+h->val);
if (!h->left && !h->right) sum = max(u+h->val, sum);
}
int main(){
int t;
cin >> t;
while (t--){
sum = 0;
pos = 0;
TreeNode* head;
cin >> str;
int x;
cin >> x;
head = make_tree();
dfs(head, 0);
cout << sum << endl;
}
return 0;
}
L. DS森林叶子编码
题目描述
给定一组森林,编写程序生成对应的二叉树,输出这颗二叉树叶结点对应的二进制编码.规定二叉树的左边由0表示,二叉树的右边由1表示。
输入
N B 表示N个树,每结点最多B个分支
第2行至第N+1行,每个树的先序遍历
输出
每行表示一个叶结点对应的二进制编码.
输入样例
3 3
A B 0 0 0 C 0 0 0 D 0 0 0
E F 0 0 0 0 0
G H 0 0 0 I J 0 0 0 0 0 0
输出样例
0 1 1
1 0
1 1 0 1 0
C++ 代码
#include <iostream>
#include <sstream>
using namespace std;
int n, nums;
string s;
string temp;
int pos;
struct TreeNode{
char val;
TreeNode** child;
TreeNode(char val = 0):val(val){
child = new TreeNode*[nums];
for (int i = 0; i < nums; ++i){
child[i] = NULL;
}
}
};
struct BiNode{
char val;
BiNode* left;
BiNode* right;
BiNode(char ch = 0):val(ch), left(NULL), right(NULL){}
};
TreeNode* make_tree(){
TreeNode* h;
char ch;
cin >> ch;
if (ch == '0') h = NULL;
else {
h = new TreeNode(ch);
for (int i = 0; i < nums; ++i){
h->child[i] = make_tree();
}
}
return h;
}
BiNode* trans(TreeNode* h){
BiNode* t = NULL;
if (h != NULL){
t = new BiNode(h->val);
t->left = trans(h->child[0]);
if (t->left){
BiNode* tt = t->left;
for (int i = 1; i < nums; ++i){
tt->right = trans(h->child[i]);
if (tt->right) tt = tt->right;
}
}
}
return t;
}
void dfs(BiNode* h, string path){
if (h->left) dfs(h->left, path + '0');
if (h->right) dfs(h->right, path + '1');
if (!h->left && !h->right){
int x = path.size();
for (int i = 0; i < x; ++i){
if (i < x-1) cout << path[i] << " ";
else cout << path[i] << endl;
}
}
}
int main(){
cin >> n >> nums;
TreeNode** head;
head = new TreeNode*[n];
for (int i = 0; i < n; ++i){
head[i] = make_tree();
}
BiNode** h;
h = new BiNode*[n];
for (int i = 0; i < n; ++i){
h[i] = trans(head[i]);
}
for (int i = 1; i < n; ++i){
h[i-1]->right = h[i];
}
dfs(h[0], "");
return 0;
}
M. DS二叉树—二叉树结点的最大距离
题目描述
二叉树两个结点的距离是一个结点经过双亲结点,祖先结点等中间结点到达另一个结点经过的分支数。二叉树结点的最大距离是所有结点间距离的最大值。例如,下图所示二叉树结点最大距离是3,C和D的距离。
二叉树用先序遍历顺序创建,#表示空树。计算二叉树结点最大距离和最大距离的两个结点(假设二叉树中取最大距离的两个结点唯一)。
输入
测试次数T
第2行之后的T行,每行为一棵二叉树先序遍历结果(#表示空树)
输出
对每棵二叉树,输出树的结点最大距离和最大距离的结点,输出格式见样例。
输入样例
3
A##
ABC##EF#G###D##
ABEH###F#K###
输出样例
0:
5:G D
4:H K
C++ 代码
#include <iostream>
using namespace std;
int depth;
char temp;
struct TreeNode{
char val;
TreeNode* left;
TreeNode* right;
TreeNode():left(NULL), right(NULL){}
TreeNode(char ch):val(ch), left(NULL), right(NULL){}
};
class Tree{
public:
TreeNode* root;
int pos;
int ld;
int rd;
char l;
char ll;
char rr;
char r;
int maxn;
string str;
Tree():pos(0), ld(0), rd(0), maxn(0){}
~Tree(){}
void MakeTree(string s){
str += s;
root = MakeTree();
}
TreeNode* MakeTree(){
char ch = str[pos++];
TreeNode* t;
if (ch == '#') return NULL;
else {
t = new TreeNode(ch);
t->left = MakeTree();
t->right = MakeTree();
}
return t;
}
void LDepth(TreeNode* root){
if (root->left == NULL){
depth = 0;
temp = root->val;
l = temp;
return ;
}
Depth(root->left, 0);
ld = depth;
l = temp;
return ;
}
void RDepth(TreeNode* root){
if (root->right == NULL){
depth = 0;
temp = root->val;
r = temp;
return ;
}
Depth(root->right, 0);
rd = depth;
r = temp;
}
void Depth(TreeNode* root, int sum){
if (root != NULL){
sum++;
if (root->left == NULL && root->right == NULL && depth < sum){
depth = sum;
temp = root->val;
}
if (root->left) Depth(root->left, sum);
if (root->right) Depth(root->right, sum);
}
}
void PreOrder(TreeNode* root){
if (root != NULL){
depth = 0;
ld = 0;
LDepth(root);
depth = 0;
rd = 0;
RDepth(root);
if (maxn < ld+rd){
ll = l;
rr = r;
maxn = ld+rd;
//cout << maxn << ll << " " << rr << endl;
}
PreOrder(root->left);
PreOrder(root->right);
}
}
};
int main(){
int t;
cin >> t;
while (t--){
string str;
cin >> str;
Tree t;
t.MakeTree(str);
t.LDepth(t.root);
t.RDepth(t.root);
t.PreOrder(t.root);
if (t.maxn == 0) cout << "0:" << endl;
else cout << t.maxn << ":" << t.ll << " " << t.rr << endl;
}
return 0;
}
DS二叉树—二叉树镜面反转
题目描述
假设二叉树用二叉链表存储,用先序序列结果创建。输入二叉树的先序序列,请你先创建二叉树,并对树做个镜面反转,再输出反转后的二叉树的先序遍历、中序遍历、后序遍历和层序遍历的序列。所谓镜面反转,是指将所有非叶结点的左右孩子对换。
–程序要求–
若使用C++只能include一个头文件iostream;若使用C语言只能include一个头文件stdio
程序中若include多过一个头文件,不看代码,作0分处理
不允许使用第三方对象或函数实现本题的要求
输入
测试次数t
每组测试数据是一个二叉树的先序遍历序列,#表示空树
输出
对每棵二叉树,输出镜面反转后的先序、中序、后序和层次遍历序列。如果空树,输出四个NULL(后面不加空格)。如下:
NULL
NULL
NULL
NULL
输入样例
3
41#32###65##7##
AB#C##D##
AB##C##
输出样例
4 6 7 5 1 3 2
7 6 5 4 3 2 1
7 5 6 2 3 1 4
4 6 1 7 5 3 2
A D B C
D A C B
D C B A
A D B C
A C B
C A B
C B A
A C B
C++ 代码
#include <iostream>
using namespace std;
string str;
int pos;
struct TreeNode{
char val;
TreeNode* left;
TreeNode* right;
TreeNode(char ch = 0):val(ch), left(NULL), right(NULL){}
};
TreeNode* make_tree(){
char ch = str[pos++];
TreeNode* t;
if (ch == '#') return NULL;
else {
t = new TreeNode(ch);
t->left = make_tree();
t->right = make_tree();
}
return t;
}
TreeNode* trans(TreeNode* h){
if (h == NULL) return NULL;
TreeNode* s;
s = new TreeNode(h->val);
if (h->left) s->right = trans(h->left);
if (h->right) s->left = trans(h->right);
return s;
}
void PreOrder(TreeNode* h){
cout << h->val << " ";
if (h->left) PreOrder(h->left);
if (h->right) PreOrder(h->right);
}
void InOrder(TreeNode* h){
if (h->left) InOrder(h->left);
cout << h->val << " ";
if (h->right) InOrder(h->right);
}
void PosOrder(TreeNode* h){
if (h->left) PosOrder(h->left);
if (h->right) PosOrder(h->right);
cout << h->val << " ";
}
void Level(TreeNode* h){
TreeNode* q[100];
int hh = 0, tt = -1;
q[++tt] = h;
while (hh <= tt){
int sz = tt-hh+1;
while (sz--){
auto t = q[hh++];
cout << t->val << " ";
if (t->left) q[++tt] = t->left;
if (t->right) q[++tt] = t->right;
}
}
}
int main(){
int t;
cin >> t;
while (t--){
pos = 0;
cin >> str;
TreeNode* h = make_tree();
TreeNode* s = trans(h);
if (s == NULL){
for (int i = 0; i < 4; ++i) cout << "NULL" << endl;
}
else {
PreOrder(s);
cout << endl;
InOrder(s);
cout << endl;
PosOrder(s);
cout << endl;
Level(s);
cout << endl;
}
}
return 0;
}
O. DS树–找出直系亲属
题目描述
如果A,B是C的父母亲,则A,B是C的parent,C是A,B的child,如果A,B是C的(外)祖父,祖母,则A,B是C的grandparent,C是A,B的grandchild,如果A,B是C的(外)曾祖父,曾祖母,则A,B是C的great-grandparent,C是A,B的great-grandchild,之后再多一辈,则在关系上加一个great-
输入
输入包含多组测试用例,每组用例首先包含2个整数n(0<=n<=26)和m(0<m<50), 分别表示有n个亲属关系和m个问题, 然后接下来是n行的形式如ABC的字符串,表示A的父母亲分别是B和C,如果A的父母亲信息不全,则用-代替,例如A-C,再然后是m行形式如FA的字符串,表示询问F和A的关系。
当n和m为0时结束输入。
输出
如果询问的2个人是直系亲属,请按题目描述输出2者的关系,如果没有直系关系,请输出-。
具体含义和输出格式参见样例.
输入样例
3 2
ABC
CDE
EFG
FA
BE
0 0
输出样例
great-grandparent
-
C++ 代码
#include<iostream>
#include<map>
#define N 26
using namespace std;
class Node
{//二叉树节点
public:
int p1;//第一个双亲的下标,-1表示不存在
int p2;//第二个双亲的下标,-1表示不存在
};
int preOrder(Node *tree,int from, int to, int depth)
{//从from出发先序遍历到找到to为止,并返回to相对于from的深度
if(from==to)
return depth;
if(tree[from].p1!=-1)
{
int ret=preOrder(tree,tree[from].p1,to,depth+1);
if(ret!=-1)
return ret;
}
if(tree[from].p2!=-1)
{
int ret=preOrder(tree,tree[from].p2,to,depth+1);
if(ret!=-1)
return ret;
}
return -1;
}
int main()
{
int n,m;
Node tree[N];//顺序存储,下标就是它所代表的字符编号,比如0代表'A'
while(true)
{
cin>>n>>m;
if(n==0||m==0)
break;
for(int i=0;i<N;i++)
{
tree[i].p1=tree[i].p2=-1;
}
while(n--)//构建树
{
char str[4];
cin>>str;
if(str[1]!='-')
tree[str[0]-'A'].p1=str[1]-'A';
if(str[2]!='-')
tree[str[0]-'A'].p2=str[2]-'A';
}
while(m--)//查询
{
char str[3];
cin>>str;
int from=str[0]-'A';
int to=str[1]-'A';
int ans1=preOrder(tree,from,to,0);
if(ans1==1)
cout<<"child"<<endl;
else if(ans1>=2)
{
for(int i=ans1;i>2;i--)
cout<<"great-";
cout<<"grandchild"<<endl;
}
else//不是小辈,那就是长辈
{
int ans2=preOrder(tree,to,from,0);
if(ans2==1)
cout<<"parent"<<endl;
else if(ans2>=2)
{
for(int i=ans2; i>2; i--)
cout<<"great-";
cout<<"grandparent"<<endl;
}
else
cout<<"-"<<endl;//也不是长辈,那就不是直系亲属
}
}
}
return 0;
}