1.1 排序——直接插入排序、快速排序、冒泡排序、归并排序
清晰直观的解释:十大经典排序算法(动图演示)
一、四种排序
c++ 在<algorithm>
头文件中定义了sort函数,采用快速排序方式,默认方式是升序排列。如果需要倒序
,可以从后往前存储一遍,或采用下面的方式。
“ 关于cmp函数的定义规则我们只需简单的记得,当cmp的返回值为true时,即表示cmp函数的第一个参数将会排在第二个参数之前
。为了实现降序排列,我们只要判断两个参数的大小,当第一个参数比第二个参数大时返回true。 ”
//定义排序规则
bool cmp(int x, int y){
return x>y;
}
//使用sort
sort(src,src+n,cmp);
1.直接插入排序——基于插入的排序
1)使用src[0]
做监视哨,减少比较次数。
2)时间复杂度为n^2
,空间复杂度为1
。
//直接插入排序
void StraightInsertionSort(int *src,int length){
for(int i=2;i<=length;i++){
if(src[i]<src[i-1]){
src[0] = src[i];
}
for(int j=i-1;src[0]<src[j];j--){
src[j+1] = src[j];
}
src[j+1] = src[0];
}
}
2.冒泡排序——基于交换的排序
时间复杂度为n^2
,空间复杂度为1
。
void BubbleSort(int *src,int length){
for(int i=1;i<length;i++){
for(int j=0;j<length-i;j++) {
if(src[j]>src[j+1]){ // 相邻元素两两对比
int t = src[j+1]; // 元素交换
src[j+1] = src[j];
src[j] = t;
}
}
}
}
下面的方法虽然能成功排序,但是不是冒泡排序
//冒泡排序
void BubbleSort(int *src,int length){
for(int i=0;i<length-1;i++){
for(int j=i+1;j<length;j++){
if(src[i]>src[j]){
int t = src[i];
src[i] = src[j];
src[j] = t;
}
}
}
}
3.快速排序——基于交换的排序
1)就平均时间而言,快速排序是目前被认为最好的一种内部排序方法。
2)时间复杂度为nlogn
,空间复杂度为1
。
//快速排序
int QSort(int *src,int low,int high){
int pivotkey = src[low];
while(low < high){
while(low<high && src[high]>=pivotkey) high--;
src[low] = src[high];
while(low<high && src[low]<=pivotkey) low++;
src[high] = src[low];
}
src[low] = pivotkey;
return low;
}
void QuickSort(int *src,int low,int high){
if(low < high){
int pivotPos = QSort(src,low,high);
QuickSort(src,low,pivotPos-1);
QuickSort(src,pivotPos+1,high);
}
}
4.归并排序
时间复杂度为nlogn
,空间复杂度为n
。归并排序的边界,一定要找好。
//归并排序
void MSort(int *src,int *res,int s,int m,int e){
for(int k=s,j=m+1;s<=m && j<=e;k++){
if(src[s]<=src[j]) res[k] = src[s++];
else res[k] = src[j++];
}
while(s<=m) res[k++] = src[s++];
while(j<=e) res[k++] = src[j++];
}
void MergeSort(int *src,int *res,int s,int e){
if(s!=e){
int res1[N];
int m = (s+e)/2;
MergeSort(src,res1,s,m);
MergeSort(src,res1,m+1,e);
MSort(res1,res,s,m,e);
}else{
res[e] = src[e];
}
}
主函数
#include <iostream>
using namespace std;
#define N 100
//打印排序结果
void print(int *src,int length){
for(int i=1;i<=length;i++){
cout<<src[i]<<" ";
}
cout<<endl<<endl;
}
int main(){
int src[N],res[N];
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>src[i];
}
//cout<<"直接插入排序:"<<endl;
// StraightInsertionSort(src,n);
//print(src,n);
//cout<<"冒泡排序:"<<endl;
//BubbleSort(src,n);
//print(src,n);
//cout<<"快速选择排序:"<<endl;
//QuickSort(src,1,n);
//print(src,n);
//cout<<"归并排序:"<<endl;
//MergeSort(src,res,1,n);
//print(res,n);
}
二、例题:成绩排序
1、题目和要求
时间限制:1s,内存限制:32MB,特殊判题:否
2、总结
1)使用了c++自带的头文件<algorithm>
模板库,重新定义了cmp
函数。
2)char[]
比较大小要么自己写,要么用strcmp
。不能直接用<
比较,极少时候对。
//参考
bool cmp(Stu s1,Stu s2){
if(s1.grade != s2.grade) return s1.grade < s2.grade;
int t = strcmp(s1.name,s2.name);
if(t!=0) return t<0;
else return s1.age < s2.age;
}
//自己写的
bool cmp(Stu s1,Stu s2){
if(s1.grade > s2.grade){
return true;
}else if(s1.grade == s2.grade){
int t = strcmp(s1.name,s2.name);
if(t!=0) return t<0;
else return s1.age < s2.age;
}
}
2)直接定义该结构体的小于运算符:
第一个 const
是保证 s 不发生改变,第二个是保证函数不发生改变。
bool operator < (const Stu &s) const{
if(grade != s.grade) return grade < s.grade;
int t = strcmp(name,s.name);
if(t!=0) return t<0;
else return age < s.age;
}
3)程序中使用while(scanf("%d",&n) != EOF)
判断程序何时终止;输入为字符串而程序采用gets()
的方法读入时,则使用while(gets(字符串变量))
。
原理:
scanf
函数是有返回值的,将返回被输入函数成功赋值的变量个数。
- 若成功完成输入并对n赋值,返回值为1。
- 如果输入已经到达结尾(输入文件到达末尾或在命令台输入Ctrl+z),则无法为变量n赋值,于是返回EOF。
4)还有一个小细节:题上说“姓名长度不超过100”,用char[]
存储时,要预留出 ‘\0’ 的位置。即#define NAME_LENGTH 101
。
3、代码
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 1000
#define NAME_LENGTH 100
struct Stu{
char name[NAME_LENGTH];
int age;
double grade;
}s[N];
bool cmp(Stu s1,Stu s2){
if(s1.grade > s2.grade){
return true;
}else if(s1.grade == s2.grade){
int t = strcmp(s1.name,s2.name);
if(t!=0){
return t<0;
}else{
return s1.age < s2.age;
}
}
}
int main(){
int n,i;
while(scanf("%d",&n) != EOF){
for(i=0;i<n;i++){
scanf("%s%d%lf",s[i].name,&s[i].age,&s[i].grade);
}
sort(s,s+n,cmp);
for(i=0;i<n;i++){
printf("%s %d %lf\n",s[i].name,s[i].age,s[i].grade);
}
}
return 0;
}