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=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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章