import java.util.Arrays; public class QuickSort { public static void main(String[] args){ QuickSort quickSort = new QuickSort(); int arr[] = {4, 6, 1, 2, 9, 0, 3, 11, 5}; quickSort.quickSort(arr); System.out.println(Arrays.toString(arr)); } public void quickSort(int[] arr){ quickSortSub(arr,0,arr.length - 1); } public void quickSortSub(int[] arr,int low,int high){ if(low < high){ int middle = partition(arr, low, high); quickSortSub(arr, low, middle - 1); quickSortSub(arr,middle + 1,high); } } public int partition(int[] arr,int low,int high){ int base = arr[high]; int i = low - 1; for(int j = low; j <= high - 1; j++){ if(arr[j] <= base){ i++; swap(arr,i,j); } } swap(arr,i+1,high); return i + 1; } public void swap(int[] arr,int i,int j){ int temp = 0; temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } }
實現partition函數有不少種方式,前面介紹的方式是兩個指針low和high都是從頭開始,向同一個方向移動,high指針在low的前面,high指針標記的是比基準數大的,low指針標記的是比基準數小的java
接下來咱們一樣採用兩個指針low和high,只不過這兩個指針是相向運動,當兩個指針相遇的時候就中止算法
public int partition1(int[] arr,int low,int high){ int base = arr[low]; int i = low; int j = high; while (i < j){ while ( arr[j] > base) j--; if(arr[j] < base){ swap(arr, i, j); i++; } while (arr[i] < base) i++; if(arr[i] > base){ swap(arr,i,j); j--; } } return i; }
快速排序算法的時間複雜度關鍵在於拆分的時候是否平衡,若是每次拆分的時候,下標恰好在中間,即q = (p+r)/2數組
那麼性能和歸併排序同樣都是O(nlogn)函數
若是拆分的時候,恰好拆分的地方另外一部分只有一個元素,那麼性能和插入排序沒有什麼區別,那麼此時拆分須要拆分n次,對於每次拆分都須要調用partition函數找到拆分處的下標,partition的時間複雜度爲θ(n)性能
因此最壞時間複雜度爲:θ(n * n) = θ(n^2)ui
最壞時間複雜度:O(n^2)spa
平均時間複雜度:O(nlogn)(元素互異)指針
import java.util.Arrays; public class InsertSort { public static void main(String[] args){ InsertSort insertSort = new InsertSort(); int[] arr = {3, 1, 2, 6, 5, 4}; insertSort.insertSort(arr); System.out.println(Arrays.toString(arr)); } public void 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){ arr[j + 1] = arr[j]; j--; } arr[j + 1] = key; } } }
時間複雜度:O(n^2)code
快速排序和歸併排序都藉助了分治的思想,可是他們也有所差異-排序
import jdk.nashorn.internal.objects.NativeInt16Array; import java.util.Arrays; public class MergeSort { public static void main(String[] args){ MergeSort mergeSort = new MergeSort(); int[] arr = {6, 2, 3, 9, 0, 1, 55}; mergeSort.mergerSort(arr); System.out.println(Arrays.toString(arr)); } public void mergerSort(int[] arr){ mergeSortSub(arr,0,arr.length - 1); } public void mergeSortSub(int[] arr,int low,int high){ if(low < high){ int middle = (int) Math.floor((low + high) >> 1); mergeSortSub(arr,low,middle); mergeSortSub(arr,middle+1,high); merge(arr,low,middle,high); } } public void merge(int[] arr,int low,int middle,int high){ int len1 = middle - low + 1; int len2 = high - middle; int[] arr1 = new int[len1 + 1 ]; int[] arr2 = new int[len2 + 1]; for(int i = 0; i < len1; i++){ arr1[i] = arr[low + i]; } for(int i = 0; i < len2; i++){ arr2[i] = arr[middle + i + 1]; } //防止數組越界 arr1[len1] = Integer.MAX_VALUE; arr2[len2] = Integer.MAX_VALUE; int t = 0, s = 0; for(int i = low; i <= high; i++){ if(arr1[t] <= arr2[s]){ arr[i] = arr1[t]; t++; }else { arr[i] = arr2[s]; s++; } } } }
執行拆分的時候須要執行:log2(n)次
有多少次拆分就須要多少次合併,每次合併的時候須要比較的次數:n次,n = high - low + 1
因此總的時間複雜度爲:θ(logn * n) = θ(nlogn)