JAVA基本算法详细图解---快速排序

快速排序思路

以排序数组int numbers = {4,8,2,3,8,9,5,2,3,6,5,8,7,3,6} 为例

整体思路:

典型的分治思想

1、分解

     以数组的第一个元素为基准进行排序,大于基准元素的 放在右边,小于基准元素的放在左边,这样就将数组分成了三部分

  •  左边数组(小于等于基准数组)
  • 基准元素本身
  • 右边数组(大于等于基准数组)

2、递归求解

  • 分别在第一步基础上 递归地对左边数组以及右边数组排序

3、合并

  •  就是将数组合并,由于第一步的所有左边的数组元素 <= 基准元素 <=右边数组,所以不需要进行任何额外的计算数组元素,合并后的数组就是有序的。

快速排序与归并排序的不同点也在此处:

快速排序的排序操作发生在第一步分解时;

归并排序的排序操作发生在第三部合并时;关于归并排序大家可以看看之前的文章。

上面是整体的思路,我们也可以感受到上述三个步骤最困难的就是第一步,我们如何将数组划分为三份,这个比较不好理解,下面我用图的方式来叙述:

下面请看详细的图解:

导出个excel还给我弄个"非会员水印",我穷我忍了。。。

下面咱们撸一下代码

  
      /**
     * 快排  递归写法
     * @param arr 排序数组
     * @param left 起始脚标
     * @param right 结束脚标
     * @return 结果
     */
    public static int[] quickSort(int[] arr,int left,int right){
        
        if(left < right){
            //第一步 分解
            int mid = partition(arr,left,right);
            //第二步 递归求解
            quickSort(arr,left,mid-1);
            quickSort(arr,mid+1,right);
            //第三步  不需要合并 因为数组本身已经有序
        }
        return arr;
    }
    
    /**
     * 分解 将数组 分为三份  对应上图中的步骤
     */
    public static int partition(int[] arr,int left,int right){
        
        int i = left;
        int j = right+1;
        
        //选出一个基准值
        int mid = arr[left];
        while (true){
            //从右向左 找寻比mid小的位置
            while (mid < arr[--j] && j >= left );
            //从左向右找到比mid大的位置
            while (mid > arr[++i] && i < right );
            if(i >= j){
                break;
            }
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
        arr[left] = arr[j];
        arr[j] = mid;
        return j;
    }

时间复杂度    T(n) = O(nlogn)。

就地快速排序使用的空间是  O(1)  的 ,是在原数组中排序

而真正消耗空间的就是递归调用了,因为每次递归就要保持一些数据;

     最优的情况下空间复杂度为:O(logn)  ;每一次都平分数组的情况

     最差的情况下空间复杂度为:O( n )      ;退化为冒泡排序的情况

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章