初级排序算法

初级排序算法

首先介绍两个概念:

  • 内部排序:排序工作能在内存中完成
  • 外部排序:数据量太大,不能在内存中完成而需要在磁盘上完成的排序

选择排序

  1. 找到数组中最小的元素
  2. 将它和数组的第一个元素交换位置(如果第一个就是最小的,那么它就和自己交换)
  3. 在剩下的元素中找到最小的元素,将它与数组第二个元素交换位置
  4. 重复以上步骤,直到整个数组排序完成.

特点:

  • 运行时间与输入无关

  • 数据移动是最少的

  • 时间复杂度:O(n2)

  • 空间复杂度:O(1)

    /**
     * 选择排序
     * 
     * @param array 目标数组
     */
    private static int[] selectSort(int[] array) {
        for (int i = 0; i < array.length - 1; i++) {
            for (int j = i + 1; j < array.length; j++) {
                int min = i;
                if (array[j] < array[min]) {
                    // 记录目前能找到的最小值元素的下标
                    min = j;
                }
            }
            if (i != min) {
                int tmp = array[i];
                array[i] = array[min];
                array[min] = tmp;
            }
        }
        System.out.println(Arrays.toString(array));
        return array;
    }

冒泡排序

  1. 比较相邻的元素.如果第一个比第二个大,就交换它们两个.
  2. 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对.这步做完后,最后的元素会是最大的.
  3. 针对所有元素重复以上步骤,除了最后一个
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较

特点:

  • 运行时间与输入无关

  • 时间复杂度:O(n2)

  • 空间复杂度:O(1)

    private static int[] bubbleSort(int[] array) {
        boolean notChange = false;
        for (int i = 1; i < array.length; i++) {
            for (int j = 0; j < array.length - i; j++) {
                if (array[j] > array[j + 1]) {
                    int flag = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = flag;
                } else {
                    notChange = true;
                }
            }
            if (!notChange)
                break;
        }
        System.out.println(Arrays.toString(array));
        return array;
    }

插入排序

  1. 从第一个元素开始,将该元素认为是已经排序过的元素
  2. 取出下一个元素为新元素,在已经排序的元素队列中 从后向前扫描
  3. 如果该元素(已排序)大于新元素,将该元素移到下一位置
  4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
  5. 将新元素插入到该位置后
  6. 重复2-5

插入排序所需要的时间,取决于输入元素的初始顺序 , 例如对一个很大且元素已经有序的数组,将会比随机顺序的数组要快的多.

何时选择插入排序

  • 数组中的每个元素距离它的最终位置都不远
  • 一个有序的大数组接一个小数组
  • 数组中只有几个元素的位置不正确

即 部分有序数组 可以选择插入排序

    private static int[] insertSort(int[] array) {
        for (int i = 1; i < array.length; i++) {
            // 记录要插入的数据
            int tmp = array[i];
            int j = i;
            while (j > 0 && tmp < array[j - 1]) {
                array[j] = array[j - 1];
                j--;
            }
            if (j != i) {
                array[j] = tmp;
            }
        }
        System.out.println(Arrays.toString(array));
        return array;
    }

快速排序

  1. 从数组中挑选一个元素,称为基准值(pivot)
  2. 重新排列数组: 所有比基准值小的元素放在基准值的前面,比基准值大的元素放在基准值的后面.在这个分割结束之后,该基准值就处于数组的中间位置.这个称为分割操作(partition)
  3. 递归的(recursively)把小于基准值的元素的子数组和大于基准值的元素的子数组排序.
public static int[] quickSort(int arr[], int start, int end) {
        int pivot = arr[start];
        int i = start;
        int j = end;
        while (i < j) {
            while ((i < j) && (arr[j] > pivot)) {
                j--;
            }
            while ((i < j) && (arr[i] < pivot)) {
                i++;
            }
            if ((arr[i] == arr[j]) && (i < j)) {
                i++;
            } else {
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
        if (i - 1 > start) {
            arr = quickSort(arr, start, i - 1);
        }
        if (j + 1 < end) {
            arr = quickSort(arr, j + 1, end);
        }
        return (arr);
    }

最差时间复杂度 : O(n2)

最优时间复杂度: O(nlogn)

平均时间复杂度: O(nlogn)

空间复杂度 : O(log n)

你可能感兴趣的:(算法)