数据结构实验

目录

一.

问题 A: 一排里的位置交换

问题 B: 围成圈

问题 C: 十进制整数转二进制

问题 D: 进出栈

问题 E: 栈容量

问题 F: 自创语言

问题 G: 离队

二.

问题 A: 满二叉树的前序遍历

问题 B: 满二叉树的中序遍历

问题 C: 满二叉树的后序遍历

问题 D: 任意二叉树的前序遍历

问题 E: 任意二叉树的中序遍历

问题 F: 任意二叉树的后序遍历

问题 G: FBI树

问题 H: 满二叉树的深度

三.

问题 A: 任意二叉树的层次遍历

问题 B: 小根堆的判定

问题 C: 最小堆的形成

问题 D: 无向图的深度优先搜索

问题 E: 无向图的广度优先搜索

问题 F: 最小生成树

四.

问题 A: 折半查找的次数

问题 B: 二叉搜索树中的查找

问题 C: 有向图的最短路径长度

问题 D: 有向图的最短路径

问题 E: 5个数的从大到小排序

问题 F: 病人排队

一.

问题 A: 一排里的位置交换

题目描述

体育课上,老师把一排里的两个身高不同的同学的位置交换了一下以方便安排分组训练。你能编程模拟这个过程吗?

输入

第一行是自然数n(n小于100),表示有n个数,第二行是n个表示身高的数据,第三行是要交换的两个同学的序号(按左起从1开始依次排序)。

输出

交换位置后的一排身高值。中间用空格间隔。

样例输入 

5
152 155 120 145 160
2 5

样例输出 

152 160 120 145 155

#include<iostream>
#include<algorithm>
using namespace std;
int main() {
	int n, a[101], x, y;
	scanf_s("%d", &n);
	for (int i = 1; i <= n; i++)scanf_s("%d", &a[i]);
	scanf_s("%d%d", &x, &y);
	swap(a[x], a[y]);
	for (int i = 1; i <= n; i++)printf("%d ", a[i]);
	return 0;
}

问题 B: 围成圈

题目描述

假如有一次班里组织户外活动,同学们随机围坐成一圈做游戏,每个同学都记住了左右同学的编号,活动结束后,老师想让你帮忙复原当时大家坐的位置,你能通过每个同学记录的左右同学的编号,把当时大家坐的一圈情况复原吗?

输入

第一行是人数n(n<100)。从第二行开始n行,分别表示1-n编号的同学左右两个同学的编号。最后一行某个同学的编号K。

输出

围坐的这个圈里,从第K个同学开始顺时针的序列。

样例输入 

5
4 5
5 3
2 4
3 1
1 2
3

样例输出 

3 2 5 1 4

#include<iostream>
#include<cmath>
using namespace std;
int q1[101],q2[101],front=1,rear=0;
int main()
{
    int n,x;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>q1[++rear]>>q2[rear];
    }cin>>x;
    for(int i=1;i<=n;i++){
        cout<<x<<' ';
        x=q1[x];
    }
    return 0;
}

问题 C: 十进制整数转二进制

题目描述

二进制是计算机运算的基础,给你一个十进制整数,你能编程实现转二进制吗?

输入

第一行n,表示接着下边有n个十进制整数,每个占一行。

输出

对应每个十进制整数输出相应二进制数占一行。

样例输入 

2
5
16

样例输出 

101
10000

#include<iostream>
#include<algorithm>
using namespace std;
void change10_2(int t) {
	if (t / 2 != 0)change10_2(t / 2);
	printf("%d", t % 2);
}
int main() {
	int n, x;
	scanf_s("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf_s("%d", &x);
		change10_2(x);
		printf("\n");
	}
	return 0;
}
#include<iostream>
#include<cmath>
using namespace std;
int s[100000], ani = 0, e = 0;
int change10_2(int t) {
    ani = 0, e = 0;
    while (t) {
        s[++ani] = t % 2;
        t /= 2;
    }while (ani) {
        e += s[ani] * pow(10, ani - 1);
        ani--;
    }
    return e;
}
int main()
{
    int n, x;
    scanf_s("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf_s("%d", &x);
        int temp = change10_2(x);
        printf("%d\n", temp);
    }
    return 0;
}

问题 D: 进出栈

题目描述

设栈S的初始状态为空,元素a, b, c, d, e, f, g 依次入栈,给你一个出栈序列,请编程判断出栈序列是否正确。

输入

占一行,为出栈序列。

输出

如果出栈学列是可能的,输出True,否则输出False。

样例输入 

a b c d e f g

样例输出 

True

#include<iostream>
using namespace std;
char s1[8], s2[8];
int top1 = 0, top2 = 0;
int main()
{
    int t = 0;
    for (int i = 1; i <= 7; i++) {
        cin >> s2[++top2];
        while (s1[top1] != s2[top2]) {
            if (t == 7) {
                printf("False");
                return 0;
            }s1[++top1] = (char)97 + t;
            t++;
        }top2--, top1--;
    }printf("True");
    return 0;
}

问题 E: 栈容量

题目描述

设栈S的初始状态为空,元素a,b,c,d,e,f,g依次入栈,出栈顺序为b,d,c,f,e,a,g那么栈容量至少应该是3。如果任意给你一个出栈序列,你能编程判断相应的栈容量至少是多少吗?

输入

元素a,b,c,d,e,f,g依次入栈情况下的一种出栈序列。

输出

对应出栈序列的栈容量至少是多少。

样例输入 

b d c f e a g

样例输出 

3

#include<iostream>
using namespace std;
char s1[8], s2[8];
int top1 = 0, top2 = 0, t = 0;
int main() {
	int maxtop = 0;
	for (int i = 1; i <= 7; i++) {
		cin >> s2[++top2];
		while (s1[top1] != s2[top2]) {
			s1[++top1] = t + 'a';
			t++;
			maxtop = max(maxtop, top1);
		}top1--, top2--;
	}printf("%d", maxtop);
	return 0;
}

问题 F: 自创语言

题目描述

学了一段英语课之后,小名同学发现英语单词就是26个字母中若干个组合在一起的,于是他想自己也创立一种语言,为了简化单词,他计划只选26个小写字母的前n个符号构造长度也为n个符号的单词,构造好单词后,先要编写个词典,给每个单词有个解释以便人们学习他自创的语言。你能编程帮助按字典序输出所有长度为n的单词吗?

输入

占一行,为整数n(n<26)。

输出

所有由前n个符号构造长度也为n个符号的单词,按字典序每行输出一个单词。

样例输入 

2

样例输出 

aa
ab
ba
bb

#include<iostream>
using namespace std;
int front = 1, rear = 0, n;
char z[26], q[26];
void f(const int x, int t) {
    if (!t)return;

    for (int i = 1; i <= x; i++) {
        q[++rear] = z[i];
        f(x, t - 1);
        if (t == 1) {
            while (front <= rear) {
                cout << q[front++];
            }printf("\n");
            front = 1;
        }rear--;
    }
}
int main() {
    for (int i = 1; i < 26; i++)z[i] = 'a' + i - 1;
    scanf_s("%d", &n);
    f(n, n);
    return 0;
}

问题 G: 离队

题目描述

体育课上,班上的同学排成了一排,结果有个同学突然感觉不适,需要去医院,就离队了,你能编程模拟离队后的状态吗?

输入

第一行是整数n(n<100),第二行有n个整数,第三行是k,表示从左开始第k个离队。

输出

输出离队后的数字序列。

样例输入 


120 125 135 126 145
3

样例输出 

120 125 126 145

#include<iostream>
#include<algorithm>
using namespace std;
int main() {
	int n, a[101], k; scanf_s("%d", &n);
	for (int i = 1; i <= n; i++)scanf_s("%d", &a[i]);
	scanf_s("%d", &k);
	for (int i = 1; i <= n; i++) {
		if(i!=k)printf("%d ", a[i]);
	}
	return 0;
}

二.

问题 A: 满二叉树的前序遍历

题目描述

给你一个满二叉树的层次遍历序列,请编程输出该二叉树的前序遍历序列。

输入

第一行是n(n小于26),表示有n个节点。第二行是该满二叉树的节点对应字母的层次遍历序列。

输出

输出该满二叉数的前序遍历序列。

样例输入 

3
B A C

样例输出 

BAC

#include<iostream>
using namespace std;
struct TreeNode {
	char v;
	TreeNode* l, * r, * f;
}a[101];
void Preorder(TreeNode* x) {
	cout << x->v;
	if (x->l)Preorder(x->l);
	if (x->r)Preorder(x->r);
}
int main() {
	int n;
	scanf_s("%d", &n);
	for (int i = 1; i <= n; i++) {
		cin >> a[i].v;
		if (i % 2 == 0)a[i / 2].l = &a[i];
		else a[i / 2].r = &a[i];
	}Preorder(&a[1]);
	return 0;
}

问题 B: 满二叉树的中序遍历

题目描述

给你一个满二叉树的层次遍历序列,请编程输出该二叉树的中序遍历序列。

输入

第一行是n(n小于26),表示有n个节点。第二行是该满二叉树的节点对应字母的层次遍历序列。

输出

输出该满二叉数的中序遍历序列。

样例输入 

3
B A C

样例输出 

ABC

问题 C: 满二叉树的后序遍历

题目描述

给你一个满二叉树的层次遍历序列,请编程输出该二叉树的后序遍历序列。

输入

第一行是n(n小于26),表示有n个节点。第二行是该满二叉树的节点对应字母的层次遍历序列。

输出

输出该满二叉数的后序遍历序列。

样例输入 

3
B A C

样例输出 

ACB

问题 D: 任意二叉树的前序遍历

题目描述

有若干个节点,每个节点上都有编号,把这些节点随意地构成二叉树,请编程输出该二叉树的前序遍历序列。

输入

第一行是n(n小于100),表示有n个节点,每个节点按从1到n依次编号。第一行后有n行,每行三个正整数i、l、r,分别表示节点i及对应的左右孩子的编号,如果不存在孩子则以-1表示。三个整数之间用一个空格隔开。

输出

输出该二叉数的前序遍历序列。

样例输入 

1 2 4 

3 1 -1 

2 -1 -1 

4 -1 -1 

样例输出 

3 1 2 4

#include<iostream>
using namespace std;
struct TreeNode {
	int v;
	TreeNode* l, * r, * f;
}a[101];
void Preorder(TreeNode* x) {
	cout << x->v<<' ';
	if (x->l)Preorder(x->l);
	if (x->r)Preorder(x->r);
}
int main() {
	int n;
	scanf_s("%d", &n);
	int x, y, z;
	for (int i = 1; i <= n; i++) {
		scanf_s("%d%d%d", &x, &y, &z);
		a[x].v = x;
		if (y != -1)a[x].l = &a[y], a[y].f = &a[x];
		if (z != -1)a[x].r = &a[z], a[z].f = &a[x];
	}for (int i = 1; i <= n; i++) {
		if (!a[i].f) {
			Preorder(&a[i]);
			break;
		}
	}
	return 0;
}

问题 E: 任意二叉树的中序遍历

题目描述

有若干个节点,每个节点上都有编号,把这些节点随意地构成二叉树,请编程输出该二叉树的中序遍历序列。

输入

第一行是n(n小于100),表示有n个节点,每个节点按从1到n依次编号。第一行后有n行,每行三个正整数i、l、r,分别表示节点i及对应的左右孩子的编号,如果不存在孩子则以-1表示。三个整数之间用一个空格隔开。

输出

输出该二叉数的中序遍历序列。

样例输入 

4
1 2 4
3 1 -1
4 -1 -1
2 -1 -1

样例输出 

2 1 4 3

问题 F: 任意二叉树的后序遍历

题目描述

有若干个节点,每个节点上都有编号,把这些节点随意地构成二叉树,请编程输出该二叉树的后序遍历序列。

输入

第一行是n(n小于100),表示有n个节点,每个节点按从1到n依次编号。第一行后有n行,每行三个正整数i、l、r,分别表示节点i及对应的左右孩子的编号,如果不存在孩子则以-1表示。三个整数之间用一个空格隔开。

输出

输出该二叉数的后序遍历序列。

样例输入 

4
1 2 4
4 -1 -1
2 -1 -1
3 1 -1

样例输出 

2 4 1 3
 

问题 G: FBI树

题目描述

我们可以把由“0”和“1”组成的字符串分为三类:全“0”串称为 B 串,全“1”串称为 I 串,既含“0”又含“1”的串则称为 F 串。
FBI 树是一棵二叉树,它的结点类型也包括 F 结点,B 结点和 I 结点三种。由一个长度为 2N 的“01”串 S 可以构造出一棵 FBI 树 T,递归的构造方法如下:
(1) T 的根结点为 R,其类型与串 S 的类型相同;
(2) 若串 S 的长度大于 1,可将串 S 从中间分开,分为等长的左右子串 S1 和 S2;由左子串 S1 构造 R 的左子树 T1,由右子串 S2 构造 R 的右子树 T2。

现在给定一个长度为 2N 的“01”串,请用上述构造方法构造出一棵 FBI 树,并输出它的后序遍历序列。
 

输入

第一行是一个整数 N(0≤N≤10),第二行是一个长度为 2N 的“01”串。
 

输出

包括一行,这一行只包含一个字符串,即 FBI 树的后序遍历序列。

样例输入 


10001011

样例输出 

IBFBBBFIBFIIIFF

#include<iostream>
#include<cmath>
#include<string.h>
using namespace std;
struct TreeNode {
    char v[1025];
    char va;
    int ani;
    TreeNode* l, * r, * fa;
}a[1001];
void preorder(TreeNode* x) {
    if (x->l)preorder(x->l);
    if (x->r)preorder(x->r);
    cout << x->va;
}
bool v_find(TreeNode* a, char s) {
    cout << 's' << s << endl;
    for (int i = 0; i < a->ani; i++) {
        if (a->v[i] == s) {
            cout << i << ' ' << a->v[i] << 's' << s << endl;
            return 1;
        }
    }return 0;
}
int main() {
    int n;
    cin >> n;
    cin >> a[1].v;
    a[1].ani = pow(2, n);
    char s1[2] = "1", s0[2] = "0";
    bool flag1 = strstr(a[1].v, s1), flag2 = strstr(a[1].v, s0);
    if (flag1 && flag2) {
        a[1].va = 'F';
    }else if (flag1) {
        a[1].va = 'I';
    }else a[1].va = 'B';
    
    int m = pow(2, n + 1) - 1;
    for (int i = 2; i <= m; i++) {
        int t = a[i / 2].ani / 2;
        if (i % 2 == 0) {
            for (int j = 0; j < t; j++) {
                a[i].v[j] = a[i / 2].v[j];
            }a[i / 2].l = &a[i];
        }
        else {
            for (int j = t; j < a[i / 2].ani; j++) {
                a[i].v[j - t] = a[i / 2].v[j];
            }a[i / 2].r = &a[i];
        }a[i].ani = t;
        bool flag1 = strstr(a[i].v, s1), flag2 = strstr(a[i].v, s0);
        if (flag1 && flag2) {
            a[i].va = 'F';
        }else if (flag1) {
            a[i].va = 'I';
        }else a[i].va = 'B';
    }preorder(&a[1]);
    return 0;
}

问题 H: 满二叉树的深度

题目描述

给你一个满二叉树的层次遍历序列,请编程输出该二叉树的深度。

输入

第一行是n(n小于26),表示有n个节点。第二行是该满二叉树的节点对应字母的层次遍历序列。

输出

输出该满二叉数的深度。

样例输入 

3
B A C

样例输出 

2

#include<iostream>
using namespace std;
struct TreeNode {
	char v;
	TreeNode* l, * r, * f;
	int d;
}a[101];
int main() {
	int n;
	scanf_s("%d", &n);
	a[1].d = 1;
	for (int i = 1; i <= n; i++) {
		cin >> a[i].v;
		if (i % 2 == 0)a[i / 2].l = &a[i];
		else a[i / 2].r = &a[i];
		a[i].d = a[i / 2].d + 1;
	}printf("%d", a[n].d);
	return 0;
}

三.

问题 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>
using namespace std;
struct TreeNode {
	int v;
	TreeNode* l, * r, * f;
}a[101],q[101];
int front = 1, rear = 0;
int main() {
	int n;
	scanf_s("%d", &n);
	int x, y, z;
	for (int i = 1; i <= n; i++) {
		scanf_s("%d%d%d", &x, &y, &z);
		a[x].v = x;
		if (y != -1)a[x].l = &a[y], a[y].f = &a[x];
		if (z != -1)a[x].r = &a[z], a[z].f = &a[x];
	}for (int i = 1; i <= n; i++) {
		if (!a[i].f) {
			q[++rear] = a[i];
			while (front <= rear) {
				if (q[front].l)q[++rear] = *q[front].l;
				if (q[front].r)q[++rear] = *q[front].r;
				printf("%d ", q[front].v);
				front++;
			}
			break;
		}
	}
	return 0;
}

问题 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>
using namespace std;
int n;
int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		int h[101], f = 1;
		for (int j = 1; 1; j++) {
			cin >> h[j];
			if (j != 1 && h[j] < h[j / 2]) {
				f = 0;
				break;
			}if (cin.get() == '\n') {
				break;
			}
		}if (f)cout << "True" << endl;
		else cout << "False" << endl;
	}
	return 0;
}

问题 C: 最小堆的形成

题目描述

现在给你n个结点的完全二叉树数组存储序列,请编程调整为最小堆,并输出相应最小堆的存储序列。

输入

第一行是n,第二行是n个结点的完全二叉树数组存储序列。

输出

输出相应最小堆的存储序列。

样例输入 

8
53 17 78 23 45 65 87 9

样例输出 

9 17 65 23 45 78 87 53

#include<iostream>
#include<algorithm>
using namespace std;
int h[101], len = 0;
void up(int k) {
	while (k > 1 && h[k] < h[k / 2]) {
		swap(h[k], h[k/2]);
		k /= 2;
	}
}
void insert_x(int x) {
	h[++len] = x;
	up(len);
}
int main()
{
	int n, x;
	scanf_s("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf_s("%d", &x);
		insert_x(x);
	}for (int i = 1; i <= n; i++) {
		printf("%d ", h[i]);
	}
	return 0;
}

问题 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;
int edge[101][101],n, m;
bool b[101] = { 0 };
void dfs(int t) {
	printf("%d ", t);
	for (int i = 1; i <= n; i++) {
		if (!b[i] && edge[t][i]) {
			b[i] = 1;
			dfs(i);
		}
	}
}
int main()
{
	scanf_s("%d%d", &n, &m);
	int x, y;
	for (int i = 1; i <= m; i++) {
		scanf_s("%d%d", &x, &y);
		edge[x][y] = 1, edge[y][x] = 1;
	}dfs(0);
	return 0;
}

问题 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>
using namespace std;
int n, m, edge[101][101], x, y;
bool b[101];
int main() {
	scanf_s("%d%d", &n, &m);
	for (int i = 1; i <= m; i++) {
		scanf_s("%d%d", &x, &y);
		edge[x][y] = 1, edge[y][x] = 1;
	}int q[101], front = 1, rear = 0;
	q[++rear] = 0,b[0]=1;
	while (front <= rear) {
		for (int i = 1; i <= n; i++) {
			if (!b[i] && edge[q[front]][i]) {
				q[++rear] = i;
				b[i] = 1;
			}
		}front++;
	}for (int i = 1; i <= n; i++)printf("%d ", q[i]);
	return 0;
}

问题 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<algorithm>
using namespace std;
int n, m, fa[101];
struct Node {
	int x, y, v;
	bool operator<(const Node& A)const {
		return v < A.v;
	}
}a[101];
int findset(int k) {
	if (fa[k] == k)return k;
	return fa[k]=findset(fa[k]);
}void Kruskal() {
	for (int i = 1; i <= n; i++)fa[i] = i;
	sort(a + 1, a + m + 1);
	int ans = 0;//边权
	for (int i = 1; i <= m; i++) {
		int x = findset(a[i].x), y = findset(a[i].y);
		if (x != y) {
			fa[x] = y;
			ans += a[i].v;
		}
	}printf("%d", ans);
}
int main() {
	scanf_s("%d%d", &n, &m);
	for (int i = 1; i <= m; i++) {
		scanf_s("%d%d%d", &a[i].x, &a[i].y, &a[i].v);
	}Kruskal();
	return 0;
}

四.

问题 A: 折半查找的次数

题目描述

给你一个无重复数的有序序列,如果采用折半查找的方式,对于给定的数,需要比较几次找到,请编程实现。

输入

第一行是N,表示序列中数的个数,序列最长1000,第二行是一个有序序列,第三行是要找的数x。

输出

如果找到x,输出折半比较的次数,否则输出NO。

样例输入 

11
5 13 19 21 37 56 64 75 80 88 92
19

样例输出 

2

#include<iostream>
using namespace std;
int main()
{
    int n, ans=0, a[1001];
    cin>>n;
    bool f=0;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }int l=1, h=n, x
    cin>>x;
    while(l<=h){
        int m=(l+h)/2;
        if(a[m]<x){
            l=m+1;
            if(l!=h)ans++;
        }
        else if(a[m]>x){
            h=m-1;
            if(l!=h)ans++;
        }
        else{
            ans++,f=1;
            break;
        }
    }if(f)cout<<ans;
    else cout<<"NO";
    return 0;
}

问题 B: 二叉搜索树中的查找

题目描述

给你一个数据序列,请构造一个二叉搜索树,然后计算出找到给定数据需比较的次数。

输入

第一行是N,表示序列中数的个数,序列最长1000,第二行是一个数据序列,第三行是要找的数x。

输出

如果找到x,输出比较的次数,没找到则输出NO。

样例输入 

5
1 2 3 5 4
5

样例输出 

4

#include<iostream>
#include<algorithm>
using namespace std;
int tree[1001] = { 0 };
int sum = 0, n, x, a[1001];
void insert(int x)
{
    int t = 1;//从根节点开始
    while (tree[t] != 0){
        if (tree[t] > x) t *= 2;
        else t = t * 2 + 1;
    }
    tree[t] = x;
}
int find_x(int y)
{
    int t = 1;
    if (*find(a, a + n, y)) {
        while (tree[t] != y || tree[t] == 0){
            sum++;
            if (tree[t] > y) t *= 2;
            else t = t * 2 + 1;
        }
        if (!tree[t]) return -1;
        else return sum + 1;
    }
    else return -1;
}
int main()
{
    cin >> n;
    for (int i = 0; i < n; i++){
        cin >> a[i];
        insert(a[i]);
    }
    cin >> x;
    int ans = find_x(x);
    if (ans != -1) cout << ans;
    else cout << "NO";
}

问题 C: 有向图的最短路径长度

题目描述

已知一个有向图,每个边都有一个正整数表示边长,请编程求出其中两个顶点间的最短路径长度。

输入

第一行是M、N,分别表示顶点数和有向边数(0<M,N<=100》),紧接着N行的每一行是X、Y、H,分别表示有向边的起点和终点以及边长。最后一行是要求其最短路径的两个顶点。

输出

相应两个顶点的最短路径值。

样例输入 

5 7
A B 10
B C 50
A E 100
A D 30
C E 10
D C 20
D E 60
A E

样例输出 

60

#include<iostream>
#include<vector>
#include<string.h>
using namespace std;
struct Node{
    char y;
    int v;
    Node(char _y,int _v){
        y=_y,v=_v;
    }
};
vector<Node>edge[1001];
int n,m,dist[1001];
char s,t;
bool b[1001];
char ans[1001],p[1001];
int s1=-1;
void dijkstra(char s,char t){
    memset(dist,127,sizeof(dist));
    dist[(int)s]=0;
    memset(b,false,sizeof(b));
    while(1){
        int x=-1;
        for(int i=(int)'A';i<=(int)'A'+n;i++){
            if(!b[i]&&dist[i]<1<<30){
                if(x==-1||dist[x]>dist[i]){
                    x=i;
                }
            }
        }b[x]=1;
        if(x==(int)t||x==-1)
            break;
        for(int i=0;i<edge[x].size();i++){
            Node te=edge[x][i];
            if(!b[te.y]){
                if(dist[te.y]>dist[x]+te.v){
                    dist[te.y]=dist[x]+te.v;
                    ans[(int)te.y]=x;
                }
            }
        }
        }if(dist[t]<1<<30){
            printf("%d",dist[t]);
    }
}
int main()
{
    cin>>n>>m;
    int z;
    char x,y;
    for(int i=1;i<=m;i++){
        cin>>x>>y>>z;
        edge[x].push_back(Node(y,z));
        //cout<<i<<endl;
    }cin>>s>>t;
    dijkstra(s,t);
 
    return 0;
}

问题 D: 有向图的最短路径

题目描述

已知一个有向图,每个边都有一个正整数表示边长,请编程求出其中两个顶点间的最短路径长度。

输入

第一行是M、N,分别表示顶点数和有向边数(0<M,N<=100》),紧接着N行的每一行是X、Y、H,分别表示有向边的起点和终点以及边长。最后一行是要求其最短路径的两个顶点。

输出

相应两个顶点的最短路径经过的顶点序列。

样例输入 

5 7
A B 10
B C 50
A E 100
A D 30
C E 10
D C 20
D E 60
A E

样例输出 

A D C E

#include<iostream>
#include<vector>
#include<string.h>
using namespace std;
struct Node{
    char y;
    int v;
    Node(char _y,int _v){
        y=_y,v=_v;
    }
};
vector<Node>edge[1001];
int n,m,dist[1001];
char s,t;
bool b[1001];
char ans[1001],p[1001];
int s1=-1;
void dijkstra(char s,char t){
    memset(dist,127,sizeof(dist));
    dist[(int)s]=0;
    memset(b,false,sizeof(b));
    while(1){
        int x=-1;
        for(int i=(int)'A';i<=(int)'A'+n;i++){
            if(!b[i]&&dist[i]<1<<30){
                if(x==-1||dist[x]>dist[i]){
                    x=i;
                }
            }
        }b[x]=1;
        if(x==(int)t||x==-1)
            break;
        for(int i=0;i<edge[x].size();i++){
            Node te=edge[x][i];
            if(!b[te.y]){
                if(dist[te.y]>dist[x]+te.v){
                    dist[te.y]=dist[x]+te.v;
                    ans[(int)te.y]=x;
                }
            }
        }if(dist[t]<1<<30){
            //printf("%d\n",dist[t]);
            p[++s1]=t;
            for(int i=(int)t;i!=(int)s;){
                p[++s1]=(char)i;
                i=(int)ans[i];
            }p[++s1]=s;
             
        }
    }
}
int main()
{
    cin>>n>>m;
    int z;
    char x,y;
    for(int i=1;i<=m;i++){
        cin>>x>>y>>z;
        edge[x].push_back(Node(y,z));
        //cout<<i<<endl;
    }cin>>s>>t;
    dijkstra(s,t);
    for(int i=s1;p[i+1]!=t;i--){
                cout<<p[i]<<' ';
            }
    return 0;
}

问题 E: 5个数的从大到小排序

题目描述

数学课上,老师公布了一个小组的5名同学的成绩,你能编程把成绩从大到小排序吗,以便老师知道考试名次?

输入

5个整数,用空格间隔开。

输出

从大到小的5个数,中间用空格间隔。

样例输入

86 78 99 100 66

样例输出 

100 99 86 78 66

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
    int a[5];
    for(int i=0;i<5;i++)scanf("%d",&a[i]);
    sort(a,a+5);
    for(int i=4;i>-1;i--)printf("%d ",a[i]);
    return 0;
}

问题 F: 病人排队

问题描述

病人登记看病,编写一个程序,将登记的病人按照以下原则排出看病的先后顺序: 

1.老年人(年龄 >= 60岁)比非老年人优先看病。

2.老年人按年龄从大到小的顺序看病,年龄相同的按登记的先后顺序排序。 

3.非老年人按登记的先后顺序看病。

输入

第1行,输入一个小于100的正整数,表示病人的个数;

后面按照病人登记的先后顺序,每行输入一个病人的信息,包括:一个长度小于10的字符串表示病人的ID(每个病人的ID各不相同且只含数字和字母),一个整数表示病人的年龄,中间用单个空格隔开。

输出

按排好的看病顺序输出病人的ID,每行一个。

样例输入

5
021075 40
004003 15
010158 67
021033 75
102012 30

样例输出 

021033
010158
021075
004003
102012

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
struct node {
    int is, age, bi;
    string id;
    friend bool operator<(node a, node b) {
        if (a.is && !b.is)return 1;//老年人>非老年人 
        if (b.is && !a.is)return 0;//非老年人>老年人 
        if (a.is == b.is && a.is)return a.age > b.age;//同为老年人 
        else return a.bi < b.bi;
    }
}e[101];
int main() {
    int n; cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> e[i].id >> e[i].age;
        e[i].bi = i, e[i].is = (e[i].age >= 60 ? 1 : 0);
    }
    sort(e + 1, e + n + 1);
    for (int i = 1; i <= n; i++)
        cout << e[i].id << endl;
    return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值