A.二叉树孩子链表法之找家人
题目描述
给出二叉树的孩子链表表示法,根据输入要求,找指定结点的双亲或孩子
输入
第一行输入两个参数,第一个参数n表示树有n个结点,第二个参数r表示根结点的数组下标
接着n行,每行先输入一个结点的数值(用单个字母表示),再输入结点的孩子下标(先左后右),如果只有一个孩子默认是左孩子,最后以-1结尾
如果该结点没有孩子,则一行只输入结点的数值和-1
接着输入t表示有t个结点要找家人
接着t行,每行输入两个参数,第1个参数是结点的数值,第2个参数是一个数字,其中0表示找双亲,1表示找左孩子,2表示找右孩子;
输出
输出t行,每行输出指定结点的双亲数值或孩子数值
每行输出一个数值,如果指定结点没有双亲或者没有孩子,则输出@
样例查看模式
正常显示查看格式
输入样例1
10 4\n
A 3 5 -1\n
B 2 9 -1\n
C 6 -1\n
D -1\n
R 0 1 -1\n
E -1\n
F 7 8 -1\n
G -1\n
H -1\n
K -1\n
4\n
G 0\n
R 1\n
C 2\n
R 0\n
输出样例1
F\n
A\n
@\n
@\n
AC代码
#include<iostream>
#include<queue>
#include<map>
using namespace std;
struct node
{char data;vector<char>child;
};
class tree
{int n;int root;vector<node>v;map<char, int>mp;map<int, char>mm;
public:tree(){cin >> n >> root;v.resize(n);for (int i = 0; i < n; i++){char ch;cin >> ch;v[i].data = ch;mp[ch] = i;mm[i] = ch;int x;cin >> x;while (x != -1){v[i].child.push_back(x);cin >> x;}}}void check(){int m;cin >> m;while (m--){char ch;int op;cin >> ch >> op;if (op == 1){if (v[mp[ch]].child.size() == 0){cout << "@" << endl;}else{cout << mm[v[mp[ch]].child[0]] << endl;}}else if (op == 2){if (v[mp[ch]].child.size() < 2){cout << "@" << endl;}else{cout << mm[v[mp[ch]].child[1]] << endl;}}else{int id = mp[ch];bool ok = 0;for (int i = 0; i < n; i++){for (int j = 0; j < v[i].child.size(); j++){if (v[i].child[j] == id){ok = 1;cout << v[i].data << endl;break;}}if (ok)break;}if (!ok)cout << "@" << endl;}}}
};
int main()
{tree t;t.check();return 0;
}
B.DS二叉树双亲表示法之找左叶子
题目描述
给出一棵二叉树的双亲表示法结果,用一个二维数组表示,位置下标从0开始,如果双亲位置为-1则表示该结点为根结点
如果结点有孩子,那么孩子的数组下标为奇数,则表示该孩子是左孩子,如果孩子的数组下标为偶数,则表示该孩子是右孩子(0算偶数)
编写程序,找出这棵树的所有左叶子。按照数组下标的顺序输出
输入
第一个输入t,表示有t棵树
接着每棵树输入3行:
第1行输入n,表示树有n个结点
第2行输入n个英文字母,表示每个树结点的数值
第3行输入n个整数,表示每个结点的双亲在数组的下标
以此类推输入下一棵树
输出
共输出t行,每行输出一棵二叉树的所有左叶子,按数组下标顺序输出
每行输出的每个叶子后面都带一个空格,最后一个也带空格
样例查看模式
正常显示查看格式
输入样例1
2\n
7\n
A B C D E F G\n
-1 0 0 1 1 3 3\n
10\n
A B C D R E F G H K\n
4 4 0 0 -1 1 2 2 6 7\n
输出样例1
F \n
D E K \n
AC代码
#include<iostream>
#include<queue>
#include<map>
#include<list>
using namespace std;
struct node
{char data;list<int>child;int fa;node(){data = '0';fa = -1;}
};
class tree
{int n;int root;vector<node>v;map<char, int>mp;map<int, char>mm;
public:tree(){cin >> n;v.resize(n);for (int i = 0; i < n; i++){cin >> v[i].data;mp[v[i].data] = i;mm[i] = v[i].data;}for (int i = 0; i < n; i++){int x;cin >> x;if (x == -1){root = i;}else{v[i].fa = x;v[x].child.push_back(i);}}}void show(){for (int i = 0; i < n; i++){cout << v[i].data << ":";for (auto tt:v[i].child){cout << mm[tt] << " ";}cout << endl;}}void check(){for (int i = 0; i < n; i++){int ss = v[i].child.size();if (ss == 0){continue;}else{int tt = v[i].child.front();if (v[tt].child.size() == 0){cout << mm[tt] << " ";}}}cout << endl;}
};
int main()
{int tt;cin >> tt;while (tt--){tree t;t.show();t.check();}return 0;
}
C.DS二叉树--基于数组存储的构建
题目描述
任意二叉树可以根据完全二叉树性质保存在一个数组中。已知二叉树的数组存储,用程序构建该二叉树。
提示:用递归方法或非递归都可以
输入
第一行输入一个整数t,表示有t个测试数据
第二行起输入二叉树的数组存储结果,空树用字符‘0’表示,输入t行
数组的数据由大写字母和0表示
输出
逐行输出每个二叉树的先序遍历结果
样例查看模式
正常显示查看格式
输入样例1
3\n
ABC0D\n
ABCDEF000G\n
ABEC0F0D0\n
输出样例1
ABDC\n
ABDEGCF\n
ABCDEF\n
AC代码
#include<iostream>
#include<queue>
#include<map>
#include<vector>
#include<list>
using namespace std;
class tree
{string s;
public:tree(){cin >> s;}void pre(int x=0){if (x >= s.size() || s[x] == '0')return;cout << s[x];pre(2 * x + 1);pre(2 * x + 2);}
};
int main()
{int tt;cin >> tt;while (tt--){tree t;t.pre(0);cout << endl;}return 0;
}
D. DS二叉树--赫夫曼树的构建与编码
题目描述
给定n个权值,根据这些权值构造huffman树,并进行huffman编码
大家参考课本算法6.12为主,注意数组访问是从位置1开始
要求:赫夫曼的构建中,默认左孩子权值不大于右孩子权值
输入
第一行先输入n,表示有n个权值,即有n个叶子
第二行输入n个权值,权值全是小于1万的正整数
输出
逐行出每个权值对应的编码,格式如下:权值-编码
即每行先输出1个权值,再输出一个短划线,再输出对应编码
接着下一行输出下一个权值和编码,以此类推
样例查看模式
正常显示查看格式
输入样例1
5\n
15 4 4 3 2\n
输出样例1
15-1\n
4-010\n
4-011\n
3-001\n
2-000\n
AC代码
#include<iostream>
using namespace std;
struct node
{int weight;int l, r, p;string code;node(){weight = 0;l = r = p = 0;}
};
class tree
{node* root;int n;
public:tree(){cin >> n;root = new node[2*n+2];//从1开始,下标不会为0,与双亲冲突for (int i = 1; i <= n; i++){cin >> root[i].weight;}}void findmin(int len, int& p1, int& p2){int min1 = 0x3f;int min2 = 0x3f;for (int i = 1; i < len; i++){//注意是独立的树!if (root[i].p == 0){if (root[i].weight < min1){min2 = min1;p2 = p1;min1 = root[i].weight;p1 = i;}else if (root[i].weight < min2){min2 = root[i].weight;p2 = i;}}}}void hatree(){int p1 = 0, p2 = 0;for (int i = n+1; i < 2 * n; i++){findmin(i, p1, p2);root[i].l = p1;root[i].r = p2;root[p1].p = i;root[p2].p = i;root[i].weight = root[p1].weight + root[p2].weight;}}void hacode(){for (int i = 1; i <= n; i++){for (int c = i, f = root[i].p; f != 0; c = f, f = root[f].p){if (root[f].l == c){(root + i)->code = '0' + (root + i)->code;}else{(root + i)->code = '1' + (root + i)->code;}}}}void show(){for (int i = 1; i <= n; i++){cout << root[i].weight <<"-" << root[i].code << endl;}}
};
int main()
{tree t;t.hatree();t.hacode();t.show();return 0;
}
E. DS图—最小生成树
题目描述
根据输入创建无向网。分别用Prim算法和Kruskal算法构建最小生成树。(假设:输入数据的最小生成树唯一。)
输入
顶点数n
n个顶点
边数m
m条边信息,格式为:顶点1顶点2权值
Prim算法的起点v
输出
输出最小生成树的权值之和
对两种算法,按树的生长顺序,输出边信息(Kruskal中边顶点按数组序号升序输出)
样例查看模式
正常显示查看格式
输入样例1
6\n
v1 v2 v3 v4 v5 v6 \n
10\n
v1 v2 6\n
v1 v3 1\n
v1 v4 5\n
v2 v3 5\n
v2 v5 3\n
v3 v4 5\n
v3 v5 6\n
v3 v6 4\n
v4 v6 2\n
v5 v6 6\n
v1\n
输出样例1
15\n
prim:\n
v1 v3 1\n
v3 v6 4\n
v6 v4 2\n
v3 v2 5\n
v2 v5 3\n
kruskal:\n
v1 v3 1\n
v4 v6 2\n
v2 v5 3\n
v3 v6 4\n
v2 v3 5\n
AC代码
#include<iostream>
#include<map>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 1000, inf = 0x3f3f3f;
int g[N][N];
int n, m;
map<string, int>mp;
map<int, string>mm;
struct node
{int u, v, w;
};
vector<node>edge;
vector<node>edges;
int fa[N];
bool cmp(const node& a, const node& b)
{return a.w < b.w;
}
void Prim(int x)
{int len = inf;int end = 0;int sum = 0;int k = 0;vector<node>temp(n + 1);//temp[i].u表:i点连接u点//temp[i].w表:i到u的距离for (int i = 1; i <= n; i++){temp[i].u = x;temp[i].w = g[x][i];}temp[x].w = 0;for (int i = 1; i < n; i++){len = inf;//找到x到某点j的最小距离for (int j = 1; j <= n; j++){if (temp[j].w && temp[j].w < len){len = temp[j].w;end = j;}}sum += len;//更新添加记录边edge[k].u = temp[end].u;edge[k].v = end;edge[k].w = len;k++;//加入后更新for (int j = 1; j <= n; j++){if (temp[j].w && temp[j].w > g[end][j]){temp[j].w = g[end][j];temp[j].u = end;}}temp[end].w = 0;}cout << sum << endl;for (int i = 0; i < n - 1; i++){cout << mm[edge[i].u] << " " << mm[edge[i].v] << " " << edge[i].w << endl;}
}
int find(int x)
{if (x != fa[x])fa[x] = find(fa[x]);return fa[x];
}
void kuskal()
{cout << "kruskal:" << endl;for (int i = 0; i < m; i++){int p1 = find(edges[i].u);int p2 = find(edges[i].v);if (p1 != p2){fa[p1] = p2;cout << mm[min(edges[i].u, edges[i].v)] << " "<< mm[max(edges[i].u, edges[i].v)] << " "<< edges[i].w << endl;}}
}
int main()
{memset(g, inf, sizeof(g));cin >> n;for (int i = 1; i <= n; i++){fa[i] = i;string s;cin >> s;mp[s] = i;mm[i] = s;}cin >> m;edge.resize(m);for (int i = 0; i < m; i++){string s1, s2;int c;cin >> s1 >> s2 >> c;g[mp[s1]][mp[s2]] =g[mp[s2]][mp[s1]] = c;edge[i].u = min(mp[s1], mp[s2]);edge[i].v = max(mp[s1], mp[s2]);edge[i].w = c;}sort(edge.begin(), edge.end(), cmp);edges = edge;string start;cin >> start;//Prim算法有起点Prim(mp[start]);kuskal();return 0;
}
F. 层次遍历叶子节点
题目描述
给定一颗二叉树的逻辑结构如下图,(先序遍历的结果,空树用字符‘0’表示,例如AB0C00D00),建立该二叉树的二叉链式存储结构,并层次遍历该二叉树的叶子节点
层次遍历是指从先从上往下,再从左到右的遍历二叉树节点
例如上图的遍历叶子的结果是D C
层次遍历二叉树算法如下,请改造成层次遍历叶子算法
初始设置:创建空队列Q,设T是根结点的指针,p是二叉树结点类型指针,初始操作时根结点T入队,执行以下循环:
(1)队首元素出队到p;
(2)访问p所指向的结点;(访问操作可以定义输出、比较、判断.......,根据题目要求来定义)
(3)p所指向的结点的左、右子结点依次入队。
(4)跳转步骤1循环,直到队空为止
输入
第一行输入一个整数t,表示有t个二叉树
第二行起输入每个二叉树的包含空树的先序遍历结果,空树用字符‘0’表示,连续输入t行
输出
输出每个二叉树的叶子的层次遍历结果,
每行结果输出叶子的数值,并且用空格隔开,最后一个叶子输出后也带空格再换行
样例查看模式
正常显示查看格式
输入样例1 <
2\n
AB0C00D00\n
ABD000C0E00\n
输出样例1
D C \n
D E
AC代码
#include<iostream>
#include<queue>
using namespace std;
struct node
{char data;node* l;node* r;node(){data = '0';l = NULL;r = NULL;}
};
class tree
{node* root;int cnt;void create(node*& root){char x;cin >> x;if (x == '0'){root = NULL;return;}root = new node;root->data = x;create(root->l);create(root->r);}void post(node* root){if (!root){return;}post(root->l);post(root->r);cout << root->data;}void mid(node* root){if (!root){return;}mid(root->l);cout << root->data;mid(root->r);}void Delete(node* root){if (!root){delete root;return;}Delete(root->l);Delete(root->r);delete root;}void child(node* root){if (!root){return;}if (!root->l && !root->r){cout << root->data << " ";}child(root->l);child(root->r);}void parent(node* root){if (!root){return;}parent(root->l);parent(root->r);if (root->l && !root->l->r && !root->l->l){cout << root->data << " ";}if (root->r && !root->r->r && !root->r->l){cout << root->data << " ";}}
public:tree(){cnt = 0;root = NULL;}void create_tree(){create(root);}~tree(){Delete(root);}void posorder(){post(root);cout << endl;}void midorder(){mid(root);cout << endl;}void find_child(){child(root);cout << endl;}void find_parent(){parent(root);cout << endl;}void lerver(){queue<node*>q;q.push(root);while (!q.empty()){auto t = q.front();q.pop();if (!t->l && !t->r){cout << t->data << " ";}if (t->l){q.push(t->l);}if (t->r){q.push(t->r);}}cout << endl;}
};
int main()
{int t;cin >> t;while (t--){tree tt;tt.create_tree();tt.lerver();}return 0;
}
G. DS线性表—多项式相加
时间限制1s
内存限制128MB
题目描述
对于一元多项式p(x)=p0+p1x+p2x2+…+pnxn,每个项都有系数和指数两部分,例如p2x2的系数为p2,指数为2。
编程实现两个多项式的相加。
例如5+x+2x2+3x3,-5-x+6x2+4x4,两者相加结果:8x2+3x3+4x4
其中系数5和-5都是x的0次方的系数,相加后为0,所以不显示。x的1次方同理不显示。
要求用单链表实现。
输入
第1行:输入t表示有t组测试数据
第2行:输入n表示有第1组的第1个多项式包含n个项
第3行:输入第一项的系数和指数,以此类推输入n行
接着输入m表示第1组的第2个多项式包含m项
同理输入第2个多项式的m个项的系数和指数
参考上面输入第2组数据,以此类推输入t组
假设所有数据都是整数
输出
对于每1组数据,先用两行输出两个原来的多项式,再用一行输出运算结果,不必考虑结果全为0的情况
输出格式参考样本数据,格式要求包括:
1.如果指数或系数是负数,用小括号括起来。
2.如果系数为0,则该项不用输出。
3.如果指数不为0,则用符号^表示,例如x的3次方,表示为x^3。
4.多项式的每个项之间用符号+连接,每个+两边加1个空格隔开。
样例查看模式
正常显示查看格式
输入样例1
2\n
4\n
5 0\n
1 1\n
2 2\n
3 3\n
4\n
-5 0\n
-1 1\n
6 2\n
4 4\n
3\n
-3 0\n
-5 1\n
2 2\n
4\n
9 -1\n
2 0\n
3 1\n
-2 2\n
输出样例1
5 + 1x^1 + 2x^2 + 3x^3\n
(-5) + (-1)x^1 + 6x^2 + 4x^4\n
8x^2 + 3x^3 + 4x^4\n
(-3) + (-5)x^1 + 2x^2\n
9x^(-1) + 2 + 3x^1 + (-2)x^2\n
9x^(-1) + (-1) + (-2)x^1\n
\n
AC代码
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
void display(vector<pair<int, int>>v)
{for (int i = 0; i < v.size(); i++){if (v[i].second == 0)continue;else if (v[i].second < 0){cout << "(" << v[i].second << ")";}else cout << v[i].second;if (v[i].first == 0){if (i != v.size() - 1&&v[i+1].second!=0)cout << " + ";continue;}else if (v[i].first < 0){cout << "x^(" << v[i].first << ")";if (i != v.size() - 1 && v[i+1].second != 0)cout << " + ";}else{cout << "x^" << v[i].first; if (i != v.size() - 1 && v[i+1].second != 0)cout << " + ";}}cout << endl;
}
int main()
{int t;cin >> t;while (t--){int n;cin >> n;vector<pair<int, int>>v1;vector<pair<int, int>>v2;vector<pair<int, int>>ans;for (int i = 0; i < n; i++){int x, y;cin >> x >> y;v1.push_back({ y,x });}cin >> n;for (int i = 0; i < n; i++){int x, y;cin >> x >> y;v2.push_back({ y,x });}sort(v1.begin(), v1.end());sort(v2.begin(), v2.end());display(v1);display(v2);//n为v2的for (int i = 0; i < n; i++){bool flag = 0;for (int j = 0; j < v1.size(); j++){if (v1[j].first == v2[i].first){ans.push_back({ v2[i].first,v1[j].second + v2[i].second });flag = 1;break;}}if (!flag){ans.push_back({ v2[i].first,v2[i].second });}}for (int j = 0; j < v1.size(); j++){bool flag = 0;for (int i = 0; i < ans.size(); i++){if (ans[i].first == v1[j].first){flag = 1;break;}}if (!flag){ans.push_back({ v1[j].first,v1[j].second });}}sort(ans.begin(), ans.end());display(ans);}cout << endl;return 0;
}