【排序算法】冒泡排序、选择排序、快速排序、归并排序

Java资深小白,不足之处,或者有任何错误欢迎指出。	--蓝紫

冒泡排序(Bubble Sort)

算法描述:

  1. 比较相邻的元素。如果第一个比第二个大,就交换它们两个;
  2. 对每一个相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
  3. 针对所有的元素重复以上的步骤,除了最后一个;
  4. 重复步骤1~3,直到排序完成。
排序方法时间复杂度(平均)时间复杂度(最坏)时间复杂度(最好)空间复杂度稳定性
冒泡排序O(n²)O(n²)O(n)O(1)稳定
  • 如果两个元素相等,不会再交换位置,所以冒泡排序是一种稳定的排序算法。

代码实现:

  public static void bubbleSort(int[] data) {
        int arrayLength = data.length;
        // 第 i 次排序
        for (int i = 1; i < arrayLength; i++) {
            // 从索引为 j 的数开始
            for (int j = 0; j < arrayLength - i; j++) {
                // 相邻元素两两对比
                if (data[j] > data[j + 1]) {
                    // 元素交换
                    int temp = data[j + 1];
                    data[j + 1] = data[j];
                    data[j] = temp;
                }
            }
            System.out.println("第" + i + "次排序:\n" + java.util.Arrays.toString(data));
        }
    }

    public static void main(String[] args) {
    
        int[] data = { 3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 };
        
        System.out.println("排序之前:\n" + java.util.Arrays.toString(data));
        
        bubbleSort(data);
        
        System.out.println("排序之后:\n" + java.util.Arrays.toString(data));
    }

选择排序(Select Sort)

算法描述:

  1. 对于给定的一组记录,经过第一轮比较后得到最小的记录,然后将该记录与第一个记录的位置进行交换;
  2. 对不包括第一个记录以外的其他记录进行第二轮比较,得到最小的记录与第二个记录进行位置交换;
  3. 重复该过程,直到进行比较的记录只有一个时为止。
排序方法时间复杂度(平均)时间复杂度(最坏)时间复杂度(最好)空间复杂度稳定性
选择排序O(n²)O(n²)O(n²)O(1)不稳定

代码实现:

  /**
     * 选择排序方式一
     * 
     * @param a
     */
    public static void selectSort(int[] a) {
        int length = a.length;
        // 最后一个元素无需和自己比较
        for (int i = 0; i < length - 1; i++) {
            for (int j = i + 1; j < length; j++) {
                if (a[i] > a[j]) {
                    int temp = a[j];
                    a[j] = a[i];
                    a[i] = temp;
                }
            }
        }
    }

    /**
     * 方式二:先找出最小的元素下标
     * 
     * @param a
     */
    public static void selectSort2(int[] a) {
        int length = a.length;
        for (int i = 0; i < length - 1; i++) {
            // 最小元素下标
            int min = i;
            // 找出最小值的下标
            for (int j = i + 1; j < length; j++) {
                if (a[j] < a[min]) {
                    min = j;
                }
            }
            // 将最小值放到未排序记录的第一个位置
            if (min > i) {
                int temp = a[i];
                a[i] = a[min];
                a[min] = temp;
            }
        }
    }

    public static void main(String[] args) {
    
        int[] data = { 3, 44, 38, 5, 43, 15, 34, 26, 27, 2, 46, 4, 19, 50, 48 };
        
        System.out.println("排序之前:\n" + java.util.Arrays.toString(data));
        
        selectSort(data);
        
        System.out.println("排序之后:\n" + java.util.Arrays.toString(data));
    }

快速排序(Quick Sort)

算法描述:

  • 使用分治法来把一个串(list)分为两个子串(sub-lists)。具体描述如下:
  1. 从数列中跳出一个元素,称为“基准”(pivot);
  2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
  3. 递归地(recursive)把小于基准元素的子数列和大于基准值元素的子数列排序。
排序方法时间复杂度(平均)时间复杂度(最坏)时间复杂度(最好)空间复杂度稳定性
快速排序O(n l o g 2 n log_2n log2n)O(n²)O(n l o g 2 n log_2n log2n)O(n l o g 2 n log_2n log2n)不稳定
  • key值的选取可以有多种形式,例如中间数或者随机数,分别会对算法的复杂度产生不同的影响。

代码实现:

 public static void quickSort(int[] data, int low, int high) {
        int i, j, temp, t;
        if (low > high) {
            return;
        }
        i = low;
        j = high;
        // temp 就是基准位
        temp = data[low];
        System.out.println("基准位:" + temp);
        while (i < j) {
            // 先看右边,依次往左递减
            while (temp <= data[j] && i < j) {
                j--;
            }
            // 再看左边,依次往右递增
            while (temp >= data[i] && i < j) {
                i++;
            }
            // 如果满足条件则交换
            if (i < j) {
                System.out.println("交换:" + data[i] + "和" + data[j]);
                t = data[j];
                data[j] = data[i];
                data[i] = t;
                System.out.println(Arrays.toString(data));

            }
        }
        // 最后将基准位与 i 和 j 相等位置的数字交换
        System.out.println("基准位" + temp + "和 i、j 相遇的位置" + data[i] + "交换");
        data[low] = data[i];
        data[i] = temp;
        System.out.println(Arrays.toString(data));
        // 递归调用左半数组
        quickSort(data, low, j - 1);
        // 递归调用右半数组
        quickSort(data, j + 1, high);
    }
     public static void main(String[] args) {
     
        int[] data = { 3, 36, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 };
        
        System.out.println("排序之前:\n" + Arrays.toString(data));
        
        quickSort(data, 0, data.length - 1);
        
        System.out.println("排序之后:\n" + java.util.Arrays.toString(data));
    }

归并排序(Merge Sort)

算法描述:

  1. 把长度为n的输入列序分为两个长度为n/2的子序列;
  2. 对这两个子序列采用归并排序;
  3. 将两个排序好的子序列合并成为一个最终的排序序列。
排序方法时间复杂度(平均)时间复杂度(最坏)时间复杂度(最好)空间复杂度稳定性
归并排序O(n l o g 2 n log_2n log2n)O(n l o g 2 n log_2n log2n)O(n l o g 2 n log_2n log2n)O(n)稳定

代码实现:

   public static void mergeSort(int[] arr) {
        sort(arr, 0, arr.length - 1);
    }

    public static void sort(int[] arr, int L, int R) {
        if (L == R) {
            return;
        }
        int mid = L + ((R - L) >> 1);
        sort(arr, L, mid);
        sort(arr, mid + 1, R);
        merge(arr, L, mid, R);
    }

    public static void merge(int[] arr, int L, int mid, int R) {
        int[] temp = new int[R - L + 1];
        int i = 0;
        int p1 = L;
        int p2 = mid + 1;
        // 比较左右两部分的元素,哪个小,把那个元素填入temp中
        while (p1 <= mid && p2 <= R) {
            temp[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
        }
        // 上面的循环退出后,把剩余的元素依次填入到temp中
        // 以下两个while只有一个会执行
        while (p1 <= mid) {
            temp[i++] = arr[p1++];
        }
        while (p2 <= R) {
            temp[i++] = arr[p2++];
        }
        // 把最终的排序的结果复制给原数组
        for (i = 0; i < temp.length; i++) {
            arr[L + i] = temp[i];
        }
    }

    public static void main(String[] args) {

        int[] data = { 3, 44, 38, 5, 43, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48 };

        System.out.println("排序之前:\n" + java.util.Arrays.toString(data));

        mergeSort(data);

        System.out.println("排序之后:\n" + java.util.Arrays.toString(data));
    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值