1. 选择排序 o n平方/o1
在剩余的数组中选取最小值与数组第一位替换
缺点是:无论是基本有序的数组还是乱序的数组,使用的时间是一致的
1 public void selectSort(int[] a){ 2 for (int i = 0; i < a.length; i++) { 3 int min = i; 4 for (int j = i+1; j < a.length; j++) { 5 if (a[min]>a[j]){ 6 swap(a,min,j); 7 min = j; 8 } 9 } 10 } 11 }
1 public void swap(int[] a,int i,int j){ 2 int temp = a[i]; 3 a[i] = a[j]; 4 a[j] = temp;
}
1 void swap(int[] arr,int i,int j){ 2 int[i] = int[i] ^ int[j]; 3 int[j] = int[i] ^ int[j]; 4 int[i] = int[i] ^ int[j]; 5 }
2. 插入排序(稳定性排序) o n平方/o1
每次都跟前面排好序的数组进行比较 后面小于前面就互换
比较适合基本有序的数组 大概比选择排序快1.7倍
1 public void insertion(int[] a){ 2 for(int i = 1;i<a.length;i++){ 3 for(int j = i;j>0&&a[j]<a[j-1];j--){ 4 swap(a,j,j-1); 5 } 6 } 7 }
3.希尔排序
希尔排序是插入排序的进化版,有点像最优子问题一样,先达到大概有序 最后进行一次插入排序
1 public void shell(int[] a){ 2 3 // 先确定一个步长h 4 int h = a.length/2; 5 6 // 等于1时就是进行一次插入排序 7 while(h>=1){ 8 for(int i = h;i<a.lenght;i++){ 9 for(int j = i;j >= h && a[j]<a[j-h];j-=h){ 10 swap(a,j,j-h); 11 } 12 } 13 h/=2; 14 } 15 16 }
4.冒泡排序(稳定排序) o n平方/o1
每一轮都得出一个最大的数放最右边
public void bubbol(int[] arr) { for (int i = arr.length - 1; i > 0; i--) { for (int j = 0; j < i; j++) { if (arr[j] > arr[j + 1]) { arr[j + 1] = arr[j] ^ arr[j + 1]; arr[j] = arr[j] ^ arr[j + 1]; arr[j + 1] = arr[j] ^ arr[j + 1]; } } } }
5. 归并排序(稳定排序) o n*logn/o n
遍历分成两个数组,两个数组双指针合并
1 public void process(int[] arr, int l, int r) { 2 if (l == r) { 3 return; 4 } 5 int mid = l + ((r - l) >> 1); 6 process(arr,l,mid); 7 process(arr,mid+1, r); 8 merge(arr,l,mid,r); 9 } 10 11 public int merge(int[] arr, int l, int mid, int r) { 12 int p1 = l; 13 int p2 = mid + 1; 14 int ret = 0; 15 int i = 0; 16 int[] help = new int[r - l + 1]; 17 while (p1 <= mid && p2 <= r) { 18 // 这一步是计算经过几次调换 19 ret += arr[p1] < arr[p2] ? (r - p2 + 1) * arr[p1] : 0; 20 // 小值移动到数组的左边 21 help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++]; 22 } 23 // 移动剩余值 24 while (p1 <= mid) { 25 help[i++] = arr[p1++]; 26 } 27 while (p2 <= r) { 28 help[i++] = arr[p2++]; 29 } 30 // 用辅助内存替换原数组的值 31 for (i = 0; i < help.length; i++) { 32 arr[l + i] = help[i]; 33 } 34 return ret; 35 }
6. 快速排序 o n*logn/o logn
选取一个数,大于这个数的放右边 小于这个数的放左边 等于这个数的放中间 没进行一次确定一批相同值的位置
1 public void sort(int[] arr, int l, int r) { 2 if (l < r) { 3 // 选出随机值 4 AlUtils.swap(arr, (int) (l + Math.random() * (r - l + 1)), r); 5 // 荷兰国旗一次 6 int[] partition = partition(arr, l, r); 7 // 左区间 8 sort(arr, l, partition[0] - 1); 9 // 右区间 10 sort(arr, partition[1] + 1, r); 11 } 12 } 13 14 public int[] partition(int[] arr, int l, int r) { 15 int less = l - 1; 16 int more = r; 17 while (l < more) { 18 if (arr[l] < arr[r]) { 19 // 目标值是r位置的值 20 // l位置的值小于目标值, l位置与less下一个值交换 l跳下一个 21 AlUtils.swap(arr, l++, ++less); 22 } else if (arr[l] > arr[r]) { 23 // l位置的值大于目标值 l位置与more上一个值交换 l不变 24 AlUtils.swap(arr, l, --more); 25 } else { 26 // l位置的值 与目标值一致不变 l跳下一个 27 l++; 28 } 29 } 30 // 目标值r位置换到中间位置 r位置的值确定了位置 31 AlUtils.swap(arr, more, r); 32 int[] result = {less + 1, more}; 33 return result; 34 }
7. 堆排序 o n*logn/o1
父 (i-1)/2
左 2*i+1
右 2*i +2
1 public void heapInsert(int[] arr, int index) { 2 while (arr[index] > arr[(index - 1) / 2]) { 3 AlUtils.swap(arr, index, (index - 1) / 2); 4 index = (index - 1) / 2; 5 } 6 } 7 8 public void heapify(int[] arr, int index, int heapSize) { 9 int left = index * 2 + 1; 10 while (left < heapSize) { 11 int largest = left + 1 < heapSize && arr[left] < arr[left + 1] ? left + 1 : left; 12 largest = arr[index] < arr[largest] ? largest : index; 13 if (largest == index) { 14 break; 15 } 16 AlUtils.swap(arr, largest, index); 17 index = largest; 18 left = index * 2 + 1; 19 } 20 } 21 22 public void sort(int[] arr) { 23 // 先建立大顶堆 24 for (int i = 0; i < arr.length; i++) { 25 heapInsert(arr, i); 26 } 27 // 第一个值与最后一个值替换 然后heapify 28 int heapSize = arr.length; 29 AlUtils.swap(arr, 0, --heapSize); 30 // 再替换 知道heapsize小于0 31 while (heapSize > 0) { 32 heapify(arr, 0, heapSize); 33 AlUtils.swap(arr, 0, --heapSize); 34 } 35 } 36 37 public void disLessK(int[] arr,int k){ 38 PriorityQueue<Integer> heap = new PriorityQueue<>(); 39 int index = 0; 40 for (;index<=Math.min(arr.length,k);index++){ 41 heap.add(arr[index]); 42 } 43 int i = 0; 44 for (;index<arr.length;i++,index++){ 45 heap.add(arr[index]); 46 arr[i] = heap.poll(); 47 } 48 while (!heap.isEmpty()){ 49 arr[i++] = heap.poll(); 50 } 51 }
8. 桶排序(不基于比较的排序)
统计排序: 创建相同长度的数组,每个数在对应的index+1 最后遍历有值的数组 放入数组
基数排序: 以10进制为例,创建10个桶(队列),个位数放入对应的队列取出,按十位放入对应队列取出,按百位放入对应的队列取出 取出放入数组 有序