☘前言☘
请添加图片描述
咕咕咕、鸽子精又回来了。😶🌫️ 没办法,之前想好好学学嵌入式,可以看到我更新了好多,结果开发板太贵了,哭晕在厕所。算了,等到回所里跟导师哭去啦。 |
今天继续更新,今天算是正式进入算法的入门了,上一章的其实就是简单的模拟,所以并不算入门,只是写了写算法罢了,之前一篇文章内容太多,导致把自己卷没了,这次一篇就一个知识点,分多个文章来
🧑🏻作者简介:一个从工业设计改行学嵌入式的年轻人
✨联系方式:2201891280(QQ)
📔源码地址:https://gitee.com/xingleigao/algorithm-notes
⏳全文大约阅读时间: 120min(有点长,大家忍一下 ,一定会有蜕变的)
🍭1.基础知识点
排序是最简单的算法,其实在之前的学习我们已经接触了冒泡排序,如果没有印象的话可以看看往期文章哈《算法笔记知识点记录》第二章——快速入门2[选择结构、循环结构和数组]
这次我们再提这个算法呢,会给大家再讲一讲选择排序和插入排序,然后就是解题常用的一种方式就是库函数0.0
👻1.1选择排序
选择排序就是,每次从后面的无序序列
选择一个最小的元素加入到有序序列的最后一个位置上
,一直重复就可以得到最终的有序序列。可以看到得到最终的结果需要n
趟选择。
于是对应的代码就很好写啦,就是n躺操作,每趟操作选出待排序部分[i,n]
中的最小的元素,与a[i]
交换。对应代码:void SelectSort(){ for(int i = 1;i <= n; ++i){ //共需要n躺过程 int k = i; for(int j = 1; j <= n;++j) //获取最小的元素 if(a[j] < a[k] k = j; swap(a[i],a[k]); //交换元素 } }
需要的注意的点有几个:
当i和k交换的时候如果一样的话可以不交换,但是这点复杂度时间影响不大
冒泡排序的最好时间复杂度是O(n),但是选择排序复杂度都是O(n^2),因为冒泡排序中间判断了是否已经有序了
示例代码给的数组起始时1终点时n
,自己写的时候要灵活改动。
🕷️1.2插入排序
简单插入排序是每次将一个元素插入到前面的已经有序的序列中,显然如果只有一个元素的话肯定有序,所以是从第二个元素插入,一共需要
n-1
趟操作。
图片还是比较清晰的表达了这个过程,但是插入的时候我们注意到需要移动元素,我们可以将查找位置和移动位置两个过程结合起来
。代码如下:void InsertSort(){ for(int i = 2;i <= n; ++i){ int tmp = a[i],j = i; while(j > 1&& tmp < a[j-1]){ a[j] = a[j-1];//后移一个 j--; } a[j] = temp;//插入完成 } }
💐1.3库函数的使用
在C++中有一个非常实用的库函数就是
sort
,我们考试也只是考虑实现,所以我们建议直接使用库函数。而且sort
规避了快排算法极端情况复杂度退化到O(n2)的情况,有兴趣的同学可以看看stl源码。
如何使用
#include <algorithm> using namespace std; sort(首元素地址(必须),尾元素地址的下一个地址(必须),比较函数(可省略));
其中前两行是规定动作,大家使用cpp进行编程的时候建议都加上
using namespace std;
防止出错。
然后前两个参数必须的,第三个可省略,默认的比较函数是从大到小进行排列。例如int main(){ int a[5] = {1,3,5,-1,2}; sort(a, a + 5); for(int i = 0;i < 5;++i) printf("%d ",a[i]); }
得到的结果就是
-1 1 2 3 5
,需要注意的是这个结果可以对double浮点数也可以生效,这个牵扯到stl的知识,大家知道可以用就完事了。
cmp函数
默认的sort函数只能完成从小到大的结果,为了实现自定义的排序方式,我们就需要cmp函数来实现自定义功能,其实从名字上也能看出来就是用来比较的函数。bool cmp(int a, intb){return a > b;}//前面大于后面就是从大到小 sort(a, a + 5, cmp);
这样就可以得到结果啦。
当然也可以写结构体作比较就可以实现很多复杂的排序啦。
✨例题
🍕题目描述
全英文。。。就问你慌不慌,2333。其实挺好懂的啦,多看看就不慌了。题目大意:一共有n个考场,每个考场都有一些学生,输入是考生的准考证号和分数,需要按分数从大到小的顺序返回所有考生的准考证号,排名、考场号和考场内排名。其中如果分数相同的话就按id的顺序进行排序。
🎶解题思路
肯定要建立结构体的,然后读入一个考场的所有数据后就可以对考场中所有人进行排序,并将对应的排名信息写入结构体,最后对所有数据进行排名,并输出对应的排名信息。
🎐小技巧
进行排名计算的时候,肯定会有并列的情况,判断方式其实就是如果当前的分数和上一个的分数一样,那么就将对应的名次信息和上一个的名次写的一样,否则就等于统计变量的值。其中将第一名赋为1。
🍘代码
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct student{
char id[17];//id号
int score; //分数
int local; //考场号
int local_rank; //考场排名
}stu[30001];
bool cmp(student a, student b){ //比较函数
if(a.score != b.score) return a.score > b.score;
else return strcmp(a.id, b.id) < 0;
}
int main(){
int N, K, num = 0;
//数据接收 并对考场内用户进行排名
scanf("%d",&N);
for(int i = 0; i < N; ++i){
//获取考场内考生数据
scanf("%d",&K);
for( int j = 0; j < K; ++j){
scanf("%s %d",stu[num].id,&stu[num].score);
stu[num].local = i + 1;
num++;
}
//对考场内考生进行排名
sort(stu + num - K,stu + num, cmp);
stu[num - K].local_rank = 1;
for(int j = num - K + 1; j < num; ++j)
if(stu[j].score == stu[j - 1].score)
stu[j].local_rank = stu[j - 1].local_rank;
else
stu[j].local_rank = j + 1 - num +K;
}
printf("%d\n",num);
sort(stu,stu + num, cmp);
int r = 1;
for(int i = 0; i < num; ++i){
if(i > 0 && stu[i].score != stu[i-1].score)
r = i + 1;
printf("%s ",stu[i].id);
printf("%d %d %d\n", r, stu[i].local, stu[i].local_rank);
}
return 0;
}
🐳课后习题
我写完会放题解,大家写完了可以在评论区打卡哟!题解我放评论区吧,这样不用修改文章。
题解:评论区见,置顶没有就是我没写完0.0,大佬们刷完打个卡
大家加油冲!!!!