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;
}