1.归并排序
归并排序,是创建在归并操作上的一种有效的排序算法。算法是采用分治法(Divide and Conquer)的一个非常典型的应用,且各层分治递归可以同时进行。归并排序思路简单,速度仅次于快速排序,为稳定排序算法,一般用于对总体无序,但是各子项相对有序的数列。
java代码:
public class Code01_MergeSort {public static void process(int[] arr, int L, int R){if (L == R){return;}int mid = L + ((R - L) >> 1);process(arr, L, mid);process(arr, mid+1, R);merge(arr, L, mid, R);}public static void merge(int[] arr, int L, int M, int R){int[] help = new int[R-L+1];int i = 0;int p1 = L;int p2 = M + 1;while (p1 <= M && p2 <= R){help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];}while (p1 <= M){help[i++] = arr[p1++];}while (p2 <= R){help[i++] = arr[p2++];}for(i = 0; i < help.length; i++){arr[L+i] = help[i];}}}
JavaScript代码:
function process(arr, L, R){if(L == R){return;}var mid = L + Math.floor((R-L)/2);process(arr, L, mid);process(arr, mid+1, R);merge(arr, L, mid, R);}function merge(arr, L, M, R){let help = [];let i = 0;let p1 = L;let p2 = M+1;while(p1 <= M && p2 <= R){help[i++] = arr[p1] >= arr[p2] ? arr[p1++] : arr[p2++];}while(p1 <= M){help[i++] = arr[p1++];}while(p2 <= R){help[i++] = arr[p2++];}for(i = 0; i < help.length; i++){arr[L+i] = help[i];}}
1)整体就是一个简单递归,左边排好序、右边排好序、让其整齐有序
2)让其整体有序的过程里用了外排序方法
3)利用master公式来求解时间复杂度
4)归并排序的实质
时间复杂度O(N*logN),额外空间复杂度O(N)
2.快速排序
快排1、2版本时间复杂度都是O(N^2), 快排3版本是O(N*logN)。
不改进的快速排序:
1) 把数组范围的最后一个数作为划分值,然后把数组通过荷兰国旗问题分成三个部分:
左侧<划分值、中间==划分值、右侧>划分值
2) 把左侧范围和右侧范围,递归执行
分析:
1)划分值越靠近两侧,复杂度越高,划分值越靠近中间,复杂度越低
2)可以轻而易举的举出最差的例子,所以不改进的快速排序时间复杂度为O(N^2);
随机快速排序
1)在数组范围中,等概率随机选一个数作为划分值,然后把数组通过荷兰国旗问题分成三个部分:
左侧<划分值、中间==划分值、右侧>划分值
2) 对左侧范围和右侧范围、递归执行
3)时间复杂度为O(N*logN);
快排3版本代码:
package class02;public class Code03_QuickSort {public static void quickSort(int[] arr){if(arr == null || arr.length < 2){return;}quickSort(arr, 0, arr.length-1);}// arr[l...r]排好序public static void quickSort(int[] arr, int L, int R){if(L < R) {swap(arr, L + (Math.random() * (R-L+1), R);int[] p = partition(arr, L, R);quickSort(arr, L, p[0]-1);quickSort(arr, p[1]+1, R);}}// 这是一个处理arr[l...r]的函数// 默认以arr[r]做划分,arr[r] -> p <p --p >p// 返回等于区域(左边界,右边界),所以返回一个长度为2的数组res,res[0] res[1]public static int[] partition(int[] arr, int L, int R){int less = L - 1;int more = R;while(L < more){if(arr[L] < arr[R]){swap(arr, ++less, L++);} else if(arr[L] > arr[R]){swap(arr, --more, L);} else{L++;}}swap(arr, more, R);return new int[] {less+1, more };}public static void swap(int[] arr, int x, int y) {int temp = arr[x];arr[x] = arr[y];arr[y] = temp;}}
JavaScript代码:
function quickSort(arr) {if(arr === null || arr.length < 2){return;}quickSortT(arr, 0, arr.length-1);return arr;}function quickSortT(arr, L, R) {if(L < R) {swap(arr, L + Math.floor(Math.random() * (R-L+1)), R);let p = partition(arr, L, R);quickSortT(arr, L, p[0] -1); // <区域quickSortT(arr, p[1]+1, R); // >区域}}function partition(arr, L, R) {let less = L - 1; // 区左边界let more = R; // 区右边界while(L < more){ //表示当前数的位置 arr[R] -> 划分值if(arr[L] < arr[R]){ // 当前数 < 划分值swap(arr, ++less, L++);} else if(arr[L] > arr[R]){ // 当前数 > 划分值swap(arr, --more, L);} else{L++;}}swap(arr, more, R);return [less+1, more];}function swap(arr, x, y) {let temp = arr[x];arr[x] = arr[y];arr[y] = temp;}
