快速排序(递归+非递归)-java

本文详细介绍了快速排序的基本原理,通过实例展示了如何划分区间并进行排序。使用递归和非递归两种方式实现快速排序,并提供了相应的Java代码。在排序过程中,先选取基准值,然后通过两个指针从两端寻找,最终达到排序目的。
摘要由CSDN通过智能技术生成

一、原理
1、从待排序区间中选择一个值作为基准值。(通常选择最左侧元素或者最右侧元素)。
2、遍历整个待排序的区间,把比基准值小的元素放在基准值左侧,比基准值大的元素放在右侧。最后整个区间就会划分为三个部分:小于基准值的元素、基准值、大于基准值的元素。
3、再针对左侧整理好的区间和右侧整理好的区间继续进行下一步的操作,重复以上过程即可。

(肯定看了这个文字的解释还是一脸懵,那就用一个例子来看一下整个的排序过程)

二、图解:

需要排序的区间:{6,1,2,7,9,3,4,5,10,8}
基准值:右侧元素-8
蓝色箭头:从左往右,找比基准值大的数字
绿色箭头:从右往左,找比基准值小的数字

第一回合:
在这里插入图片描述
先从左往右,找比基准值大的数字:
在这里插入图片描述
再从右往左,找比基准值小的数字:
在这里插入图片描述
交换两个数字:
在这里插入图片描述
再向右找比基准值大的数字:
在这里插入图片描述
这时,我们就会发现,两个箭头重合了,此时交换重合位置的数字和基准值。
在这里插入图片描述
这个时候我们就会发现,基准值8左侧的元素都比8大,右侧的都小。这样就达到了我们的目的。但是此时排序还没有结束。

我们将8左侧的元素分成一个区间{6,1,2,7,5,3,4},右侧的元素分为另一个区间{8,9}。分别将这两个区间又按照上面的方法进行排序。

第二回合:
2.1:划分{6,1,2,7,5,3,4},此时基准值我设为4
在这里插入图片描述
先从左向后找比基准值大的数字,在从右向左找比基准值小的数字,最后交换位置。
在这里插入图片描述

再继续找,这个时候两个箭头在7的位置相遇了。
在这里插入图片描述
交换相遇位置的元素和基准值:
在这里插入图片描述
这个时候又会分出两个区间{3,1,2} 和 {5,6,7},再继续进行划分。(这里我就不具体的排序了)

2.2划分{8,9},基准值为9
在这里插入图片描述
先从左向右找比基准值大的数字,在从右向左找比基准值小的数字。
在这里插入图片描述
交换重合位置元素和基准值:
在这里插入图片描述
这个区间就排列有序了。
此时第二回合完了之后我们的这一组数字就变成了:
在这里插入图片描述
一直按照这样的方法把{3,1,2}和{5,6,7}进行排序之后进行合并,就会得到一组有序的数字。

这里需要注意的是:如果取最左侧为基准值,就必须先从右向左找,再从左向右找。如果取最右侧为基准值,就必须先从左向后找,再从右向左找。

三、递归实现快速排序:

public static void quickSort(int[] array) {
        quickSortHelper(array,0,array.length-1);//辅助方法
    }

    private static void quickSortHelper(int[] array, int left, int right) {
        if(left >= right) {
            //说明这个区间中有0个或者1个元素
            return;
        }

        int index = partition(array,left,right);//重合位置的下标
        quickSortHelper(array,left,index - 1);//递归实现左区间
        quickSortHelper(array,index + 1,right);//递归实现右区间
    }

    private static int partition(int[] array, int left, int right) {
        int i = left;
        int j = right;
        int base = array[j];
        while (i < j){
            //循环从左向后找到比基准值大的元素
            while (i < j && array[i] <= base) {
                i++;
            }
            
            //代码走到这里,i有可能和j重合,也有可能是找到了比基准值大的元素
            //下面,循环从由向左找比基准值小的元素
            while (i < j && array[j] >= base) {
                j--;
            }
            
            //交换i位置的元素和j位置的元素
            swap(array,i,j);
        }
        //代码跳出循环之后,说明i和j重合了,就需要交换重合位置的元素和基准值。
        swap(array,i,right);
        return i;
    }
    private static void swap(int[] array, int i, int j) {
        int tmp = array[j];
        array[j] = array[i];
        array[i] = tmp;
    }

四、非递归实现快速排序
需要借助栈来模拟递归的一个过程。

public static void quickSortByLoop(int[] array) {
        Stack<Integer> stack = new Stack<>();
        stack.push(array.length - 1);
        stack.push(0);

        while (!stack.isEmpty()) {
            int left = stack.pop();
            int right = stack.pop();

            if(left >= right) {
                continue;
            }

            int index = partition(array,left,right);
            stack.push(right);
            stack.push(index + 1);

            stack.push(index-1);
            stack.push(left);
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值