以下总结常见排序算法及其实现。对面试尤为有用。
中文 | 英文 | 时间复杂度(最坏和平均) | 稳定性 | 空间复杂度 | 备注 |
冒泡排序 | Bubble Sort | O(n2)/O(n2) | YES | O(1) | 即使在O(n2)算法中也是效率低下的。关键,每次冒泡 之后,最后一个元素是已经排序好的,所以不用再排了。 如果一轮排序后已经没有swap,则不用再排了。 |
插入排序 | Insertion Sort | O(n2)/O(n2) | YES | O(1) | 有一些优势:在O(n2)算法中,效率较高,如果数据集 基本有序,则效率较高。从数据结构上来说,使用链表 会使效率较高。
在数组上实现的方法:第n步排前n个元素,第n+1步插 |
选择排序 | Selection Sort | O(n2)/O(n2) | NO | O(1) | 比插入稍差。实现简单。基本思想是第n步找a[n:] 之中最小的那个,与a[n]交换。 |
快速排序 | Quick Sort | O(n2)/O(nlogn) | No | O(logn) | 比其他的O(nlogn)算法在实际上都要快一些,所以用的 最多。
基本思路,找到一个pivot value,利用这个pivot 在数组上实现的方法:写一个partition函数,首先,把 |
堆排序 | Heap Sort | O(nlogn)/O(nlogn) | NO | O(n)/C | 与Quick Sort相比,Heap Sort有较低的Worst Case Complexity。但是在实际情况下运行得较慢。在实时 系统中,为保证速度稳定性,常用堆排序。
与归并排序相比,最大的问题是依赖于随机存储。不适用 Merge Sort比较适用于并行计算。 |
归并排序 | Merge Sort | O(nlogn)/O(nlogn) | YES | O(n) | 见上。 |
代码 (in Java)
1. 冒泡排序
public int[] sort(int[] r) { for(int i = 0; i<r.length;i++){ for(int j = 0; j< r.length-i-1;j++){ if(r[j]>r[j+1]){ swap(r,j,j+1); } } } return r; }
2. 插入排序
public int[] sort(int[] r) { for(int i = 1 ; i<r.length ; i++){ int value = r[i]; for(int j = 0; j< i; j++){ if(r[j] > value){ for(int l = j ; l < i; l++){ r[l+1] = r[l]; } r[j] = value; break; } } } return r; }
3. 选择排序
public int[] sort(int[] r) { for(int i = 0; i<r.length;i++){ int min = Integer.MAX_VALUE; int minpos = -1; for(int j=i; j<r.length;j++){ if(r[j]<min){ min = r[j]; minpos = j; } } swap(r,i,minpos); } return r; }
4. 快速排序
int partition(int[] r, int left, int right, int pivotIndex){ swap(r,pivotIndex, right); int storeIndex = left; int pivotValue = r[right]; for(int i = left; i< right ; i++){ if(r[i]<=pivotValue){ swap(r,i,storeIndex); storeIndex = storeIndex+1; } } swap(r,storeIndex,right); return storeIndex; }
void qsort(int[] r , int left, int right){ if(left == right){ return; }else{ if(right-left==1){ if(r[left]>r[right]){ swap(r,left,right); return; } return; } } int pivotIndex = (left + right) / 2; int nPivotIndex = partition(r,left,right,pivotIndex); if(nPivotIndex>left) qsort(r,left,nPivotIndex-1); if(nPivotIndex<right) qsort(r,nPivotIndex+1,right); }
5. 归并排序
public void merge(int[] r, int left, int right, int center, int[] cache){ int pos = left; int cur1 = left, cur2 = center +1; for(;cur1<=center && cur2 <=right; pos++){ if(r[cur1]<r[cur2]){ cache[pos] = r[cur1]; cur1++; }else{ cache[pos] = r[cur2]; cur2++; } } for(;cur1<=center;cur1++,pos++){ cache[pos] = r[cur1]; } for(;cur2<=right;cur2++,pos++){ cache[pos] = r[cur2]; } for(pos = left ; pos <= right; pos++){ r[pos] = cache[pos]; } } public void merge_sort(int[] r, int left, int right, int[] cache){ int len = right - left +1; if(len <= 1){ return; }else{ int center = (left + right)/2; merge_sort(r,left,center,cache); merge_sort(r,center+1,right,cache); merge(r,left,right,center,cache); } }
6.