排序

选择排序

  • 时间复杂度(O(N^2))

在 N个数中 遍历N-1次 找到最小的数字和第一个数字交换
在便利N-2个中找到最小的数字和第二个数字交换
循环往复 直到N个数遍历完成

  1. package algorithm;
  2. import java.util.Arrays;
  3. public class selectSort {
  4. // 选择排序 第i个位置存放第i位序列
  5. public static int tempSize = 20; // 测试多少组数据的长度
  6. public static int tempValue = 30; // 数据的值在哪个范围
  7. public static int tempTime = 100; // 比较多少组数据
  8. public static void selectSort(int[] arr) {
  9. if (arr == null) {
  10. return;
  11. }
  12. for (int i = 0; i < arr.length; i++) { // 循环次数
  13. int minValue = i; // 比较值
  14. for (int j = i + 1; j < arr.length; j++) {
  15. if (arr[minValue] > arr[j]) {
  16. minValue = j;
  17. }
  18. }
  19. swap(arr, i, minValue);
  20. }
  21. }
  22. public static void swap(int[] arr, int i, int j) {
  23. int temp = arr[i];
  24. arr[i] = arr[j];
  25. arr[j] = temp;
  26. }
  27. public static void sort(int[] arr) {
  28. Arrays.sort(arr);
  29. }
  30. public static boolean isEqual(int[] arr, int[] arr2) {
  31. if ((arr == null && arr2 != null) || (arr != null && arr2 == null)) {
  32. return false;
  33. }
  34. if (arr == null) {
  35. return true;
  36. }
  37. if (arr.length != arr2.length) {
  38. return false;
  39. }
  40. for (int i = 0; i < arr.length; i++) {
  41. if (arr[i] != arr2[i]) {
  42. return false;
  43. }
  44. }
  45. return true;
  46. }
  47. public static int[] generator(int size, int value) {
  48. int[] arr = new int[(int) ((Math.random() + 1) * size)];
  49. for (int i = 0; i < size; i++) {
  50. // [-value,value]
  51. arr[i] = ((int) (Math.random() * (value + 1)) - (int) (Math.random() * value));
  52. }
  53. return arr;
  54. }
  55. // 拷贝数组
  56. public static int[] copyArray(int[] array) {
  57. // 引用数据类型 都可以为null
  58. if (array == null) {
  59. return null;
  60. }
  61. int[] tempArray = new int[array.length];
  62. for (int i = 0; i < array.length; i++) {
  63. tempArray[i] = array[i];
  64. }
  65. return tempArray;
  66. }
  67. public static void printf(int[] a, int[] b, int[] c) {
  68. for (int i = 0; i < a.length; i++) {
  69. System.out.println("排序值,sort值,初始值");
  70. System.out.printf("%d,%d,%d", a[i], b[i], c[i]);
  71. System.out.println();
  72. }
  73. }
  74. public static void main(String[] args) {
  75. for (int i = 0; i < tempTime; i++) {
  76. int[] arr = generator(tempSize, tempValue);
  77. int[] arr1 = copyArray(arr);
  78. int[] arr2 = copyArray(arr);
  79. selectSort(arr1);
  80. sort(arr2);
  81. if (!isEqual(arr1, arr2)) {
  82. printf(arr1, arr2, arr);
  83. return;
  84. }
  85. }
  86. System.out.println("ok");
  87. }
  88. }

冒泡排序

  • 时间复杂度O(N^2)

比较两个相邻的数字的结果 判断是否要交换顺序 (一轮下来的时间复杂度是O(N))
以此重复 知道所有排序完成

  1. package algorithm;
  2. import java.util.Arrays;
  3. public class bubblingSort {
  4. // 冒泡排序
  5. public static int tempSize = 20; // 测试多少组数据的长度
  6. public static int tempValue = 10; // 数据的值在哪个范围
  7. public static int tempTime = 50; // 比较多少组数据
  8. // 比较两个相邻的元素,将值大的元素交换到右边
  9. // 时间复杂度O(n^2)
  10. public static void bubblingSort(int[] arr) {
  11. if (arr == null || arr.length < 2) { // 注意边界问题
  12. return;
  13. }
  14. for (int i = 0; i < arr.length - 1; i++) { // 循环次数
  15. // 每次循环都会确定i+1个排序 所以要 arr.length - (i + 1)
  16. // 注意这里的arr.length - i -1
  17. for (int j = 0; j < arr.length - i - 1; j++) {
  18. // 这里的
  19. if (arr[j] > arr[j + 1]) {
  20. swap(arr, j, j + 1);
  21. }
  22. }
  23. }
  24. }
  25. public static void sort(int[] arr) {
  26. Arrays.sort(arr);
  27. }
  28. // 交换顺序
  29. public static void swap(int[] arr, int i, int j) {
  30. int temp = arr[i];
  31. arr[i] = arr[j];
  32. arr[j] = temp;
  33. }
  34. // 生成随机数组
  35. public static int[] generateRandomArray(int size, int value) {
  36. // 生成size长度的数组 并且值在 [0-value - 1] 之间
  37. int[] array = new int[(int) ((Math.random() + 1) * size)];
  38. for (int i = 0; i < array.length; i++) {
  39. array[i] = (int) (Math.random() * value);
  40. }
  41. return array;
  42. }
  43. // 拷贝数组
  44. public static int[] copyArray(int[] array) {
  45. // 引用数据类型 都可以为null
  46. if (array == null) {
  47. return null;
  48. }
  49. int[] tempArray = new int[array.length];
  50. for (int i = 0; i < array.length; i++) {
  51. tempArray[i] = array[i];
  52. }
  53. return tempArray;
  54. }
  55. public static boolean isEqual(int[] arr, int[] rightArray) {
  56. if (arr == null && rightArray != null || arr != null && rightArray == null) {
  57. return false;
  58. }
  59. if (arr == null) {
  60. return true;
  61. }
  62. if (arr.length != rightArray.length) {
  63. return false;
  64. }
  65. for (int i = 0; i < arr.length; i++) {
  66. if (arr[i] != rightArray[i]) {
  67. return false;
  68. }
  69. }
  70. return true;
  71. }
  72. public static void printf(int[] a, int[] b, int[] c) {
  73. for (int i = 0; i < a.length; i++) {
  74. System.out.println("排序值,sort值,初始值");
  75. System.out.printf("%d,%d,%d", a[i], b[i], c[i]);
  76. System.out.println();
  77. }
  78. }
  79. public static void main(String[] args) {
  80. for (int i = 0; i < tempTime; i++) {
  81. int[] arr = generateRandomArray(tempSize, tempValue); // 第一组数据
  82. int[] rightArray = copyArray(arr); // 拷贝一组数组 用于比较
  83. int[] tempArray = copyArray(arr); // 拷贝一组数组 用于比较
  84. bubblingSort(arr);
  85. sort(rightArray);
  86. // 比较是否两个相等
  87. if (!isEqual(arr, rightArray)) {
  88. printf(arr, rightArray, tempArray);
  89. return;
  90. }
  91. }
  92. System.out.println("ok");
  93. }
  94. }

插入排序

  • 时间复杂度O(N^2)

    将第i位的元素插入到前0- (i-1) 中去 ```java package algorithm;

import java.util.Arrays;

public class insertSort { // 插入排序 i>=1 从小到大 // 将第i位的元素插入到前0- (i-1) 中去 public static int tempSize = 20; // 测试多少组数据的长度 public static int tempValue = 100; // 数据的值在哪个范围 public static int tempTime = 1000; // 比较多少组数据

  1. // 时间复杂度O(n^2)
  2. public static void insertSort(int[] arr) {
  3. if (arr == null || arr.length < 2) { // 注意边界问题
  4. return;
  5. }
  6. for (int i = 1; i < arr.length; i++) {
  7. for (int j = 0; j < i; j++) {
  8. if (arr[j] > arr[i]) {
  9. // 往后移动一位
  10. move(arr, j, i);
  11. }
  12. }
  13. }
  14. }
  15. public static void sort(int[] arr) {
  16. Arrays.sort(arr);
  17. }
  18. // 插入 往后位移 从i到j位往后移
  19. public static void move(int[] arr, int i, int j) {
  20. // 数据移动是从 [i,j)
  21. int tampValue = arr[j];
  22. for (int k = j - 1; k >= i; k--) {
  23. arr[k + 1] = arr[k];
  24. }
  25. arr[i] = tampValue;
  26. }
  27. // 生成随机数组
  28. public static int[] generateRandomArray(int size, int value) {
  29. // 生成size长度的数组 并且值在 [0-value - 1] 之间
  30. int[] array = new int[(int) ((Math.random() + 1) * size)];
  31. for (int i = 0; i < array.length; i++) {
  32. array[i] = (int) (Math.random() * value);
  33. }
  34. return array;
  35. }
  36. // 拷贝数组
  37. public static int[] copyArray(int[] array) {
  38. // 引用数据类型 都可以为null
  39. if (array == null) {
  40. return null;
  41. }
  42. int[] tempArray = new int[array.length];
  43. for (int i = 0; i < array.length; i++) {
  44. tempArray[i] = array[i];
  45. }
  46. return tempArray;
  47. }
  48. public static boolean isEqual(int[] arr, int[] rightArray) {
  49. if (arr == null && rightArray != null || arr != null && rightArray == null) {
  50. return false;
  51. }
  52. if (arr == null) {
  53. return true;
  54. }
  55. if (arr.length != rightArray.length) {
  56. return false;
  57. }
  58. for (int i = 0; i < arr.length; i++) {
  59. if (arr[i] != rightArray[i]) {
  60. return false;
  61. }
  62. }
  63. return true;
  64. }
  65. public static void printf(int[] a, int[] b, int[] c) {
  66. for (int i = 0; i < a.length; i++) {
  67. System.out.println("排序值,sort值,初始值");
  68. System.out.printf("%d,%d,%d", a[i], b[i], c[i]);
  69. System.out.println();
  70. }
  71. }
  72. public static void main(String[] args) {
  73. for (int i = 0; i < tempTime; i++) {
  74. int[] arr = generateRandomArray(tempSize, tempValue); // 第一组数据
  75. int[] rightArray = copyArray(arr); // 拷贝一组数组 用于比较
  76. int[] tempArray = copyArray(arr); // 拷贝一组数组 用于比较
  77. insertSort(arr);
  78. sort(rightArray);
  79. // 比较是否两个相等
  80. if (!isEqual(arr, rightArray)) {
  81. printf(arr, rightArray, tempArray);
  82. return;
  83. }
  84. }
  85. System.out.println("ok");
  86. }

}

<a name="W5egR"></a>
# 快速排序
```java
import java.util.Arrays;

public class quickSort {
    /**
     * 快速排序
     * 时间复杂度nlogn
     * @param arr
     * @desc 选择一个基准数,通过一趟排序将要排序的数据分割成独立的两部分;
     * 其中一部分的所有数据都比另外一部分的所有数据都要小。然后,再按此方法对这两部分数据分别进行快速排序,
     * 整个排序过程可以递归进行,以此达到整个数据变成有序序列。
     */
    public static void quickSort(int[] arr) {
        if(arr == null || arr.length < 2) return;
        int pre = 0; //左边界
        int next = arr.length -1; //右边界
        quickSortStack(arr,pre,next);
    }
    public static void quickSortStack(int[] arr,int i, int j) {
        if(i >= j) return;
        int current = arr[i]; //基准值
        // 保存边界值
        int pre = i;
        int next = j;
        while(pre < next) {
            // 如果 next的值比当前的值大 则继续往下查找
            while(pre < next && arr[next] >= current) {
                next--;
            }
            // 这里会走 arr[next] < current 交换顺序
            if(pre < next) {
                arr[pre] = arr[next];
                //之后往pre向上走判断
                pre++;
                // 之后next这个数字就是基准值下标了
            }
            // pre的值比当前基准值小
            while(pre < next && arr[pre] <= current) {
                pre++;
            }
            // arr[pre] > current
            if(pre < next) {
                arr[next] = arr[pre];
                next--;
                // 之后pre这个数字就是基准值下标了
            }
        }
        // 结束后 pre = next 基准值放于中间
        arr[pre] = current;
        quickSortStack(arr,i,pre-1);
        quickSortStack(arr,pre+1,j);
    }
    public static void sort (int[] arr) {
        Arrays.sort(arr);
    }
    public static void swapArray(int[] arr,int a,int b) {
        if(a == b) return;
        arr[a] = arr[a] ^ arr[b];
        arr[b] = arr[a] ^ arr[b];
        arr[a] = arr[a] ^ arr[b];
    }
    public static boolean isEqual(int[] arr, int[] sort) {
        if((arr == null && sort !=null) || (arr != null && sort == null)) {
            return false;
        }
        if(sort == null) {
            return true;
        }
        if(arr.length != sort.length) {
            return false;
        }
        for (int i = 0; i < arr.length; i++) {
            if(arr[i] != sort[i]) {
                return false;
            }
        }
        return true;
    }
    public static int[] tempNumber(int size,int result) {
        int[] arr = new int[size];
        for (int i = 0; i < size; i++) {
            arr[i] = ((int)((Math.random() *result) + 1) - (int)(Math.random() * result));
        }
        return arr;
    }
    public static int[] copyArr(int[] arr) {
        int[] copyArr = new int[arr.length];
        for (int i = 0; i < arr.length; i++) {
            copyArr[i] = arr[i];
        }
        return copyArr;
    }
    public static void systemOut(int[] arr, int[] sortArr, int[] tempArr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.printf("arr:%d,sortArr:%d,tempArr:%d",arr[i],sortArr[i],tempArr[i]);
            System.out.println();
        }
    }
    public static void main(String[] args) {
        int tempSize = 2; //比较次数
        int size = 10;// 数组长度
        int result = 50;
        for (int i = 0; i < tempSize; i++) {
            int[] resultArr = tempNumber(size,result);
            int[] sortArr = copyArr(resultArr);
            int[] tempArr = copyArr(resultArr);
            quickSort(resultArr);
            sort(sortArr);
            if(!isEqual(resultArr,sortArr)) {
                systemOut(resultArr,sortArr, tempArr);
                return;
            }
        }
        System.out.println("ok");
    }
}

二分法

时间复杂度: log2^N (二分不一定要有序)

  • 一个有序数组 查找某个数是否存在
  • 一个有序数组 找>=某个数的最左侧的位置
  • 一个有序数组 找<=某个数的最右侧位置
  • 局部最小值问题(数组可以无序 但是相邻位置的数组不能相等)
    // 二分法 谨记二分法不一定要有序
      public static int dichotomy(int[] arr, int result) {
          int flag = -1;
          if (arr == null) {
              return flag;
          }
          int pre = 0;
          int next = arr.length - 1;
          while (pre < next) {
              int middle = (int) ((pre + next) / 2);
               // 这里的middle 可以优化 pre + next 可能会有长度溢出的风险
              // int middle = (int) pre +((next - pre) >> 1)
              if (arr[middle] > result) {
                  next = middle - 1;
              }
              if (arr[middle] < result) {
                  pre = middle + 1;
              }
              if (arr[middle] == result) {
                  flag = middle;
                  break;
              }
          }
          return flag;
      }