博主歡迎轉載,但請給出本文鏈接,我尊重你,你尊重我,謝謝~
http://www.cnblogs.com/chenxiwenruo/p/8529525.html
特別不喜歡那些隨便轉載別人的原創文章又不給出鏈接的
所以不准偷偷復制博主的博客噢~~
最近適當復習了下基本的排序算法,雖然做題的時候一般都直接用sort了事,但基本的排序原理還是要了解的,所以把常見的排序又重新寫了下。
基本的插入、選擇、冒泡就不說了,歸並排序、快速排序可以網上搜算法導論的學習,也很簡單。
1.插入排序
void insertSort(int a[],int len){ for(int i=1;i<len;i++){ int tmp=a[i]; int j=i-1; while(j>=0 && tmp<a[j]){ a[j+1]=a[j]; j--; } a[j+1]=tmp; } }
2.選擇排序
void selectSort(int a[],int len){ for(int i=0;i<len-1;i++){ int minidx=i; for(int j=i+1;j<len;j++){ if(a[j]<a[minidx]){ minidx=j; } } if(a[i]>a[minidx]){ int tmp=a[i]; a[i]=a[minidx]; a[minidx]=tmp; } } }
3.冒泡排序
void bubbleSort(int a[],int len){ int tmp; for(int i=0;i<len-1;i++){ bool flag=true; for(int j=0;j<len-i-1;j++){ if(a[j]>a[j+1]){ tmp=a[j+1]; a[j+1]=a[j]; a[j]=tmp; flag=false; } } if(flag) break; } }
4.歸並排序O(NlgN)
#define INF 0x3f3f3f3f /* 將[l,mid]和[mid+1,r]兩個區間進行合並,每次取兩個開頭最小的那個 */ void merges(int a[],int l,int mid,int r){ int len1=mid-l+1; int len2=r-mid; int L[len1+1],R[len2+1]; for(int i=0;i<len1;i++) L[i]=a[l+i]; for(int i=0;i<len2;i++) R[i]=a[mid+1+i]; L[len1]=INF; R[len2]=INF; int left=0,right=0; for(int k=l;k<=r;k++){ if(L[left]<=R[right]){ a[k]=L[left]; left++; } else{ a[k]=R[right]; right++; } } } //對區間[l,r]進行歸並排序 void mergeSort(int a[],int l,int r){ if(l<r){ int mid=(r+l)/2; mergeSort(a,l,mid); mergeSort(a,mid+1,r); merges(a,l,mid,r); } }
5.快速排序O(NlgN)
/* 以最后a[r]為划分點,將數組a划分成兩個部分 前部分<=a[r],后部分>a[r] 最后返回a[r]的索引 */ int quick_partition(int a[],int l,int r){ int x=a[r]; int i=l-1; for(int j=l;j<r;j++){ if(a[j]<=x){ i++; swap(a[i],a[j]); } } swap(a[i+1],a[r]); return i+1; } void quickSort(int a[],int l,int r){ if(l<r){ int mid=quick_partition(a,l,r); quickSort(a,l,mid-1); quickSort(a,mid+1,r); } }
6.最大堆排序O(NlgN)
//----------------堆排序O(NlgN)最大堆的實現-------------------------- /* 將最大堆的根節點和末尾交換后,可能破壞了最大堆的性質,所以要進行更新 */ void heap_update(int a[],int i,int heap_size){ int l=i*2+1; int r=i*2+2; int large=i; if(l<heap_size && a[l]>a[large]) large=l; if(r<heap_size && a[r]>a[large]) large=r; if(large!=i){ swap(a[i],a[large]); heap_update(a,large,heap_size); } } /* 將val插入到數組a的末尾,並進行最大堆的維護 */ void heap_insert(int a[],int val,int heap_size){ heap_size++; a[heap_size-1]=val; int idx=heap_size-1; while(idx>0 && a[idx/2]<a[idx]){ swap(a[idx/2],a[idx]); idx=idx>>1; } } void heapSort(int a[],int len){ //構建最大堆 for(int i=0;i<len;i++) heap_insert(a,a[i],i); for(int i=len-1;i>=0;i--){ swap(a[0],a[i]); heap_update(a,0,i); //每次heap_size減小1的 } }
7.希爾排序
最近突然遇到希爾排序,之前沒聽過,所以就了解一下,不專門寫介紹了,給一篇鏈接吧,講得挺詳細的
https://www.cnblogs.com/chengxiao/p/6104371.html
希爾排序對於增量序列(即gap)的選擇很重要,會影響到排序的性能,通常都采用gap=length/2。
希爾排序是可以突破O(N^2)的,但gap/=2的情況下最壞時間復雜度依然為O(N^2),一些優化過后的序列最壞情況可以到O(N^3/2)。
/* https://www.cnblogs.com/chengxiao/p/6104371.html 希爾排序 */ void shellsort(int a[],int len){ //划分成gap個組 for(int gap=len/2;gap>0;gap/=2){ //從第gap個元素,逐個對其所在組進行插入排序操作 //而不需要for每個組進行操作 for(int i=gap;i<len;i++){ int j=i-gap; //插入排序采用交換法即可 while(j>=0 && a[j]>a[j+gap]){ swap(a[j],a[j+gap]); j-=gap; } } /* printf("gap:%d\n",gap); for(int i=0;i<len;i++) printf("%d ",a[i]); printf("\n"); */ } }
完整的測試代碼:
#include <iostream> #include <cstdio> #include <algorithm> #include <string.h> #include <cstdlib> #include <ctime> using namespace std; //----------------插入排序-------------------------- void insertSort(int a[],int len){ for(int i=1;i<len;i++){ int tmp=a[i]; int j=i-1; while(j>=0 && tmp<a[j]){ a[j+1]=a[j]; j--; } a[j+1]=tmp; } } //----------------選擇排序-------------------------- void selectSort(int a[],int len){ for(int i=0;i<len-1;i++){ int minidx=i; for(int j=i+1;j<len;j++){ if(a[j]<a[minidx]){ minidx=j; } } if(a[i]>a[minidx]){ int tmp=a[i]; a[i]=a[minidx]; a[minidx]=tmp; } } } //----------------冒泡排序-------------------------- void bubbleSort(int a[],int len){ int tmp; for(int i=0;i<len-1;i++){ bool flag=true; for(int j=0;j<len-i-1;j++){ if(a[j]>a[j+1]){ tmp=a[j+1]; a[j+1]=a[j]; a[j]=tmp; flag=false; } } if(flag) break; } } //----------------歸並排序O(NlgN)-------------------------- #define INF 0x3f3f3f3f /* 將[l,mid]和[mid+1,r]兩個區間進行合並,每次取兩個開頭最小的那個 */ void merges(int a[],int l,int mid,int r){ int len1=mid-l+1; int len2=r-mid; int L[len1+1],R[len2+1]; for(int i=0;i<len1;i++) L[i]=a[l+i]; for(int i=0;i<len2;i++) R[i]=a[mid+1+i]; L[len1]=INF; R[len2]=INF; int left=0,right=0; for(int k=l;k<=r;k++){ if(L[left]<=R[right]){ a[k]=L[left]; left++; } else{ a[k]=R[right]; right++; } } } //對區間[l,r]進行歸並排序 void mergeSort(int a[],int l,int r){ if(l<r){ int mid=(r+l)/2; mergeSort(a,l,mid); mergeSort(a,mid+1,r); merges(a,l,mid,r); } } //----------------快速排序O(NlgN)-------------------------- /* 以最后a[r]為划分點,將數組a划分成兩個部分 前部分<=a[r],后部分>a[r] 最后返回a[r]的索引 */ int quick_partition(int a[],int l,int r){ int x=a[r]; int i=l-1; for(int j=l;j<r;j++){ if(a[j]<=x){ i++; swap(a[i],a[j]); } } swap(a[i+1],a[r]); return i+1; } void quickSort(int a[],int l,int r){ if(l<r){ int mid=quick_partition(a,l,r); quickSort(a,l,mid-1); quickSort(a,mid+1,r); } } int main() { int num=10; int a[num]; srand((unsigned)time(NULL)); for(int i=0;i<num;i++){ a[i]=rand()%20; printf("%d ",a[i]); } printf("\n"); quickSort(a,0,num-1); for(int i=0;i<num;i++){ printf("%d ",a[i]); } return 0; }
最后,當然排序最省力的就是C++中的自定義排序了,直接用algorithm中的sort即可。
#include <algorithm> bool cmp(int a,int b){ return a>b; } sort(a,a+n); //a為數組,n為數組的長度,默認是從小到大排序 sort(a,a+n,cmp);//cmp即為自定義比較函數,此處是從大到小排序。
