选择排序
令 从 到 枚举,进行 趟操作,每趟从待排序部分 中选择最小的元素,令其与待排序部分的第一个元素 进行交换,这样 就会与当前有序区间 形成新的有序区间
一共
趟操作,总复杂度为
void selectSort() {
for(int i = 1; i <=n; i++) { //n趟操作
int k = i;
for(int j = i; j <= n; j++) { //选出[i,n]中最小的元素,下标为k
if(A[j] < A[k]) {
k = j;
}
}
int temp = A[i]; //交换A[k]与A[i]
A[i] = A[k];
A[k] = temp;
}
}
插入排序
后面的元素不断有序地插入前面排好的元素(从后往前枚举已有序部分来确定插入位置)
int A[maxn], n; //n为元素个数,数组下标为1~n
void insertSort() {
for(int i = 2; i <= n; i++) { //一共排了n-1次
int temp =A[i], j = i; //temp临时存放,j从i开始往前枚举
while(j > 1 && temp < A[j - 1]) {//只要temp小于前一个元素
A[j] = A[j - 1];//把A[j-1]往后移(空出位置)
j--;
}
A[j] = temp;//插入位置为j
}
}
sort函数(第六章)
(1)如何使用sort
必须加上头文件“#include <algorithm>”和“using namespace std;”
使用方法:
sort(首元素地址(必填),尾元素地址的下一个地址(必填),比较函数(非必填));
不写比较函数,则默认对前面给出的区间进行递增排序
#include <stdio.h>
#include <algorithm>
using namespace std;
int main(){
int a[6] = {9, 4, 2, 5, 6, -1};
//将a[0]~a[3]从小到大排序
sort(a, a + 4);
for(int i = 0; i < 6; i++) {
printf("%d ", a[i]);
}
//将a[0]~a[5]从小到大排序
sort(a, a + 6);
for(int i = 0; i < 6; i++) {
printf("%d ", a[i]);
}
return 0;
}
也可以对double,char型数组排序(字典序)
如果想从大到小:
bool cmp(int a, int b){
return a > b; //可以理解为当a > b时把a放在b前面
}
int main() {
int a[] = {3, 1, 4, 2};
sort(a, a + 4, cmp);
for(int i = 0; i < 4; i++) {
printf("%d ", a[i]); //输出 4 3 2 1
}
return 0;
}
也可以对double,char型这样操作
记住:cmp里从小到大用“<”,因为a<b就是左小右大,反之。
(2)结构体数组的排序
定义了如下结构体
struct node{
int x, y;
}ssd[10];
如果想对ssd数组从大到小排
bool cmp(node a, node b) {
return a.x>b.x;
例子
#include <stdio.h>
#include <algorithm>
using namespace std;
struct node{
int x, y;
}ssd[10];
bool cmp(node a, node b) {
return a.x > b.x; //按x值从大到小对结构体数组排序
}
int main() {
ssd[0].x = 2; //{2, 2}
ssd[0].y = 2;
ssd[1].x = 1; //{1, 3}
ssd[1].y = 3;
sort(ssd,ssd + 2, cmp); //排序
for(int i = 0; i < 3; i++){
printf("%d %d\n", ssd[i].x, ssd[i].y);
}
return 0;
}
如果先按x从大到小排序,但当x相等的情况下,按照y的大小从小到大排序(二级排序),cmp的写法是:
bool cmp(node a, node b) {
if(a.x != b.x) return a.x > b.x;
else return a.y < b.y;
}
(3)容器的排序(跳过)
回本章(1)相关结构体的定义
struct Student {
//姓名,准考证号,分数,排名
char name[10];
char id[10];
int score;
int r;
}stu[100010];
(2)cmp函数的编写
要求:按分数高低排,否则按姓名字典排
bool cmp (Student a, Student b) {
if(a.score != b. score) return a.score > b.score;
else return strcmp(a.name, b.name)< 0;
}
(3)排名的实现
分数不同的排名不同,分数相同的排名相同但占用同一个排位。
遍历个体,如果每个个体分数等于上一个个体,则当前个体排名等于上一个个体排名,否则当前个体排名等于数组下标加一。
stu[0].r = 1;
for(int i = 1; i < n; i++) {
if(stu[i].score == stu[i - 1].score) {
stu[i].r = stu[i - 1].r;
} else {
stu[i].r = i + 1;
}
}
有时不一定要把排名记录下来,直接输出即可,避免代码冗长
int r = 1;
for(int i = 0; i < n; i++) {
if(i > 0 && stu[i].score != stu[i - 1].score) {
r = i + 1;
}
例题
n个考场,现在给出各个考场中考生准考证号与分数,要求将所有考生按分数从高到低排序,并按顺序输出所有考生的准考证号、排名、考场号以及考场内排名。
思路
在结构体类型student中存放准考证号、分数、考场号以及考场内排名。写一个排序函数cmp,规则为:
1 当分数不同时,按分数从大到小排
2 否则按准考证号从小到大排
bool cmp(Student a, Student b) {
if(a.score != b.score) return a.score > b.score;
else return strcmp(a.id, b.id) < 0;
}
算法本体分为
1 读入考生信息,并进行排序,写入结构体
2 对考生进行排序
3 按排序一边计算总排名,一边输出考生信息
注意同一考场考生单独排序方法:定义int型变量num,用来存放当前获取到的考生人数。每读入一个考生信息,就让num自增。读取完后考生对应的数组下标为[num-k,num)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct Student {
// 准考证号,分数,考场号,考场内排名
char id[15];
int score;
int location_number;
int local_rank;
}stu[30010];
bool cmp(Student a, Student b) {
//先按分数从高到低,否则按1准考证大小
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; // num为总考生数
scanf("%d", &n); // n为考场数
for(int i = 1; i <= n; i++) {
scanf("%d", &k); //该考场人数
for(int j = 0; j < k; j++) {
scanf("%s %d", stu[num].id, &stu[num].score);
stu[num].location_number = i; // 该考生的考场号为i
num++; // 总考生数加1
}
sort(stu + num - k, stu + num, cmp); // 将该考场的考生排序
stu[num - k].local_rank = 1; // 该考场第一名的locan_rank记为1
for(int j = num - k + 1; j < num; j++) //对该考场剩余的考生
if(stu[j].score == stu[j - 1].score) { //如果与前一位考生同分
//local_rank也相同
stu[j].local_rank = stu[j - 1].local_rank;
} else {
// local_rank 为该考生前的人数
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; //当前考生与上一个考生分数不同时,让r更新为人数+1
}
printf("%s ",stu[i].id);
printf("%d %d %d\n", r, stu[i].location_number, stu[i].local_rank);
}
return 0;
}