快速排序(自己版本)

快排,面试最喜欢问的排序算法。这是运用分治法的一种排序算法。

快速排序,说白了就是给基准数据找其正确索引位置的过程.

快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)。

原理:

如下图所示,假设最开始的基准数据为数组第一个元素23,则首先用一个临时变量去存储基准数据,即tmp=23;然后分别从数组的两端扫描数组,设两个指示标志:i指向起始位置,j指向末尾.

首先从后半部分开始,如果扫描到的值大于基准数据就让j减1,如果发现有元素比该基准数据的值小(如上图中18<=tmp),找到j的位置,

然后从前半部分开始,如果扫描到的值小于基准数据就让i加1,如果发现有元素大于基准数据的值(如下图46=>tmp),记录i的位置,

找到i与j之后进行一个交换

j指针迁移

然后再开始从前往后遍历,直到i=j结束循环,此时i或j的下标就是基准数据23在该数组中的正确索引位置.如下图所示.

基准与正确位置交换

这样一遍走下来,可以很清楚的知道,其实快速排序的本质就是把基准数大的都放在基准数的右边,把比基准数小的放在基准数的左边,这样就找到了该数据在数组中的正确位置.
  以后采用递归的方式分别对前半部分和后半部分排序,当前半部分和后半部分均有序时该数组就自然有序了

利用了递归,空间换时间,8w数据0.021s

    private static void quickSort(int[] arr, int low, int high) {
        if (low < high) {
            // 找寻基准数据的正确索引
            int index = getIndex(arr, low, high);
            // 进行迭代对index之前和之后的数组进行相同的操作使整个数组变成有序
            quickSort(arr, low, index - 1);
            quickSort(arr, index + 1, high);
        }
    }

    /**
     * 找基准最重要的方法,采用的策略是使数组第一个元素作为基准,i与j分别指向首和尾,
     * i 与 j 移动 ,互相交换
     * 到最后i == j 的时候,将基准与i交换。
     * 当时想弄一个动图演示的,但我debug是一样的呀!
     */
    private static int getIndex(int[] arr, int low, int high) {
        int i = low;
        int j = high;
        // 基准数据
        int tmp = arr[low];
        while (i < j) {
            // 当队尾的元素大于等于基准数据时,向前挪动j指针
            while (i < j && arr[j] >= tmp) {
                j--;
            }
            // 当队首元素小于等于tmp时,向前挪动i指针
            while (i < j && arr[i] <= tmp) {
                i++;
            }
            // 上面二个while循环结束,因为分别碰到了比基准小 与 碰到了比基准大的元素。
            // 然后进行一个交换。
            // 这里可以不用判断 i 是否小于j  如果i==j 再交换,交换的内容都是一样的,增加了if语句可能会造成更多的时间。
            swap(arr,i,j);
        }
        // 跳出循环时i和j相等,此时的i或j就是tmp的正确索引位置
        // 由原理部分可以很清楚的知道low位置的值并不是tmp,需要互相交换pivot(第一个元素) 和 应该去的地方
        swap(arr,low,i);
        return i; // 返回tmp的正确位置
    }
    // 抽取交换方法
    public static void swap(int[]arr,int i,int j){
        int t = arr[i];
        arr[i] = arr[j];
        arr[j] = t;
    }

有参考https://blog.csdn.net/nrsc272420199/article/details/82587933的作图

  • 代码https://blog.csdn.net/Websphere_zxf/article/details/109013001
posted @ 2021-09-21 23:09  能借我十块钱吗  阅读(22)  评论(0编辑  收藏  举报