快速排序详解

快速排序:可以对一个数组或者是对数组中的一段进行排序

思想: 选择一个base, 然后通过一顿瞎操作, 使得 当前数组变成 左小,base, 右大(小,大,都是相对于base 来说的)

           然后使用同样的方法将 上一步的左小排成 左小,base, 右大的格式, 将上一步的右大也排成 左小,base, 右大的格式

          这样不断的进行,最终变成了一个有序的数组(从思想中可以发现这个是将大问题不断转换为一个个的小问题,所以可以

          使用递归实现)

实现: 因为上面说了这个可以通过递归实现, 所以我只需要弄清楚一层的 左小,base, 右大的实现即可

          选择数组最左边的数为base,然后生成两个指针left, right,分别指向数组的左边和右边,根据左边指针的作用

          是将左边的数都变成比base 小的数, 所以左边指针left 在移动的时候,发现比base 大的数字的时候,异常出现了

          同理右边指针right的作用是将右边的数字都变成比base 大的数, 所以右边指针right 移动的时候,发现比base 小的

         数字的时候, 异常出现了,那么怎么处理呢? 将left 指向的数字,和right 指向的数字进行相互的交换, 就使得左右两边暂时满足

         开始的愿望, 左小右大,直到两个指针相遇的时候。两个指针相遇了, 那么这个不是之前的异常了,问题出现了,

         两者相遇的时候,这个值为多大,是比base大的,还是小的,怎么处理。还有上面的指针动的先后顺序有没有讲究?

       (下面有解答) 然后使用递归思想进行全部的排序,解决问题。

 

一、递归的最小化问题的终止条件是什么?

       答: 终止条件是: 当left 和 right 一开始就相同的时候, 而不是left < right , 那么就是终止,不需要进行排序了

            即排序的元素为一个或者为空的时候, 则不进行排序了, 返回了。

 

二、第一个为什么选择左边或者是右边作为基底?

      答:是因为这样很方便,就不需要随机的去选择一个数字

 

三、 为什么左边为base, 则右边的指针先动, 右边的为基底时, 则左边的先动

      答: 首先, 明确一点,两个指针相遇的时候,一定是一个指针遇到另外一个指针,即一个指针多走了一步,然后两个相遇了

              所以, 先走的那个指针就会与后走的那个指针进行相遇了(在两个元素的时候,这个句话有问题, 所以成立的条件时候大于

            三个元素的时候)因为,左base 时候,右边的指针与右边指针相遇的时候, 右边指针对应的值一定是小于base的,即两者相遇

              的指针所对应的值是小于base的, 所以直接可以交换base和交点位置的元素 满足左小, base , 右大的格局

             同理: 右边为base 的时候, 左边的指针开始进行移动,所以最终两个指针相遇的地方对应的数字一定是大于base的, 所以

            可以直接交换base 和交点上数值, 满足 左小, base, 右大的原则。

 

总结: 快速排序的口诀,一选底二动指针分先后左基底右先行右基底左先行指针相遇换基底问题化小转递归终止条件0,1 (个)数

        

class  QuickSourt {
    public static void main(String []args) {

        int[] arr = {2,4,7,9,2,4,6,79,1,23,45,23,7,23};
        System.out.println("hello");
        qucikSort(arr, 0, arr.length-1);
        System.out.println("hello");
        for(int i = 0; i < arr.length; i ++){
            System.out.println(arr[i] +" ");
        }
    }

    public static void qucikSort(int[] arr, int left, int right){
        // 递归的终止条件
        if(left  >  right){
            return;  
        }
int base = arr[left]; // 设置基底 int i = left; int j = right; while(i != j){ // 直到找到一个 比 base 小的数字 while(arr[j] >= base && i < j){ // 这边这个限制条件还是不错的 j--; } // 直到找到一个比 base 大的数字 while(arr[i] <= base && i < j){ i ++; } int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } arr[left] = arr[i]; arr[i] = base; // 然后使用递归再不断的自己排自己的左边和右边的 qucikSort(arr, left, i - 1); qucikSort(arr, i + 1, right); } }

 

posted on 2019-11-05 09:24  黄山一叶  阅读(1169)  评论(0编辑  收藏  举报