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