Java:快速排序的基本实现

快速排序基本思想

基于分治,是对冒泡排序的一种改进。

首先选取一个基准点(pivot),为计算简单,暂且选取数组的第一位为基准点,并将其存储到临时变量中。

事实上,基准点的选取一定程度上影响着快速排序的速率,目前有许多中选取基准点的方案,比如产生随机索引,取前中后的中位数等等。

以该基准点为依据,将数组分为两部分。定义两个指针,其中左指针从左向右扫描,找到比基准大的数,移到右边,右指针从右向左扫描,找到比基准小的数,移到左边。循环往复之后,最终high指针指向的位置即为pivot应该存在的位置,可得到pivot的索引。

在这里插入图片描述

代码实现

    //用户接口
    public static void quickSort(int[] arr){
        quickSort(arr,0,arr.length-1);
    }
    //快速排序,分而治之
    private static void quickSort(int[] arr, int start, int end) {
        if(end>start){
            //通过partition方法获取pivot的位置
            int pivotIndex = partition(arr,start,end);
            quickSort(arr,start, pivotIndex);
            quickSort(arr,pivotIndex+1,end);
        }
    }
    //排序,并返回pivot的正确位置
    private static int partition(int[] arr, int low, int high) {
        // 取第一位为基准
        int pivot = arr[low];
        while (low < high) {
            // 从后往前找到比pivot小(相等的情况忽略)的元素位置
            while (low < high && arr[high] >= pivot) {
                high--;
            }
            // 将这个位置移到左边low阵营
            arr[low] = arr[high];
            // 从前向后找到比pivot大(相等的情况忽略)的元素
            while (low < high && arr[low] <= pivot) {
                low++;
            }
            // 将这个位置移到右边high阵营
            arr[high] = arr[low];

        }
        // low==high相等,跳出循环 此时将pivot插入属于他的位置
        arr[low] = pivot;
        // 返回pivot的位置
        return low;
    }

时间复杂度

最坏的情况下:基准元素每次选的都是最小的,那么将会把数组划分为一个空数组和一个n-1长的大数组,最终的复杂度:(n-1)+(n-2)+……+2+1 = O(n^2),是让人难以接受的,因此基准点的选取很重要。

最好的情况下:基准元素每次都选的很好,都正好将数组划分为规模大致相等的两个部分。T(n) = T(n/2)+T(n/2)

+n。与归并排序类似,时间复杂度为O(nlogn)

可以发现,在最坏的情况下,归并排序的效率要比快速排序优秀,但平均情况下两者效率相似,但快速排序不需要额外的数组空间用于归并,在空间效率上优于归并排序

快速排序的问题

可以发现,每一次的分,基准元素都将直接插入到自己的位置,这一点不同于插入排序。这也是快速排序快的地方。

使用递归,将会额外占用系统堆栈的空间。对于小规模的数据,可能不如插入排序。

当递归的数据规模充分小的时候,应该停止递归,直接调用简单排序。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值