7-1 统计工龄

代码 :

#include <bits/stdc++.h>
using namespace std; const int N = 1e5 + 10;
int a[N], d[110]; int main() {
int n;
cin >> n; for (int i = 0; i < n; i++) scanf("%d", &a[i]); for (int i = 0; i < n; i++) d[a[i]] ++; for (int i = 0; i <= 50; i++) {
if (d[i]) printf("%d:%d\n", i, d[i]);
} return 0;
}

7-2 寻找大富翁

代码 :

#include <bits/stdc++.h>
using namespace std; const int N = 1e6 + 10;
int a[N]; // 快排
void qsort(int l, int r){
if (l >= r) return; int i = l - 1, j = r + 1;
int x = a[l + r >> 1];
while (i < j){
do i++; while (a[i] > x);
do j--; while (a[j] < x);
if (i < j) swap(a[i], a[j]);
} qsort(l, j);
qsort(j + 1, r);
} int main() {
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++) scanf("%d", &a[i]); qsort(1, n); // m 有可能小于 n, 取个最小值
for (int i = 1; i <= min(m, n); i++) {
if (i == 1) printf("%d", a[i]);
else printf(" %d", a[i]);
}
return 0;
}

7-3 点赞狂魔

题意 :

​ 给 N 个用户, 每个用户有个 NameK 个特性编号 Fi ; 找出每个人点赞不同编号的数量, 并输出数量最大的前三名; 如果有并列, 就输出标签出现次数平均值最小的那个, 若不足3人,则用-补齐缺失

代码:

#include <bits/stdc++.h>
using namespace std; struct Node {
char name[10];
int cnt, k; // cnt 存不同标签数量, k 存所有标签数量
} p[110]; set<int> s; // set 去重 // 排序规则
bool cmp(Node a, Node b) {
if (a.cnt != b.cnt) return a.cnt > b.cnt;
return a.k < b.k;
} int main() {
int n;
cin >> n; for (int i = 1; i <= n; i++) {
cin >> p[i].name >> p[i].k;
s.clear();
int x;
for (int j = 0; j < p[i].k; j++) {
scanf("%d", &x);
s.insert(x);
}
p[i].cnt = s.size();
} // 根据题目规则排序
sort(p + 1, p + n + 1, cmp); if (n == 0) printf("- - -\n");
else if (n == 1) printf("%s - -\n", p[1].name);
else if (n == 2) printf("%s %s -\n", p[1].name, p[2].name);
else printf("%s %s %s\n", p[1].name, p[2].name, p[3].name); return 0;
}

7-4 插入排序还是归并排序

题意:

​ 给出两个长度为 N 的序列, 第一行代表初始状态, 第二行代表插入排序 (归并排序) 的中间序列; 判断是用的插入排序还是归并排序, 并输出用该排序算法再迭代一轮的结果序列

思路 :

​ 对于插入排序, 因为每次都是从序列头中拿出一个, 插入到排好的序列中, 所以对于一个长度为 n 的序列, 如果是插入排序, 前 k 个数应该是排好序的, 而后 n - k 个数中 a[i] == b[i], 这样就能找到 k, 并排序前 k + 1 的长度

​ 对于归并排序, 因为它每次都是取半递归排序, 所以要找到最小的已经排好序的子段长度 len, 然后再按照 2 * len 的子段长度归并排序

代码参考博客地址: 博客园 kingwzun

代码 :

#include <bits/stdc++.h>
using namespace std; const int N = 110; int a[N], b[N]; int main() {
int n;
cin >> n; for (int i = 0; i < n; i++) cin >> a[i];
for (int i = 0; i < n; i++) cin >> b[i]; // 先判断是不是插入排序
int flag = 0;
int k = 0;
for (int i = 1; i < n; i++) {
if (flag == 0 && b[i] < b[i - 1]) k = i, flag = 1; // 看前面排好序的递增序列
// 如果 k 到 n 间 a[i], b[i] 不全相等, 说明不是插入排序
if (flag == 1 && b[i] != a[i]) {
flag = 2;
break;
}
} if (flag == 1) {
cout << "Insertion Sort" << endl; sort(a, a + k + 1); for (int i = 0; i < n; i++) {
if (i) cout << " " << a[i];
else cout << a[i];
}
} else {
cout << "Merge Sort" << endl; // 找到最小的排好序的子段
int len = 0x3f3f3f3f;
int cnt = 1;
for (int i = 0; i < n - 1; i ++) {
if (b[i] < b[i + 1]) cnt++;
else len = min(len, cnt), cnt = 1;
} len *= 2;
for (int i = 0; i < n; i += len)
sort(a + i, a + min(i + len, n)); // 这里和 n 取min值, 防止越界 for (int i = 0; i < n; i++) {
if (i) cout << " " << a[i];
else cout << a[i];
}
} return 0;
}

7-5 插入排序还是堆排序

题意:

​ 同 7-4, 判断是插入排序还是堆排序, 并输出用该排序算法再迭代一轮的结果序列

思路

插入排序7-4, 或者因为数据很小, 可以每次都排序判断

​ 对于堆排序, 题目是从长度为 n 开始, 每次对前 k 个序列取大根堆, 并将长度为 k 的序列里的第一个和最后一个交换, 直到 k == 0; 完整的一步迭代是 : 形成前 k 个数的大根堆, 并 swap(a[1], a[k]), 并且形成前 k - 1 个数的大根堆

代码参考博客地址 : CSDN 摺耳喵

代码 1 :

#include <bits/stdc++.h>
using namespace std; const int N = 110; int a[N], b[N], tmp[N]; int main() {
int n;
cin >> n; for (int i = 0; i < n; i++) cin >> a[i];
for (int i = 0; i < n; i++) cin >> b[i];
memcpy(tmp, a, sizeof (tmp)); bool flag = 0;
// 这里 i 一定要从 2 开始, 不然会被卡
for (int i = 2; i <= n; i++) {
sort(a, a + i);
if (flag) {
cout << "Insertion Sort" << endl;
for (int j = 0; j < n; j++) {
if (j) cout << " " << a[j];
else cout << a[j];
}
break;
}
if (equal(a, a + n, b)) flag = 1;
} if (!flag) {
memcpy(a, tmp, sizeof (a)); for (int i = n; i >= 1; i--) {
make_heap(a, a + i);
if (flag) {
cout << "Heap Sort" << endl;
for (int j = 0; j < n; j++) {
if (j) cout << " " << a[j];
else cout << a[j];
}
break;
}
if (equal(a, a + n, b)) flag = 1;
swap(a[0], a[i - 1]);
}
}
return 0;
}

代码 2 : 手写堆排序实现

// 注意 : 这里数组的下标是从 1 开始的

#include <bits/stdc++.h>
using namespace std; const int N = 110; int a[N], b[N], tmp[N];
int len; // 大根堆
void down(int u) {
int t = u;
if (u * 2 <= len && a[t] < a[u * 2]) t = u * 2;
if (u * 2 + 1 <= len && a[t] < a[u * 2 + 1]) t = u * 2 + 1; if (u != t) {
swap(a[t], a[u]);
down(t);
}
} void init() {
for (int i = len / 2; i; i--) down(i);
} int main() {
int n;
cin >> n; for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= n; i++) cin >> b[i]; memcpy(tmp, a, sizeof (a)); bool flag = 0;
for (int i = 2; i <= n; i++) {
sort(a + 1, a + i + 1);
if (flag) {
cout << "Insertion Sort" << endl;
for (int j = 1; j <= n; j++) {
if (j != 1) cout << " " << a[j];
else cout << a[j];
}
break;
}
if (equal(a, a + n, b)) flag = 1;
} if (!flag) {
memcpy(a, tmp, sizeof (a)); flag = 0;
for (int i = n; i >= 1; i--) {
len = i;
init();
if (flag) {
cout << "Heap Sort" << endl;
for (int j = 1; j <= n; j++) {
if (j != 1) cout << " " << a[j];
else cout << a[j];
}
break;
}
if (equal(a, a + n, b)) flag = 1;
swap(a[1], a[i]);
}
}
return 0;
}

7-6 逆序对

思路 : 归并排序逆序对

代码 :

#include <bits/stdc++.h>
using namespace std; const int N = 1e6 + 10; int a[N], tmp[N];
long long int sum = 0; // 归并排序
void merge_sort(int l, int r) {
if (l >= r) return; int mid = l + r >> 1;
merge_sort(l, mid), merge_sort(mid + 1, r); int k = 0, i = l, j = mid + 1;
while (i <= mid && j <= r) {
if (a[i] <= a[j]) tmp[k++] = a[i++];
else // 这里 a[i] > a[j] 就说明 a[i] 到 a[mid] 间的数都大于 a[j] 并形成逆序对
tmp[k++] = a[j++], sum += mid - i + 1;
}
while (i <= mid) tmp[k++] = a[i++];
while (j <= r) tmp[k++] = a[j++]; for (int i = l, j = 0; i <= r; i++, j++) a[i] = tmp[j];
} int main() {
int n;
cin >> n; for (int i = 1; i <= n; i++) scanf("%d", &a[i]); merge_sort(1, n); cout << sum << endl;
return 0;
}

7-7 堆排序

代码 :

#include <bits/stdc++.h>
using namespace std; const int N = 110;
int h[N], len; // 这里是大根堆
void down(int u) {
int t = u;
if (u * 2 <= len && h[t] < h[u * 2]) t = u * 2;
if (u * 2 + 1 <= len && h[t] < h[u * 2 + 1]) t = u * 2 + 1; if (t != u) {
swap(h[t], h[u]);
down(t);
}
} void init() {
for (int i = len / 2; i; i--) down(i);
} int main() {
int n;
while (cin >> n) { for (int i = 1; i <= n; i++) cin >> h[i];
len = n;
init(); for (int i = n; i > 1; i--) {
swap(h[1], h[i]);
len = i - 1;
down(1);
for (int j = 1; j <= n; j++) {
if (j == 1)
printf("%d", h[j]);
else
printf(" %d", h[j]);
}
printf("\n");
}
}
return 0;
}

7-8 石子合并

代码参考博客地址 :

CSDN ACdreamers

星辰阁

代码 :

#include <bits/stdc++.h>
using namespace std; const int N = 110; int a[N], d[N];
int dp[N][N]; int main() {
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
d[i] = d[i - 1] + a[i];
} for (int h = 1; h <= n; h++) {
for (int i = 1; i <= n; i++) {
int j = i + h;
if (j > n) continue;
dp[i][j] = 0x3f3f3f3f;
for (int k = i; k <= j; k++) {
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j]);
}
dp[i][j] += d[j] - d[i - 1];
}
} cout << dp[1][n] << endl;
return 0;
}

7-9 第k小

代码参考地址 : acwing

代码1 : 快排实现

#include<bits/stdc++.h>
using namespace std; const int N = 1e6 + 10;
int a[N]; int quick_sort(int l, int r, int k) {
if (l >= r) return a[k]; int x = a[(l + r) >> 1], i = l - 1, j = r + 1; while (i < j) {
do i++; while (a[i] < x);
do j--; while (a[j] > x);
if (i < j) swap(a[i], a[j]);
}
if (k <= j) quick_sort(l, j, k);
else quick_sort(j + 1, r, k);
} int main() {
int n, k;
scanf("%d %d", &n, &k);
for (int i = 0; i < n; i++) scanf("%d", &a[i]);
cout << quick_sort(0, n - 1, k - 1) << endl; return 0;
}

代码2 : 堆排序实现

#include <bits/stdc++.h>
using namespace std; const int N = 1e6 + 10; int h[N], len; // 小根堆
void down(int u) {
int t = u;
if (u * 2 <= len && h[t] > h[u * 2]) t = u * 2;
if (u * 2 + 1 <= len && h[t] > h[u * 2 + 1]) t = u * 2 + 1; if (u != t) {
swap(h[u], h[t]);
down(t);
}
} void init() {
for (int i = len / 2; i; i--) down(i);
} int main() {
int n, k;
cin >> n >> k; for (int i = 1; i <= n; i++) scanf("%d", &h[i]); len = n;
init();
for (int i = 1; i < k; i++) {
swap(h[1], h[len]);
len--;
down(1);
} cout << h[1] << endl; return 0;
}

7-10 快速排序的过程

代码 : 快速排序的模板很多, 但是这道题好像只能用这个模板 ( 不是很确定 )

#include <bits/stdc++.h>
using namespace std; const int N = 1e3 + 10; int a[N];
int n; void quick_sort(int l, int r) {
if (l > r) return;
int x = a[l], i = l, j = r; while (i < j) {
while (i < j && a[j] >= x) j--;
while (i < j && a[i] <= x) i++;
if (i < j) swap(a[i], a[j]);
}
swap(a[l], a[j]); for (int k = 1; k <= n; k++) {
cout << a[k] << " ";
}
cout << endl;
quick_sort(l, j - 1);
quick_sort(j + 1, r);
} int main() {
cin >> n; for (int i = 1; i <= n; i++) cin >> a[i];
quick_sort(1, n); return 0;
}

PTA 21级数据结构与算法实验8—排序的更多相关文章

  1. 数据结构与算法实验题 6.1 s_sin’s bonus

    数据结构与算法实验题 6.1 s_sin's bonus ★实验任务 正如你所知道的 s_sin 是一个非常贪玩的人 QAQ(如果你非常讨厌他请直接从第二段开 始看),并且令人感到非常遗憾的是,他是一 ...

  2. 数据结构与算法实验题 9.1 K 歌 DFS+剪枝

    数据结构与算法实验题 K 歌 ★实验任务 3* n 个人(标号1~ 3 * n )分成 n 组 K 歌.有 m 个 3 人组合,每个组合都对应一个分数,你能算出最大能够得到的总分数么? ★数据输入 输 ...

  3. 数据结构与算法实验题 4.2 Who is the strongest

    数据结构与算法实验题 4.2 Who is the strongest ★实验任务 在神奇的魔法世界,召唤师召唤了一群的魁偶.这些魁偶排成一排,每个魁偶都有一个 战斗值.现在该召唤师有一个技能,该技能 ...

  4. HDU 3791 二叉搜索树 (数据结构与算法实验题 10.2 小明) BST

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=3791 中文题不说题意. 建立完二叉搜索树后进行前序遍历或者后序遍历判断是否一样就可以了. 跟这次的作业第 ...

  5. Java数据结构和算法(五)--希尔排序和快速排序

    在前面复习了三个简单排序Java数据结构和算法(三)--三大排序--冒泡.选择.插入排序,属于算法的基础,但是效率是偏低的,所以现在 学习高级排序 插入排序存在的问题: 插入排序在逻辑把数据分为两部分 ...

  6. 数据结构与算法之--高级排序:shell排序和快速排序

    高级排序比简单排序要快的多,简单排序的时间复杂度是O(N^2),希尔(shell)排序大约是O(N*(logN)^2),而快速排序是O(N*logN). 说明:下面以int数组的从小到大排序为例. 希 ...

  7. 数据结构与算法之PHP排序算法(堆排序)

    一.堆的定义 堆通常是一个可以被看做一棵树的数组对象,其任一非叶节点满足以下性质: 1)堆中某个节点的值总是不大于或不小于其父节点的值: 每个节点的值都大于或等于其左右子节点的值,称为大顶堆.即:ar ...

  8. Java数据结构和算法(三)--三大排序--冒泡、选择、插入排序

    三大排序在我们刚开始学习编程的时候就接触过,也是刚开始工作笔试会遇到的,后续也会学习希尔.快速排序,这里顺便复习一下 冒泡排序: 步骤: 1.从首位开始,比较首位和右边的索引 2.如果当前位置比右边的 ...

  9. 数据结构与算法之PHP排序算法(希尔排序)

    一.基本思想 希尔排序算法是希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本. 该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个“增量”的元素组成的)分别进行直接 ...

  10. 数据结构与算法实验题6.1 s_sin’s bonus byFZuer

    玩家从n 个点n-1 条边的图,从节点1 丢下一个小球,小球将由于重力作用向下落,而从小球所在点延伸出的每一条边有一个值pi 为小球通过该条边的概率(注意从同一个节点向下延伸的所有边的pi 的和可以小 ...

随机推荐

  1. Spring源码系列:核心概念解析

    前言 本文旨在为读者解析Spring源码中的关键类,以便读者在深入阅读源码时,能够了解关键类的作用和用途.在阅读Spring源码时,经常会遇到一些不熟悉的概念,了解关键类的作用可以帮助读者更好地理解这 ...

  2. RK3568用户自定义开机画面功能

    RK方案中的开机画面处画逻辑 在RK的方案中,如RK1109,RK1126,RK3568这些嵌入式LINUX方案在开机画面的处理逻辑都是一致的. 用户的uboot,kernel开机画面都是同dts,k ...

  3. 如何将 Spire.Doc for C++ 集成到 C++ 程序中

    Spire.Doc for C++是一个专业的 Word 库,供开发人员在任何类型的 C++ 应用程序中阅读.创建.编辑.比较和转换 Word 文档. 本文演示了如何以两种不同的方式将 Spire.D ...

  4. google + chatgpt

    google注册 网址:https://www.google.com/ 使用右上角登录按钮 点击创建账户然后根据步骤注册 chagpt注册 1.https://chat.openai.com/auth ...

  5. MQTT-保留消息和遗嘱消息

    保留消息 为什么需要保留消息 ​ 如果不考虑持久会话的因素,那么MQTT订阅只有在客户端连接之后才能创建,所以服务端不能提前预知某个主题会被哪些服务端订阅或者某个客户端会订阅哪些主题,所以当消息到达服 ...

  6. HTML中meta标签的那些属性

    <meta> 标签是 HTML 中用于描述网页元信息的元素.它位于 <head> 部分,不会显示在页面内容中,但对于浏览器.搜索引擎等具有重要作用.主要作用有:定义文档的字符编 ...

  7. Keepalived 高可用

    Keepalived 高可用 什么是高可用 一般是指2台机器启动着完全相同的业务系统,当有一台机器down机了,另外一台服务器就能快速的接管,对于访问的用户是无感知的. 高可用通常使用的软件 keep ...

  8. OData WebAPI实践-Non-EDM模式

    前文说到了 EDM 与 OData 之间的关系,具有 EDM 的 OData 提供了强大的查询能力,但是 OData 并不必须要配置 EDM,我们也可以使用 Non-EDM 方案. Non-EDM 所 ...

  9. 前端Vue项目打包性能优化方案

    一.前言 Vue 框架通过数据双向绑定和虚拟 DOM 技术,帮我们处理了前端开发中最脏最累的 DOM 操作部分, 我们不再需要去考虑如何操作 DOM 以及如何最高效地操作 DOM:但 Vue 项目中仍 ...

  10. 2021-06-29:在两个都有序的数组中找整体第K小的数。

    2021-06-29:在两个都有序的数组中找整体第K小的数. 福大大 答案2021-06-29: 1.A和B长度不等的时候,需要把A和B的长度变成相等. A是短数组,B是长数组. 第k小的数,k从1开 ...