1.归并排序

归并排序,是创建在归并操作上的一种有效的排序算法。算法是采用分治法(Divide and Conquer)的一个非常典型的应用,且各层分治递归可以同时进行。归并排序思路简单,速度仅次于快速排序,为稳定排序算法,一般用于对总体无序,但是各子项相对有序的数列。

java代码:

  1. public class Code01_MergeSort {
  2. public static void process(int[] arr, int L, int R){
  3. if (L == R){
  4. return;
  5. }
  6. int mid = L + ((R - L) >> 1);
  7. process(arr, L, mid);
  8. process(arr, mid+1, R);
  9. merge(arr, L, mid, R);
  10. }
  11. public static void merge(int[] arr, int L, int M, int R){
  12. int[] help = new int[R-L+1];
  13. int i = 0;
  14. int p1 = L;
  15. int p2 = M + 1;
  16. while (p1 <= M && p2 <= R){
  17. help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
  18. }
  19. while (p1 <= M){
  20. help[i++] = arr[p1++];
  21. }
  22. while (p2 <= R){
  23. help[i++] = arr[p2++];
  24. }
  25. for(i = 0; i < help.length; i++){
  26. arr[L+i] = help[i];
  27. }
  28. }
  29. }

JavaScript代码:

  1. function process(arr, L, R){
  2. if(L == R){
  3. return;
  4. }
  5. var mid = L + Math.floor((R-L)/2);
  6. process(arr, L, mid);
  7. process(arr, mid+1, R);
  8. merge(arr, L, mid, R);
  9. }
  10. function merge(arr, L, M, R){
  11. let help = [];
  12. let i = 0;
  13. let p1 = L;
  14. let p2 = M+1;
  15. while(p1 <= M && p2 <= R){
  16. help[i++] = arr[p1] >= arr[p2] ? arr[p1++] : arr[p2++];
  17. }
  18. while(p1 <= M){
  19. help[i++] = arr[p1++];
  20. }
  21. while(p2 <= R){
  22. help[i++] = arr[p2++];
  23. }
  24. for(i = 0; i < help.length; i++){
  25. arr[L+i] = help[i];
  26. }
  27. }

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版本代码:

  1. package class02;
  2. public class Code03_QuickSort {
  3. public static void quickSort(int[] arr){
  4. if(arr == null || arr.length < 2){
  5. return;
  6. }
  7. quickSort(arr, 0, arr.length-1);
  8. }
  9. // arr[l...r]排好序
  10. public static void quickSort(int[] arr, int L, int R){
  11. if(L < R) {
  12. swap(arr, L + (Math.random() * (R-L+1), R);
  13. int[] p = partition(arr, L, R);
  14. quickSort(arr, L, p[0]-1);
  15. quickSort(arr, p[1]+1, R);
  16. }
  17. }
  18. // 这是一个处理arr[l...r]的函数
  19. // 默认以arr[r]做划分,arr[r] -> p <p --p >p
  20. // 返回等于区域(左边界,右边界),所以返回一个长度为2的数组res,res[0] res[1]
  21. public static int[] partition(int[] arr, int L, int R){
  22. int less = L - 1;
  23. int more = R;
  24. while(L < more){
  25. if(arr[L] < arr[R]){
  26. swap(arr, ++less, L++);
  27. } else if(arr[L] > arr[R]){
  28. swap(arr, --more, L);
  29. } else{
  30. L++;
  31. }
  32. }
  33. swap(arr, more, R);
  34. return new int[] {less+1, more };
  35. }
  36. public static void swap(int[] arr, int x, int y) {
  37. int temp = arr[x];
  38. arr[x] = arr[y];
  39. arr[y] = temp;
  40. }
  41. }

JavaScript代码:

  1. function quickSort(arr) {
  2. if(arr === null || arr.length < 2){
  3. return;
  4. }
  5. quickSortT(arr, 0, arr.length-1);
  6. return arr;
  7. }
  8. function quickSortT(arr, L, R) {
  9. if(L < R) {
  10. swap(arr, L + Math.floor(Math.random() * (R-L+1)), R);
  11. let p = partition(arr, L, R);
  12. quickSortT(arr, L, p[0] -1); // <区域
  13. quickSortT(arr, p[1]+1, R); // >区域
  14. }
  15. }
  16. function partition(arr, L, R) {
  17. let less = L - 1; // 区左边界
  18. let more = R; // 区右边界
  19. while(L < more){ //表示当前数的位置 arr[R] -> 划分值
  20. if(arr[L] < arr[R]){ // 当前数 < 划分值
  21. swap(arr, ++less, L++);
  22. } else if(arr[L] > arr[R]){ // 当前数 > 划分值
  23. swap(arr, --more, L);
  24. } else{
  25. L++;
  26. }
  27. }
  28. swap(arr, more, R);
  29. return [less+1, more];
  30. }
  31. function swap(arr, x, y) {
  32. let temp = arr[x];
  33. arr[x] = arr[y];
  34. arr[y] = temp;
  35. }