树专题整理

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;
}
  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值