1. 1
【问题描述】计算机类2202班同学举行黄河大合唱比赛,领唱同学被指挥老师安排进了队伍中(链式排列),现在请你帮老师将领唱的那位同学找出来,排到队伍的第一个吧。
【输入形式】第一行是参加合唱比赛的总人数n,第二行是这n个同学的姓名,第三行是领唱同学的姓名name
【输出形式】按指挥老师要求重新排列后的所有同学姓名。若找不到姓名为name的同学,则输出None。
【样例输入】
10
Zhang Wang Deng Li Liu Wu Zhai Xiao Chen Xu
Wu
【样例输出】
Wu Zhang Wang Deng Li Liu Zhai Xiao Chen Xu
【提示】
1、请注意,务必采用单链表完成该操作哦,如果采用数组存储则不给分的啦!
2、推荐采用带头结点的单链表,对特殊数据的操作将非常方便。
注意点:前驱指针必须设置为head,否则会导致报错
#include <iostream>
#include <vector>
using namespace std;
typedef struct biao
{
string data;
biao* next;
}biao;
void creat(biao* head, string s)
{
biao* point = new biao;
point->data = s;
point->next = nullptr;
if (head->next == nullptr)
{
head->next = point;
}
else
{
biao* point1 = head->next;
while (point1->next)
{
point1 = point1->next;
}
point1->next = point;
}
}
int main()
{
long n;
cin >> n;
biao* head = new biao;
head->next = nullptr;
if (n != 0)
{
for (int i = 0; i < n; i++)
{
string s;
cin >> s;
creat(head, s);
}
string s1;
cin >> s1;
if (s1.size() > 0)
{
biao* point = head->next;
biao* pre = head;
int i = 0;
while (point)
{
if (point->data == s1)
{
i = 1;
break;
}
pre = point;
point = point->next;
}
if (i == 0)
{
printf("None");
}
else
{
pre->next = point->next;
point->next = head->next;
head->next = point;
biao* point2 = head->next;
while (point2)
{
cout << point2->data << ' ';
point2 = point2->next;
}
}
}
if (s1.size() == 0)
{
biao* point2 = head->next;
while (point2)
{
cout << point2->data << ' ';
point2 = point2->next;
}
}
}
return 0;
}
2. 2
【问题描述】 托蒂同学最近热爱一种猜数字游戏,该游戏的规则是根据一棵二叉排序树的前序遍历序列,猜出这棵树的后序遍历序列的第n个数字的值。请你写一个程序帮助托蒂同学大杀四方。
【输入形式】 输入为两行:第一行为一个二叉排序树的前序遍历序列,序列为整型,且不包含重复数字,以数字0作为输入结束符;第二行为一个整型变量n (n<=树的节点数)。
【输出形式】 该树的后序遍历序列中的第n个数字的值。
【样例输入】
4 2 1 3 5 7 6 0
2
【样例输出】
3
【提示】请注意二叉排序树遍历的特点。
注意点:二叉搜索树的创建格式,注意指针的初始化,其次注意引用的使用
#include <iostream>
#include <vector>
using namespace std;
typedef struct tree
{
int data;
tree* left;
tree* right;
}tree;
void creat(tree*&root,int a)
{
if (root == nullptr)
{
root = new tree;
root->data = a;
root->left = root->right = nullptr;
}
else
{
if (root->data < a)
{
creat(root->right, a);
}
else
{
creat(root->left, a);
}
}
}
vector<int>ret;
void bi(tree* root)
{
if (root == nullptr)
{
return;
}
bi(root->left);
bi(root->right);
ret.push_back(root->data);
}
int main()
{
vector<int>s;
int l = 0;
while (1)
{
int x;
cin >> x;
if (x == 0)
{
break;
}
s.push_back(x);
l++;
}
int i = 0;
tree*root = nullptr;
for (int j = 0; j < l; j++)
{
creat(root, s[j]);
}
int t;
cin >> t;
bi(root);
printf("%d", ret[t-1]);
return 0;
}
3. 3
【问题描述】假设需要在n个城市之间建立通信联络网,现要求在最节省经费的前提下建立这个通信网。可以用连通网来表示n个城市以及n个城市之间可能设置的通信线路,其中网的顶点表示城市,边表示两个城市之间的线路,赋于边的权值表示相应的代价。对于n个顶点的连通网可以建立许多不同的生成树,每一棵生成树都可以是一个通信网。现在,需要选择一棵生成树,使总的耗费最小。
【输入形式】输入第一行数据包括城市数目的正整数n(<=50)和候选网络线路数目m。随后m行对应m条通信线路,每行给出3个正整数,分别是该条通信线路直接连通的两个城市的编号以及该通信线路的预算成本。为简单起见,城市从1~n编号。
【输出形式】输出从1号城市开始,逐步建立整个通信网络的城市编号,同时输出最低成本。
【样例输入】
6 10
1 2 6
1 3 1
1 4 5
2 3 5
2 5 3
3 4 5
3 6 4
3 5 6
4 6 2
5 6 6
【样例输出】
1 3 6 4 2 5
15
【提示】输入的通信线路是双向可达的。
注意点:直接背吧,无所谓什么理解不理解的,如果有更复杂的操作不写也罢,这个模板写下来即使用例一个没过也能拿一半分
#include<iostream>
#include<vector>
using namespace std;
int grap[50][50];
typedef struct tree
{
int weight;
int parent;
int flag;
}tree;
int getmin(tree* arr, int limit)
{
int minweight = 9999;
int ret = 0;
for (int i = 1; i <= limit; i++)
{
if (arr[i].weight < minweight && arr[i].flag == 0)
{
minweight = arr[i].weight;
ret = i;
}
}
return ret;
}
void plm(int limit)
{
int sum = 0;
tree arr[100];
vector<int>tree;
tree.push_back(1);
for (int i = 1; i <= limit; i++)
{
arr[i].parent = 1;
arr[i].weight = grap[1][i];
arr[i].flag = 0;
}
arr[1].parent=-999;
for (int i = 2; i <= limit; i++)
{
int min = getmin(arr, limit);
sum += arr[min].weight;
arr[min].flag = 1;
tree.push_back(min);
for (int i = 2; i <= limit; i++)
{
if (grap[min][i] < arr[i].weight)
{
arr[i].weight = grap[min][i];
arr[i].parent = min;
}
}
}
for (int i = 0; i < tree.size(); i++)
{
cout << tree[i] << ' ';
}
cout << endl << sum;
}
int main()
{
int num;
int edge;
cin >> num >> edge;
for (int i = 1; i <= num; i++)
{
for (int j = 1; j <= num; j++)
{
grap[i][j] = 9999;
}
}
for (int i = 0; i < edge; i++)
{
int begin;
int end;
int weight;
cin >> begin >> end >> weight;
grap[begin][end] = grap[end][begin] = weight;
}
plm(num);
return 0;
}
4. 4
【问题描述】如果一个排序算法能够保留数组中重复元素的相对位置则可以被称为是稳定的。这个性质在许多情况下很重要。例如:在考虑一个需要处理大量含有地理位置和时间戳的事件互联网商业应用程序中,我们在时间发生时将它们挨个存储在一个数组中,这样在数组中它们已经是按照时间顺序排序好了的。现在假设在进一步处理前将按照地理位置划分。一种简单的方法是将数组按照位置排序。如果排序算法不是稳定的,排序后的每个城市的交易可能不会再是按照时间顺序排序的了。很多情况下,不熟悉排序稳定性的程序员在第一次遇到这种情形的时候会在使用不稳定排序算法后把数组弄的一团糟而一脸懵。现输入一组数据,以0作为输入的结束,从插入排序、希尔排序、快速排序、堆排序四种排序方法中挑选一种稳定的排序算法,对输入的数据进行从大到小的排序,给出排序后的结果。
【输入形式】一组数据,以0作为输入的结束
【输出形式】排序后的结果
【样例输入】
9 8 7 3 1 9 0
【样例输出】
9 9 8 7 3 1
【提示】选择不稳定的排序算法不得分。
注意点:稳定的算法:冒泡,插入,归并,不稳定:快排,希尔,堆,时间复杂度为nlongn的为堆,归并,快排,除了希尔剩余为n方,且希尔介于二者之间,而赶时间选快排,省空间选堆排,稳定性归排,
#include <iostream>
#include <vector>
using namespace std;
void sort(vector<int>&s, int n)
{
for (int i = 0; i < n; i++)
{
int end = i - 1;
int tmp = s[i];
while (end >= 0)
{
if (s[end] < tmp)
{
s[end + 1] = s[end];
end--;
}
else
{
break;
}
}
s[end + 1] = tmp;
}
}
int main()
{
vector<int>s;
int count = 0;
while (1)
{
int t;
cin >> t;
if (t == 0)
{
break;
}
count++;
s.push_back(t);
}
sort(s, count);
for (int t = 0; t < count; t++)
{
cout << s[t]<<' ';
}
return 0;
}