七、排序 1.时间复杂度
平均情况下,快排,希尔排序(复杂度了解即可)、归并排序和堆排序的复杂度为O(nlog²n),其他都是O(n²)。一个特殊的是计数排序,其复杂度为O(n*k)
最坏情况下,快速排序的为O(n²),其他都和平均情况下相同
2.空间复杂度
快排O(nlog²n),归并O(n),基数O(n+k),其他都是O(1)
快排、希尔、简单选择、堆排序是不稳定的,其余均为稳定的。
插入排序 时间复杂度:最好O(n) 最坏O(n²) 平均O(n²)
空间复杂度:O(1)
稳定
直接插入排序 1 2 3 4 5 6 7 8 9 10 11 void InsertSort (int arr[],int n) { for (int i = 1 ; i < n;i++){ int t = arr[i]; int j = i; while (j&&t < arr[j-1 ]){ arr[j] = arr[j-1 ]; j--; } arr[j] = t; } }
折半插入排序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 void binary_sort () { for (int i=1 ;i<n;i++){ if (a[i-1 ]<a[i])continue ; int t=a[i],l=0 ,r=i-1 ; while (l<r){ int mid=l+r>>1 ; if (a[mid]>t) r=mid; else l=mid+1 ; } for (int j=i-1 ;j>=r;j--){ a[j+1 ]=a[j]; } a[r]=t; } }
希尔排序 时间复杂度:最好O(nlog²n) 最坏O(nlog²n) 平均O(nlogn)
空间复杂度:O(1)
不稳定排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 void ShellSort (int num[],int len) { for (int d = len / 2 ;d > 0 ;d /= 2 ){ for (int start = 0 ;start < d;start++){ for (int i = start + d;i < len ; i++){ int t = num[i]; int j = i; while (j > start && num[j - d] > t){ num[j] = num[j - d]; j -= d; } num[j] = t; } } } }
冒泡排序 时间复杂度:最好O(n) 最坏O(n²) 平均O(n²)
空间复杂度 O(1)
稳定
1 2 3 4 5 6 7 8 9 10 void Bubble_Sort (int arr[],int len) { int i, j, temp; for (i = 0 ; i < len - 1 ; i++) for (j = 0 ; j < len - 1 - i; j++) if (arr[j] > arr[j + 1 ]) { temp = arr[j]; arr[j] = arr[j + 1 ]; arr[j + 1 ] = temp; } }
快速排序 时间复杂度:最好O(nlogn) 最坏为O(n²) 平均O(nlogn)
空间复杂度:O(logn)
不稳定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 void Quick_Sort (int arr[],int l,int r) { int i = l,j = r; if (l < r){ int temp = arr[l]; while (i < j){ while (i < j && arr[j] >= temp) j--; if (i < j){ arr[i] = arr[j]; i++; } while (i < j && arr[i] < temp) i++; if (i < j){ arr[j] = arr[i]; j--; } } arr[i] = temp; } Quick_Sort (arr,l, i - 1 ); Quick_Sort (arr,i + 1 ,r); }
选择排序 时间复杂度:最好O(n) 最坏O(n²) 平均O(n²)
空间复杂度:O(1)
不稳定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 void Selection_Sort (int arr[],int len) { int i,j,temp; for (i = 0 ; i < len - 1 ; i++) { int k = i; for (j = i + 1 ; j < len; j++) if (arr[j] < arr[k]) k = j; if (k != i){ temp=arr[min]; arr[min]=arr[i]; arr[i]=temp; } } }
堆排序(看成完全二叉树,根结点要么最大要么最小) 时间复杂度:最好O(nlogn) 最坏为O(nlogn) 平均O(nlogn)
空间复杂度:O(1)
不稳定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 void sift (int arr[],int low,int high) { int i,j; i=low,j=2 *i; int temp=arr[low]; while (j<=high){ if (j<high&&arr[j]<arr[j+1 ]) j++; if (temp<arr[j]){ arr[i]=arr[j]; i=j; j=2 *i; } else break ; } arr[i]=temp; } void Heap_Sort (int n,int arr[]) { int temp; for (int i=n/2 ;i>=1 ;i--) sift (arr,i,n); for (int i=n;i>=2 ;i--){ temp=arr[1 ]; arr[1 ]=arr[i]; arr[i]=temp; sift (arr,1 ,i-1 ); } }
二路归并排序 时间复杂度:最好O(nlogn) 最坏为O(nlogn) 平均O(nlogn)
空间复杂度:O(n)
稳定
思想:先两两归并,然后两两归并,最后两两归并
对于一个左边一半和右边一半分别有序的数组,合并成一个新的整体有序的数组,需要注意的是,这里需要一个和原数组一样大的辅助空间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 void MergrSort (int arr[],int n,int low,int high) { if (low < high){ int mid = (low + high) / 2 ; MergrSort (arr, low, mid); MergrSort (arr, mid+1 , high); int temp[Maxn]; int i = low,j = mid + 1 ,k = 0 ; while (i <= mid && j <= high){ if (arr[i] <= arr[j]){ temp[k++] = arr[i++]; } else { temp[k++] = arr[j++]; } } while (i <= mid){ temp[k++] = arr[i++]; } while (j <= high){ temp[k++] = arr[j++]; } for (i = low,j = 0 ;j < k;i++,j++) arr[i] = temp[j]; } }
基数排序 时间复杂度:最好O(n * k) 最坏为O(n * k) 平均O(n * k)
空间复杂度:O(n + k)
稳定