排序算法(4)--冒泡排序与快速排序

1 冒泡排序

冒泡排序的基本思想就是两两进行比较, 也就是相邻的两个元素进行比较, 每次一个外循环都可以确定一个最大值, 并将这个最大值放在无序序列的最后面, 持续这个过程, 直到整个序列有序.
详细执行过程如下:
在这里插入图片描述
代码如下:

public static void bubbleSort(int[] arr) {
        for (int i = 0; i < arr.length-1; i++) {
            boolean flag = false;
            for (int j = 0; j < arr.length-1-i; j++) {
                if (arr[j] > arr[j+1]) {
                    int tmp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = tmp;
                    flag = true;
                }
            }
            if (flag == false) {
                break;
            }
        }
    }
    public static void main(String[] args) {
        int[] arr = {3,2,5,7,1,6,8,9,4};
        System.out.println(Arrays.toString(arr));
        bubbleSort(arr);
        System.out.println(Arrays.toString(arr));
    }
}

运行结果:
在这里插入图片描述
性能分析: 这里需要注意一下: 如果序列是优化过的, 也就是有序的, 其时间复杂度可能是 O(n).
在这里插入图片描述

2 快速排序

快速排序的基本思想如下:

  • 从待排序列中选择一个数, 作为基准值(pivot);

关于基准值的选择主要有三种方式:
1) 选择边上的数字, 例如我们经常会选择序列的首位数字作为基准值;
2) 随机选择;
3) 三位数中, 也就是arr[start], arr[mid], arr[end] 这三个数中选择中间大的数字, 下面的代码我们就是用的这种方式.

  • 遍历整个待排序列, 将比基准值小的放在基准值的左边, 将比基准值大的或者相等的放在基准值的右边, 如下图所示;
  • 采用分治的思想, 对基准值左右两个区间按照以上顺序处理, 直到小区间的长度等于 1 的时候, 代表已经有序.
    在这里插入图片描述

关于快速排序这里主要介绍两种方法, 一种是递归遍历的方式, 另一种是非递归遍历的方式.

2.1 递归实现

详细过程如下:
在这里插入图片描述
代码如下:

public class SwapSort {
    public static int partition(int[] arr, int low, int high) {
        int tmp = arr[low];
        while (low < high) {
            while (low < high && arr[high] >= tmp) {
                high--;
            }
            arr[low] = arr[high];
            while (low < high && arr[low] <= tmp) {
                low++;
            }
            arr[high] = arr[low];
        }
        arr[high] = tmp;
        return low;
    }
    public static void swap(int[] arr, int i, int j) {
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
    public static void selectPivotMedianOfThree(int[] arr, int start, int end, int mid) {
        while (true) {
            if (arr[mid] > arr[start]) {
                swap(arr, start, mid);
                continue;
            }
            if (arr[start] > arr[end]) {
                swap(arr, start, end);
                continue;
            }
            if (arr[mid] > arr[end]) {
                swap(arr, start, end);
                continue;
            }
            break;
        }
    }
    
    public static void quick(int[] arr, int start, int end) {
        if (start >= end) {
            return;
        }
        int mid = (start+end)/2;
        selectPivotMedianOfThree(arr, start, end, mid);
        int pivot = partition(arr, start, end);
        quick(arr, start, pivot-1);
        quick(arr, pivot+1, end);
    }
    public static void quickSort(int[] arr) {
        quick(arr, 0, arr.length-1);
    }
    
    public static void main(String[] args) {
        int[] arr = {3,2,5,7,1,6,8,9,4};
        System.out.println(Arrays.toString(arr));
        quickSort(arr);
        System.out.println(Arrays.toString(arr));
    }
}

运行结果:
在这里插入图片描述
性能分析:
在这里插入图片描述

2.2 非递归实现

非递归的实现需要用到栈, 详细过程如下:
在这里插入图片描述
代码如下:

public class SwapSort {
    public static int partition(int[] arr, int low, int high) {
        int tmp = arr[low];
        while (low < high) {
            while (low < high && arr[high] >= tmp) {
                high--;
            }
            arr[low] = arr[high];
            while (low < high && arr[low] <= tmp) {
                low++;
            }
            arr[high] = arr[low];
        }
        arr[high] = tmp;
        return low;
    }

    public static void quickSort2(int[] arr) {
        Stack<Integer> stack = new Stack<>();
        int start = 0;
        int end = arr.length - 1;
        int pivot = partition(arr, start, end);
        // 左边有两个元素及以上
        if (pivot > start + 1) {
            stack.push(0);
            stack.push(pivot - 1);
        }
        if (pivot < end - 1) {
            stack.push(pivot + 1);
            stack.push(end);
        }
        while (!stack.empty()) {
            end = stack.pop();
            start = stack.pop();
            pivot = partition(arr, start, end);
            // 左边有两个元素及以上
            if(pivot > start+1) {
                stack.push(0);
                stack.push(pivot-1);
            }
            if(pivot < end-1) {
                stack.push(pivot+1);
                stack.push(end);
            }
        }
    }

    public static void main(String[] args) {
        int[] arr = {3,2,5,7,1,6,8,9,4};
        System.out.println(Arrays.toString(arr));
        quickSort2(arr);
        System.out.println(Arrays.toString(arr));
    }
}

运行结果:
在这里插入图片描述


版权声明:本文为Onion_521257原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。