机试课
三、排序和查找
排序
机试考点:直接用排序的算法
c语言:qsort
c++:sort(主要)
关键点:compare函数什么时候不发生交换
c++:sort
STL的算法
头文件algorithm算法头文件
#include <algorithm>
sort函数的功能:排序
(1)可以排序的数据结构:静态数组、动态数组vector(map、set意义不大,本身就有序)
(2)sort可以自定义排序规则
升序、降序或自定义规则
1、静态数组
sort函数(数组名,数组名+数组长度)
第一个参数:数组首地址
第二个参数:尾后地址,最后一个地址的后一个地址
范围左闭右开
//静态数组
int arr[6] = {2,4,6,1,3,5};
sort(arr, arr + 6);//第一个参数:数组首地址 第二个参数:尾后地址,最后一个地址的后一个地址
2、动态数组vector
sort函数(数组名.begin(),数组名.end())
这里的参数为迭代器
参数范围相同
//动态数组vector
vector<int> vec= {2,4,6,1,3,5};
sort(vec.begin(), vec.end());//第一个参数:数组首地址 第二个参数:尾后地址,最后一个地址的后一个地址
3、自定义排序规则
sort函数底层:快速排序(小于枢纽放左边,大于枢纽放右边,基于比较)
一定存在:
lhs代表左边指向的内容,rhs代表右边指向的内容
if(lhs 比较 rhs){//默认比较是小于<
不交换
}else{
交换
}
默认比较是小于<(升序)
自定义函数(),两个参数lhs和rhs,返回bool值(true\false)
函数体内是不发生交换的条件
在主函数内调用sort函数,有三个参数,第三个参数是自定义的函数名
bool compare(int lhs,int rhs){//自定义排序——降序 两个参数,返回bool值(true\false)
return lhs >= rhs;//比较左边和右边的大小
}
//自定义排序——降序
sort(vec.begin(), vec.end(), compare);//三个参数,第三个参数是自定义的函数
compare函数设计方案
(1)函数形式与返回值
返回bool值(true\false),两个参数lhs和rhs,参数类型和容器一直(int型写int,char型写char)
bool compare(int lhs,int rhs)
(2)当lhs和rhs不发生交换时,返回true
例题1、整数奇偶排序
思路:判断不交换的情况
(1)左奇 右偶
(2)左奇 右奇 且 左>右
(3)左偶 右偶 且 左<右
代码:
#include <stdio.h>
#include <algorithm>
using namespace std;
bool compare(int lhs, int rhs){
if(lhs % 2 == 1 && rhs % 2 == 0){
return true;
}else if(lhs % 2 == 1 && rhs % 2 == 1 && lhs > rhs){
return true;
}else if(lhs % 2 == 0 && rhs % 2 == 0 && lhs < rhs){
return true;
}else{
return false;
}
}
int main(){
int arr[10];
for(int i = 0; i < 10; i++){
scanf("%d", &arr[i]);//放到具体每个元素里面 &arr[i] 或者写成arr+i
}
sort(arr, arr+10, compare);
for(int i = 0; i < 10; i++){
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
例题2、成绩排序2
思路:
(1)不是单个信息,创造一个类保存信息
//定义自定义类型
struct Student{
int number;
int score;
};
(2)自定义sort函数排序
(3)用vector数组
代码:
#include <stdio.h>
#include <algorithm>
#include <map>
#include <vector>
using namespace std;
//定义自定义类型
struct Student{
int number;
int score;
};
bool compare(Student lhs, Student rhs){
if(lhs.score < rhs.score){
return true;
}else if(lhs.score == rhs.score && lhs.number < rhs.number){
return true;
}else{
return false;
}
}
int main(){
int n;
scanf("%d", &n);
vector<Student> vec(n);//维持一个动态数组
for(int i = 0; i < n; i++){
scanf("%d%d", &vec[i].number, &vec[i].score);//%d之间不用逗号隔开 .运算符是访问类的成员
}
sort(vec.begin(), vec.end(), compare);
for(int i = 0; i < n; i++){
printf("%d %d\n", vec[i].number, vec[i].score);
}
return 0;
}
例题3、成绩排序※
关键点:
(1)可选排序方式——>两个compare函数
(2)原始成绩单中靠前的学生排列在前——>稳定排序
解决方法:
<1>标准库的stable_sort函数
<2>改造sort函数
易错点:
(1)长度不超过 10的小写字母构成的字符串——>至少11个字符,还有终止符——>多一点最好
char name[20];//长一点,不要小于11
(2)比较稳定性——>结构体内多一个序号成员,比较时纳入序号规则
struct Student{
char name[20];//长一点,不要小于11
int score;
//实现稳定排序
int seq;//序号,比较时纳入序号规则
};
else if(lhs.score == rhs.score && lhs.seq < rhs.seq){
return true;
}
(3)输入到字符数组无需取地址(name)
scanf("%s%d", vec[i].name, &vec[i].score);//name无需取地址,因为name本身是字符数组
代码:
#include <stdio.h>
#include <algorithm>
using namespace std;
struct Student{
char name[20];//长一点,不要小于11
int score;
//实现稳定排序
int seq;//序号,比较时纳入序号规则
};
bool compare0(Student lhs, Student rhs){//高到低
if(lhs.score > rhs.score){
return true;
}else if(lhs.score == rhs.score && lhs.seq < rhs.seq){
return true;
}else{
return false;
}
}
bool compare1(Student lhs, Student rhs){//低到高
if(lhs.score < rhs.score){
return true;
}else if(lhs.score == rhs.score && lhs.seq < rhs.seq){
return true;
}else{
return false;
}
}
int main(){
int n;
scanf("%d", &n);
int flag = -1;//排序规则
scanf("%d", &flag);
// Student student[n];
vector<Student> vec(n);
for(int i = 0; i < n; i++){
scanf("%s%d", vec[i].name, &vec[i].score);//name无需取地址,因为name本身是字符数组
vec[i].seq = i;
}
if(0 == flag){
sort(vec.begin(), vec.end(), compare0);
}else{
sort(vec.begin(), vec.end(), compare1);
}
for(int i = 0 ; i < n; i++){
printf("%s %d\n", vec[i].name, vec[i].score);
}
return 0;
}