1.直接插入排序
void InsertSort(int *arr, int length) { for(int i=1; i<length; ++i) { if(arr[i]<arr[i-1]) { int tmp=arr[i]; int j; for(j=i; j-1>=0 && tmp<arr[j-1]; --j)//后移 { arr[j]=arr[j-1]; } arr[j]=tmp;//插入 } } }
2.希尔排序
void ShellInsert(int *arr, int length, int dk) { for(int i=dk; i<length; i=i+dk) { if(arr[i]<arr[i-dk]) { int tmp=arr[i]; int j; for(j=i; j-dk>=0 && tmp<arr[j-dk]; j=j-dk)//后移 { arr[j]=arr[j-dk]; } arr[j]=tmp;//插入 } } } void ShellSort(int *arr, int length) { int dlta[]={5, 3, 1}; for(unsigned long i=0; i<sizeof(dlta)/4; ++i) { ShellInsert(arr, length, dlta[i]);//做一趟增量为dlta[i]的插入排序 } }
3.简单选择排序
void SelectSort(int *arr, int length) { for(int i=0; i<length; ++i) { int min=i; for(int j=i+1; j<length; ++j)//选择最小 { if(arr[min]>arr[j])min=j; } int tmp=arr[i];//交换 arr[i]=arr[min]; arr[min]=tmp; } }
4.堆排序
void HeapAdjust(int *arr, int s, int m) { int tmp=arr[s]; for(int j=2*s+1; j<=m; j=2*j+1)//j表示s的子节点,由于数组下标从0开始,故j=2*s+1 { if(j<m && arr[j]<arr[j+1])++j;//如果右子树存在,则j指向左右子树中最大的 if(tmp>arr[j])break;//如果不需交换就退出,否则就令父节点的值等于子节点,令s=j往下接着比较 arr[s]=arr[j]; s=j; } arr[s]=tmp;//插入 } void HeapSort(int *arr, int length) { int i; int tmp; for(i=length/2-1; i>=0; --i) { HeapAdjust(arr,i,length-1);//调整为大顶堆 } for(i=length-1; i>0; --i)//交换第一个元素 { tmp=arr[0]; arr[0]=arr[i]; arr[i]=tmp; HeapAdjust(arr,0,i-1);//自上而下,重新调整为大顶堆 } }
/******************************************************************************/或者另外一种更加易懂的写法
void HeapAdjust(vector<int> &numbers, int begin, int end) { int parent=begin; int child=parent*2+1; while(child<=end) { if(child+1<=end && numbers[child]<numbers[child+1])++child; if(numbers[parent]<numbers[child]) { int tmp=numbers[parent]; numbers[parent]=numbers[child]; numbers[child]=tmp; } parent=child; child=parent*2+1; } } void HeapSort(vector<int> &numbers, int length) { for(int i=length/2-1; i>=0; --i)HeapAdjust(numbers, i, length-1); for(int i=length-1; i>0; --i) { int tmp=numbers[0]; numbers[0]=numbers[i]; numbers[i]=tmp; HeapAdjust(numbers, 0, i-1); } }
5.冒泡排序
void BubbleSort(int *arr, int length) { for(int i=length-1; i>=1; --i) { for(int j=1; j<=i; ++j) { if(arr[j-1]>arr[j])//交换 { int tmp=arr[j-1]; arr[j-1]=arr[j]; arr[j]=tmp; } } } }
6.快速排序
#include<iostream> using namespace std; int Partition(int *arr, int low, int high) { int tmp=arr[low]; while(low<high) { while(low<high && arr[high]>=tmp)--high; arr[low]=arr[high]; while(low<high && arr[low]<=tmp)++low; arr[high]=arr[low]; } arr[low]=tmp; return low; } void QuickSort(int *arr, int low, int high) { if(low<high) { int mid=Partition(arr, low, high);//一分为二 QuickSort(arr, low, mid-1);//对左边进行一次快排 QuickSort(arr, mid+1, high);//对右边进行一次快排 } } int main() { int arr[]={49, 38, 65, 97, 76, 13, 27, 49}; QuickSort(arr, 0, 7); return 0; }
7.归并排序
void Merge(int *tmp, int *arr, int start, int mid, int end) { int i, j, k; for(i=start, j=mid+1, k=start; i<=mid && j<=end; ++k) { if(tmp[i]<tmp[j])arr[k]=tmp[i++]; else arr[k]=tmp[j++]; } while(i<=mid)arr[k++]=tmp[i++]; while(j<=end)arr[k++]=tmp[j++]; for(int idx=start; idx<=end; ++idx)tmp[idx]=arr[idx];//将排好序的arr[start...end]复制到tmp[start...end]中 } void MSort(int *arr, int *tmp, int start, int end) { if(start==end) { tmp[start]=arr[start]; return; } else if(start>end) return; else { int mid=(start+end)/2;//从中间分界 MSort(arr, tmp, start, mid);//对arr[start...mid]进行一次归并排序,排序结果放至tmp[start...mid] MSort(arr, tmp, mid+1, end);//对arr[mid+1...end]进行一次归并排序,排序结果放至tmp[mid+1...end] Merge(tmp, arr, start, mid, end);//将tmp[start...mid]和tmp[mid+1...end]合并至arr[start...end] } } void MergeSort(int *arr, int length) { int *tmp=new int[length]();//分配辅助空间 MSort(arr, tmp, 0, length-1); delete [] tmp; } /************************************************************************************/或者另外一种更加清楚的写法 void Merge(vector<int> &numbers, int begin, int mid, int end) { int *arr=new int[end-begin+1]; int i, j, k; for(i=begin, j=mid+1, k=0; i<=mid && j<=end; ++k) { if(numbers[i]<numbers[j])arr[k]=numbers[i++]; else arr[k]=numbers[j++]; } while(i<=mid)arr[k++]=numbers[i++]; while(j<=end)arr[k++]=numbers[j++]; for(i=begin; i<=end; ++i)numbers[i]=arr[i-begin]; delete []arr; } void MergeSort(vector<int> &numbers, int begin, int end) { if(begin<end) { int mid=(begin+end)/2; MergeSort(numbers, begin, mid); MergeSort(numbers, mid+1, end); Merge(numbers, begin, mid, end); } }
8.基数排序
void RadixSort(int *arr, int length) { vector<int> bucket[10];//数组0-9,设置10个桶 int m=10; while(true) { bool flag=true; for(int idx=0; idx<length; ++idx) { int tmp=(arr[idx]%m)/(m/10);//m=10,取个位;m=100,取十位... bucket[tmp].push_back(arr[idx]);//按位放入桶中 if(m<=arr[idx])flag=false;//循环终止条件 } int k=0; for(int i=0; i<10; ++i)//将桶中元素倒出 { for(size_t j=0; j<bucket[i].size(); ++j) { arr[k++]=bucket[i][j]; } bucket[i].clear(); } if(flag)break; m=m*10;//开始下一轮比较 } }
总结
排序方法 | 时间复杂度 | 空间复杂度 | 稳定性 | ||
最好 | 最坏 | 平均 | |||
直接插入排序 | O(n) | O(n2) | O(n2) | O(1) | 稳定 |
希尔排序 | O(n) | O(n2) | O(n1.3) | O(1) | 不稳定 |
简单选择排序 | O(n) | O(n2) | O(n2) | O(1) | 不稳定 |
堆排序 | O(n*log2n) | O(n*log2n) | O(n*log2n) | O(1) | 不稳定 |
冒泡排序 | O(n) | O(n2) | O(n2) | O(1) | 稳定 |
快速排序 | O(n*log2n) | O(n2) | O(n*log2n) | O(log2n) | 不稳定 |
归并排序 | O(n*log2n) | O(n*log2n) | O(n*log2n) | O(log2n)~O(n) | 稳定 |
基数排序 | O(d(r+n)) | O(d(r+n)) | O(d(r+n)) | O(rd+n) | 稳定 |
注:r代表关键字基数,d代表长度,n代表关键字个数 |