- 选择排序 o(n^2)
//从后面所有的值中每次选出最小值
for(int i = 0;i < n;i++){
int min = i;
for(int j = i+1;j < n;j++){
if(a[j] < a[min])
min = j;
swap(a[i],a[min]);
}
}
- 插入排序 o(n^2)
//从第一个值开始每次将值插到它应该在的位置
for(int i = 1;i < n;i++){
for(int j = i;j > 0&&arr[j] < arr[j-1];j--){
swap(arr[j],arr[j-1]);
}
}
- 交换的操作比比较的操作耗时
- 插入排序优化:将一次次的交换用赋值取代
for(int i = 1;i < n;i++){
T e = arr[i];
int j;
for(j = i; j > 0 && arr[j-1] >e; j--){
arr[j] = arr[j-1];
}
arr[j] = e;
}
- 插入排序对近乎有序的排序性能甚至比nlogn级别的排序更好
- 归并排序 o(nlgn)
void mergeSort(T arr[],int n){
__mergeSort(arr,0,n-1);
}
//递归使用归并
void __mergeSort(T arr[],int l,int r){
if(l>=r)
return ;
int mid = (l+r)/2;
__mergeSort(arr,l,mid);
__mergeSort(arr,mid+1,r);
__merge(arr,l,mid,r);
}
//将arr[l....mid]和arr[mid+l....r]两部分进行归并
void __merge(T arr[],int l,int mid,int r){
T aux[r-l+1];
//将值先复制一份
for(int i = l;i<=r;i++){
aux[i-l] = arr[i];
}
int i = l,j = mid +l;
for(int k = l;k<=r;k++){
if(i>mid){
arr[k] = aux[j-l];
j++;
}
else if(j>r){
arr[k] = aux[i-l];
i++;
}
else
if(aux[i-l] < aux[j-l]){
arr[k] = aux[i-l];
i++;
}
else{arr[k] = aux[j-l];
j++;
}
}
}
- 归并排序的优化
//当arr[mid]小于arr[mid+1]时,不用再归并
__mergeSort(arr,l,mid);
__mergeSort(arr,mid+1,r);
if(arr[mid]>arr[mid+1])
__merge(arr,l,mid,r);
元素量非常小的时候,整个数组近乎有序的概率比较大,可以转而使用插入排序来提高性能
if(r-l)<=15{
insertSort(arr,l,r);
return ;
}
void insertSort(T arr[],int l,int r){
for(int i=l+1;i<r;i++)
T e = arr[i];
for(int j=i;j>l&&arr[j-1]>e;j--){
arr[j]=arr[j-1];
arr[j]=e;
}
return ;
}
- 自底向上的归并排序(可对链表进行排序)
void mergeSortBU(T arr[],int n){
for(int sz=1;sz<n;sz+=sz){
for(int i=0;i+sz<n;i+=sz+sz)
__merge(arr,i,i+sz-1,min(i+sz+sz-1));
}
}
- 快速排序 o(nlgn)
void quickSort(T arr[],int n){
__quickSort(arr,0,n-1);
}
__quickSort(T arr[],l,r){
if(l>r)
return ;
int p = __partition(arr,l,r);
__quickSort(arr,l,p-1);
__quickSort(arr,p+1,r);
}
int __partition(T arr[],int l,int r){
T v = arr[l];
int j=l;
for(int i=l+1;i<=r;i++){
if(arr[i]<v){
swap(arr[j+1],arr[i]);
j++;
}
}
swap(arr[j],arr[l]);
return j;
}
- 数组近乎有序,快排退化为O(n^2)
- 快排优化,用随机化种子实现快排在近乎有序时的优化
swap(arr[l],arr[rand%(r-l+1)+l]);
12.双路快速排序法
int partition(T arr[],int l,int r){
swap(arr[l],arr[rand%(r-l+1)+l]);
T v = arr[l];
int i=l+1,j=r;
while(true){
while(i<=r&&arr[i]<v) i++;
while(j>=l&&arr[j]>v) j--;
if(i>j) break;
swap(arr[i],arr[j]);
i++;
j--;
}
swap(arr[l],arr[j]);
return j;
}
- 三路快速排序法
void quickSort3Ways(T arr[],int l,int r){
if(r-l<=15){
InsertSort(arr,l,r);
return ;
}
swap(arr[l],arr[rand%(r-l+1)+l]);
T v = arr[l];
int lt=l,i=l+1,gt=r+1;
while(i<gt){
if(arr[i]<v){
swap(arr[lt+1],arr[i]);
lt++;
i++;
}
else if(arr[i]>v){
swap(arr[i],arr[gt-1]);
gt--;
}
else{
i++;
}
}
swap(arr[l],arr[lt]);
}
- 归并排序和快速排序都采用了分治算法