实验(十七)冒泡排序
知识点复查
实验内容
实验代码实现
#include<stdio.h>
void bubble(int m[],int size) {
for (int i = 0;i < size-1;i++) {//这一步的思路是每次都将最大的数放到最后面
for (int j = 0;j < size - i - 1;j++) {//每次都将最大的数放到最后面,所以每次比较的范围都要减小
//为什么用嵌套循环
if (m[j] > m[j + 1]) {
int temp = m[j];
m[j] = m[j + 1];
m[j + 1] = temp;
}
}
}
}
int main() {
int n=0;
scanf("%d", &n);
int m[11];
if (n <= 0 || n >= 10) {
printf("ERROR");
}
else {
for (int i = 0; i < n; i++) {
scanf("%d", &m[i]);
}
}
bubble(m,n);
for (int i = 0; i < n; i++) {
printf("\t%d", m[i]);
}
return 0;
}
编写总结
首先不管这个代码怎么运行,需要搞清楚输入和输出,输入n作为参与排序的数字个数,然后依次输入n个数字填入一个数组中(这个过程也即对数组初始化),然后用某个函数对数组进行(从小到大)排序得到排序后的数组,然后通过循环遍历数组作为输出。
那么我们就要定义一个函数用于对数组元素进行排序,那么怎么进行排序就是函数最核心的地方。
冒泡排序的逻辑:相邻元素作比较(如果大家看我的解释看不懂的话,就搜一下冒泡排序的动画演示)。
我想重点讲一下为什么要嵌套循环,内部循环执行是为了对相邻元素比较并移位,每次都会执行m[0]与m[1]的比较,m[1]与m[2]的比较,m[2]与m[3]的比较,,,那就有个问题,这些步骤肯定能保证最大的元素来到了数组末尾,那其他元素呢,假设数组为【5,7,4,3,2】那么执行一次,会变成【5,4,3,2,7】,因此我们还需要多次(至少要执行4次,因为有5个元素)这样的循环比较,我们下次需执行m[0]与m[1]的比较,m[1]与m[2]的比较,m[2]与m[3]的比较,我们不需要再考虑m[3]与m[4]的比较,因为上次循环比较,我们已经确保了倒数第一是最大数,所以每执行一次循环比较,下次循环就少一次比较,执行一次少一次比较。回看实验代码,对照着理解即可。
1. 算法原理
-
基本思想:通过对待排序序列从前向后(从下表较小的元素开始),依次比较相邻元素的排序码,若发现逆序则交换,使排序码较大的元素逐渐从前部移向后部(像冒泡一样)。因为排序的过程中,各元素不断接近自己的位置,如果一轮比较后没有任何元素交换,则排序完成,否则需要继续进行比较和交换。
-
比较次数:对于长度为 n 的序列,第一轮比较需要比较 n−1 次,第二轮比较需要比较 n−2 次,以此类推,总共需要比较的次数为 2n(n−1) 次。
2. 算法步骤
-
比较相邻的元素:如果第一个比第二个大(升序排列),就交换它们两个。
-
对每一对相邻元素做同样的工作:从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数。
-
针对所有的元素重复以上的步骤:除了最后一个,因为在每次遍历中,最大的数已经被排到了最后。
-
重复步骤1~3:直到没有任何一对数字需要比较。
实验(十八)报数
知识点复查
实验内容
实验代码实现
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() {
int n, m;
scanf("%d%d", &n, &m);
// 检查输入是否符合要求
if (n <= 0 || n >= 20 || m <= 0 || m >= 20) {
printf("ERROR\n");
return 0;
}
int people[20]; // 假设人数不会超过20
for (int i = 0; i < n; i++) {
people[i] = i + 1; // 初始化编号
}
int index = 0; // 从第一个人开始
int count = 0; // 计数器,用于报数
int total = n; // 总人数
int out_count = 0; // 已出列人数
while (out_count < n) {
if (people[index] != 0) { // 如果这个人还在圈中
count++;
if (count == m) { // 如果报数到m,出列
printf("\t%d", people[index]);
count = 0; // 重置计数器
people[index] = 0; // 标记为已出列
out_count++;
}
}
index = (index + 1) % n; // 移动到下一个人
}
printf("\n"); // 添加换行符
return 0;
}
编写总结
代码编写的难点在于,第一叫到人出列,下一个报的m的人的位置怎么确定。
-
初始化一个数组来表示围成一圈的人,每个人有一个编号。
-
使用一个变量index来表示当前位置,初始值为0。
-
使用一个变量out-
count
来记录已经出列的人数。 -
使用一个循环,直到所有人都出列:
-
计算出列位置:
index = (index + m - 1) % total;
-
输出出列人的编号。
-
将出列的人从数组中移除,并更新
index(从下一个人开始报数)
和total
。
-
-
如果输入不符合要求,输出“ERROR”。