问题 A 任意二叉树的层次遍历
有若干个节点,每个节点上都有编号,把这些节点随意地构成二叉树,请编程输出该二叉树的层次遍历序列。
输入:第一行是n(n小于100),表示有n个节点,每个节点按从1到n依次编号。第一行后有n行,每行三个正整数i、l、r,分别表示节点i及对应的左右孩子的编号,如果不存在孩子则以-1表示。三个整数之间用一个空格隔开。
输出:该二叉数的层次遍历序列。
样例输入:
4
1 2 4
3 1 -1
2 -1 -1
4 -1 -1
样例输出:
3 1 2 4
#include<iostream>
#include<stack>
#include<queue>
#include<string>
using namespace std;
struct node {
char a;
node* left;
node* right;
node() { left = right = NULL; }
};
struct work {
int a, b, val;
};
node* convert(work* x, int a) {
node* p = new node;
p->a = x[a].val+'0';
if (x[a].a != -1) { p->left = convert(x, x[a].a); }
if (x[a].b != -1) { p->right = convert(x, x[a].b); }
return p;
}
class tree {
node* root;
public:
tree() { root = new node; }
void create() {
int n; cin >> n; int r;
work* x = new work[n];
for (int i = 0; i < n; i++)
cin >> x[i].val >> x[i].a >> x[i].b;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (x[i].val == x[j].a) {
x[j].a = i;
break;
}
else if (x[i].val == x[j].b) {
x[j].b = i;
break;
}
if (j == n - 1)
r=i;
}
}
root = convert(x, r);
}
void qx(node *q) {
cout << q->a ;
if (q->left != NULL)qx(q->left);
if (q->right != NULL)qx(q->right);
}
void zx(node* q) {
if (q->left != NULL)zx(q->left);
cout << q->a;
if (q->right != NULL)zx(q->right);
}
void hx(node* q) {
if (q->left != NULL)hx(q->left);
if (q->right != NULL)hx(q->right);
cout << q->a;
}
void ccbl(node* q) {
queue<node>s;
s.push(*q);
node* p;
while(!s.empty()){
p = &s.front();
cout << p->a << ' ';
if (p->left != NULL) {
s.push(*p->left);
}
if (p->right != NULL) {
s.push(*p->right);
}
s.pop();
}
}
node* getr() { return root; }
};
int* test(int n) {
int* x = new int[n];
for (int i = 0; i < n; i++)
cin >> x[i];
return x;
}
int main() {
tree a;
a.create();
a.ccbl(a.getr());
}
问题 B: 小根堆的判定
题目描述
堆是以线性连续方式存储的完全二叉树,小根堆的每一个元素都不大于其左右孩子,现在给你n个完全二叉树数组存储序列,请编程判定相应完全二叉树数组存储序列是否为小根堆。
输入
第一行n(n<100),表示有n组测试用例。后边的n行,每一行都是相应完全二叉树数组存储序列(序列最长为100)。
输出
对应相应完全二叉树数组存储序列,判定为小根堆的输出True,否则输出False。
样例输入
2
30 26 27 88
5 6 7 8 9 10
样例输出
False
True
#include<iostream>
#include<string>
using namespace std;
int main()
{
int n; cin >> n;
int x[100][500],y[100];
for (int i = 0; i < n; i++) {
int k = 0;
while (1) {
cin >> x[i][k++];
if (cin.get() == '\n')break;
}
y[i] = k;
}
for (int i = 0; i < n; i++) {
bool flag(true); int j = 0;
int m = y[i]-1;
while (flag) {
if (2 * j + 1 > m)break;
if (x[i][j] > x[i][2 * j + 1]) {
flag = 0; break;
}
if (2 * j + 2 > m)break;
if (x[i][j] > x[i][2 * j + 2]) {
flag = 0; break;
}
j++;
}
if (!flag)cout << "False" << endl;
else { cout << "True" << endl; }
}
}
问题 C: 最小堆的形成
题目描述
现在给你n个结点的完全二叉树数组存储序列,请编程调整为最小堆,并输出相应最小堆的存储序列。
输入
第一行是n,第二行是n个结点的完全二叉树数组存储序列。
输出
输出相应最小堆的存储序列。
样例输入
8
53 17 78 23 45 65 87 9
样例输出
9 17 65 23 45 78 87 53
#include<iostream>
#include<string>
using namespace std;
void swap(int *x,int n,int k) {
if (2 * k + 1 < n) {
swap(x, n, 2 * k + 1);
if (x[2 * k + 1] < x[k]) {
int temp(x[k]);
x[k] = x[2 * k + 1];
x[2 * k + 1] = temp;
}
swap(x, n, 2 * k + 1);
}
if (2 * k + 2 < n) {
swap(x, n, 2 * k + 2);
if (x[2 * k + 2] < x[k]) {
int temp(x[k]);
x[k] = x[2 * k + 2];
x[2 * k + 2] = temp;
}
swap(x, n, 2 * k + 2);
}
}
int main()
{
int n; cin >> n;
int* x = new int[n];
for (int i = 0; i < n; i++) {
cin >> x[i];
}
swap(x, n, 0);
for (int i = 0; i < n; i++) {
cout << x[i] << ' ';
}
}
问题 D 无向图的深度优先搜索
题目描述
已知一个无向图G的顶点和边,顶点从0依次编号,现在需要深度优先搜索,访问任一邻接顶点时编号小的顶点优先,请编程输出图G的深度优先搜索序列。
输入
第一行是整数m和n(1<m,n<100),分别代表顶点数和边数。后边n行,每行2个数,分别表示一个边的两个顶点。
输出
该图从0号顶点开始的深度优先搜索序列。
样例输入
5 5
0 1
2 0
1 3
1 4
4 2
样例输出
0 1 3 4 2
没用栈,感觉用栈太麻烦了
#include<iostream>
using namespace std;
void sd(bool**x,bool*y,int a,int n) {
if (y[a] == 0) {
cout << a << ' ';
y[a] = true;
}
for (int i = 0; i < n; i++) {
if (x[a][i] == 1&&y[i]==0)sd(x,y,i,n);
}
}
int main()
{
int n, m; cin >> n >> m;//顶点和边数
bool** x = new bool*[n];
bool* y = new bool[n];
for (int i = 0; i < n; i++) {
x[i] = new bool[n];
for (int j = 0; j < n; j++) {
x[i][j] = 0;
}
y[i] = 0;
}
for (int i = 0; i < m; i++) {
int a, b; cin >> a >> b;
x[a][b] = x[b][a] = 1;
}
sd(x, y, 0, n);
}
问题 E: 无向图的广度优先搜索
题目描述
已知一个无向图G的顶点和边,顶点从0依次编号,现在需要广度优先搜索,访问任一邻接顶点时编号小的顶点优先,请编程输出图G的广度优先搜索序列。
输入
第一行是整数m和n(1<m,n<100),分别代表顶点数和边数。后边n行,每行2个数,分别表示一个边的两个顶点。
输出
该图从0号顶点开始的广度优先搜索序列。
样例输入
5 5
0 1
2 0
1 3
1 4
4 2
样例输出
0 1 2 3 4
#include<iostream>
#include<queue>
using namespace std;
queue<int>s;
void gd(bool**x,bool*y,int a,int n) {
while (!s.empty()) {
int q = s.front();
cout << q << ' ';
s.pop();
for (int i = 0; i < n; i++) {
if (x[q][i] == 1&&y[i]==0) {
s.push(i); y[i] = 1;
}
}
}
}
int main()
{
int n, m; cin >> n >> m;//顶点和边数
bool** x = new bool*[n];
bool* y = new bool[n];
for (int i = 0; i < n; i++) {
x[i] = new bool[n];
for (int j = 0; j < n; j++) {
x[i][j] = 0;
}
y[i] = 0;
}
for (int i = 0; i < m; i++) {
int a, b; cin >> a >> b;
x[a][b] = x[b][a] = 1;
}
s.push(0); y[0] = 1;
gd(x, y, 0, n);
}
问题 F 最小生成树
已知一个无向图G的顶点和边,顶点从0依次编号,请编程输出图G的最小生成树对应的边权之和。
第一行是整数m和n(1<m,n<100),分别代表顶点数和边数。后边n行,每行3个数,分别表示一个边的两个顶点和该边的权值。
最小生成树对应的边权之和。
4 5
0 1 6
0 2 9
2 1 12
1 3 10
3 2 3
18
#include<iostream>
#include<queue>
using namespace std;
int minval(bool*y,int **z,int n) {
int amin = 0, mini=0, min;
for (int o = 0; o < n - 1; o++) {
min = 5000;
for (int j = 0; j < n; j++) {
int mintemp=5000,minitemp;
if (y[j] == 1) {
int i;
for (i = 0; i < n; i++)
{
if (y[i] == 1)continue;
if (z[j][i] < mintemp) {
mintemp = z[j][i];
minitemp = i;
}
}
}
else continue;
if (min > mintemp) {
min = mintemp;
mini = minitemp;
}
}
y[mini] = 1;
amin += min;
}
return amin;
}
int main()
{
int n, m; cin >> n >> m;//顶点和边数
bool** x = new bool*[n];
bool* y = new bool[n];
int** z = new int* [n];
for (int i = 0; i < n; i++) {
x[i] = new bool[n]; z[i] = new int[n];
for (int j = 0; j < n; j++) {
x[i][j] = 0;
z[i][j] = 9999;
}
y[i] = 0;
}
for (int i = 0; i < m; i++) {
int a, b,val; cin >> a >> b>>val;
z[a][b] = z[b][a] = val;
}
y[0] = 1;
cout << minval( y, z, n);
}
把0写成o了,是说for循环怎么出不去QAQ