快速排序算法递归和非递归的思路以及java实现

本文详细介绍了快速排序的基本思想和实现方式,包括递归和非递归两种实现。快速排序是一种高效的排序算法,由C.A.R.Hoare在1962年提出,基于分治法原理。文章通过代码示例解析了如何通过‘挖坑填数’和‘分治法’将数据分为小于和大于基准值的两部分,并递归地对这两部分进行排序,最终实现整个序列的排序。此外,还提供了非递归实现的思路,利用栈模拟递归过程。
摘要由CSDN通过智能技术生成
基本思想

快速排序(QuickSort)是对冒泡排序的一种改进。快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:

1.从要排序的数据中取一个数为“基准数”。
2.通过一趟排序将要排序的数据分割成独立的两部分,其中左边的数据都比“基准数”小,右边的数据都比“基准数”大。
3.然后再按步骤2对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

该思想可以概括为:挖坑填数 + 分治法。

分治法

分治,字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。在计算机科学中,分治法就是运用分治思想的一种很重要的算法。分治法是很多高效算法的基础,如快速排序,归并排序,傅立叶变换(快速傅立叶变换)等等

可能大家看到这里还是不太懂,没关系,对照着下边代码以及注释看就很清楚了


快速排序递归实现

递归体

public static void QuickSort(int []array,int left,int right){
        if(left > right)return;
        int index = getindex(array,left,right);
        //根据基准值把数组分为左右两个区间。
        // 其中左区间全部小于基准值,右区间全部大于基准值
        // 递归处理左右区间
        QuickSort(array, left, index - 1);
        QuickSort(array, index + 1, right);
    }

获取基准值代码

public static int getindex(int []array,int left,int right){
        int begin = left;
        int end = right;
        int index = array[right]; //取基准值为最右侧。
        while (begin < end){
            // 然后从左开始找,找到一个数大于基准值停止。
            while (begin < end && array[begin] <= index){
                begin++;
            }
            //然后从右继续找,找到小于基准值停止,交换他们位置。
            // 如果左右指针不重合,也就是begin<end,继续循环。
            while (begin < end && array[end] >= index){
                end--;
            }
            //如果循环结束,也就是左右指针重合,此时重合位置一定大于基准值。
            //证明:1.如果因为begin++导致和end重合。因为重合之前begin最后一次循环是找到了一个大于基准值的数,交换给了end,array[end]一定大于基准值,而begin和其重合。则说明重合位置在end处,也是大于基准值的
            //2.如果end—-导致和begin重合。由于能运行到end—-,说明上边begin++循环停止。也就是begin找到了一个比基准值大的数,停止了循环。此时end和begin重合,说明该位置为array[begin]一定比基准值大
            swap(array,begin,end);
        }
        // 将重合的位置元素和基准值元素交换,然后return重合位置的下标,作为下一步划分左右区间的基准元素
        swap(array,begin,right);
        return begin;
    }

交换函数(标准三连)

    public static void swap(int []array,int a,int b){
        int tem = array[a];
        array[a] = array[b];
        array[b] = tem;
    }

快速排序非递归实现

采用非递归的方法,首先要想到栈的使用,通过阅读递归调用部分的代码,思考如何用栈来代替。
递归调用的核心代码是 getindex(array, left, right);
每次循环都必须包含这句核心代码,可以想到,如果要对该行代码实现循环,只能对left和right采取操作,所以我们在栈中压入left和right,每个循环弹出一对left和right,用于模拟递归核心代码的实现,
当栈空后就说明没有需要排序的部分了,结束循环

具体代码如下:

    public static void QuickSort2(int []array){
        //stack 存下标。
        Stack<Integer> stack = new Stack<>();
        //初始操作,边界入stack 的顺序和pop的顺序相反。
        stack.push(array.length-1);
        stack.push(0);
        while (!stack.isEmpty()) {
            //弹出左边界和右边界。
            int left = stack.pop();
            int right = stack.pop();
            //如果left>=rigth,说明栈里只有一个元素,则排序完成。
            if(left>=right)continue;
            //使用上边递归时定义的getindex(array,left,right),获取到基准值,将数组分为:左区间-元素全部小于基准值。右区间-元素全部大于基准值
            int index = getindex(array,left,right);
            //栈push左右区间的边界,继续处理
            // [index+1,right]为右区间
            stack.push(right);
            stack.push(index+1);
            //[left,right-1]为左区间
            stack.push(index-1);
            stack.push(left);
        }
    }

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值