自己写的心得,尤其是快速排序,看了几篇都没太明白,又自己总结了一下
快速排序
-
稳定性:不稳定
-
时间复杂度:最佳:O(nlogn), 最差:O(nlogn),平均:O(nlogn)
-
空间复杂度:O(logn)
过程重点
先分为两部分,再递归划分左右——分治思想。
基础操作:划分
目的:最后一个元素确定为中间分界,将数组划分为两部分(一部分都大于,一部分均小于)
做法:
最后一个元素看作基准,前序元素从前到后与其比较。
-
若前序元素>基准,指针指向大数。索引后移。
-
若前序元素<基准,指针与索引互相交换。
确定指针。指针指向的数会在最后与基准交换。因此指针指向一定大于基准数。
-
若指针遇到大数之前:指针与索引统一,交换即不动。指针后移,索引后移
-
若指针遇到大数之后:指针指向大数,慢于索引,索引指向小数,交换将小数置前。指针后移重新寻找大数
递归操作:
终止条件:只有一个元素(low=high)
实现
public static int partition(int[] array, int low, int high) { int pivot = array[high]; int pointer = low; for (int i = low; i < high; i++) { if (array[i] <= pivot) { int temp = array[i]; array[i] = array[pointer]; array[pointer] = temp; pointer++; } System.out.println(Arrays.toString(array)); } int temp = array[pointer]; array[pointer] = array[high]; array[high] = temp; return pointer; } public static void quickSort(int[] array, int low, int high) { if (low < high) { int position = partition(array, low, high); quickSort(array, low, position - 1); quickSort(array, position + 1, high); } }
冒泡排序
-
时间复杂度:最佳:o(n) ,最差:o(n^2), 平均:o(n^2)
-
空间复杂度:o(1)
-
稳定
过程重点
相邻比较,将大数由大到小依次冒泡排到最后
第一次排序过后最大数冒到最后
第二次排序将剩余前n-1个数中最大排到最后
实现
/** * 冒泡排序 * @param arr * @return arr */ public static int[] bubbleSort(int[] arr) { for (int i = 1; i < arr.length; i++) { // Set a flag, if true, that means the loop has not been swapped, // that is, the sequence has been ordered, the sorting has been completed. boolean flag = true; for (int j = 0; j < arr.length - i; j++) { if (arr[j] > arr[j + 1]) { int tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; // Change flag flag = false; } } if (flag) { break; } } return arr; }
boolean只能为true/false
public static int[] bubble sort(int[] arr){ for(int i = 1; i<=arr.length; i++){ boolean flag =false ; for(int j = 0; j<arr.length-i; j++){ if(arr[j]>arr[j+1]){ int temp = arr[j]; arr[j]= arr[j+1]; arr[j+1] = arr[j]; flag = true; } } if(!boolean) break; } return arr; }
选择排序
-
稳定性:不稳定
-
时间复杂度:最佳:O(n2) ,最差:O(n2), 平均:O(n2)
-
空间复杂度:O(1)
过程重点
round1:将第一个数定为最小,向后遍历,遇小交换,选出最小
round2:将第二个数定位最小
......以此类推
实现
// 下标写法 public static int[] selectionSort(int[] arr) { for (int i = 0; i < arr.length - 1; i++) { int minIndex = i; for (int j = i + 1; j < arr.length; j++) { if (arr[j] < arr[minIndex]) { minIndex = j; } } if (minIndex != i) { int tmp = arr[i]; arr[i] = arr[minIndex]; arr[minIndex] = tmp; } } return arr; }
// 麻烦易错的值写法 public static int[] selectsort(int[] arr){ for(int i = 0; i<arr.length-1; i++){ int min = arr[i]; for(int j = i+1; j<arr.length;j++){ if(arr[j]<arr[i]){ int temp = arr[j]; arr[j]= arr[i]; arr[i] = arr[j]; min = arr[i]; } } } return arr; }
插入排序
-
稳定性:稳定
-
时间复杂度:最佳:O(n) ,最差:O(n2), 平均:O(n2)
-
空间复杂度:O(1)$
-
排序方式:In-place
过程重点
类似洗牌。
round1:第一个数看作已有顺序,将下一个数与第一个数比较。大的话不动,小的话第一个数后移一位,空出位置将小数插入。
roundn:前n个数已有顺序,将未排序的第一个数key与有序数列数列从后往前从大到小比较。未排序数大的话不动,小的话将大数向后移动(不会影响后面的已排序数列,因为后面的必定已经移动过),直到找到合适序位
实现
public static int[] insertsort(int[] arr){ for(int i = 1; i<arr.length; i++){ int key = arr[i]; int j = i-1; while(j>=0 && arr[j]>key){ //j>0相当于第一个数没参与排序,不可以, arr[j+1]=arr[j]; j--; } arr[j+1]=key; } return arr; }