利用Java 实现快速排序--hunter学Java


在这里插入图片描述

一.简述快速排序

所谓快速排序,其最大特点就是快,如何能快?当然是时间复杂度与空间复杂度均较小,就会快了。快速排序是一种基于分而治之思想的的排序算法,说到分而治之,是不是很容易想到二分法?它的时间复杂度是log(n),那我们可不可以将一个数组不断进行诸如二分法般的排序?

二.具体讲述

1.基准值

下面我们就来讲一讲具体的思想,首先我们拿到了一个数组,以{5,4,3,9,8,2,3,4,5,8,10}为例,我们需要选定一个标准值,所谓的标准值就是我们要以他为中轴将数列按大小一分为二的元,目的在于完成第一次的“二分”,这里我们将最左边的数记为基准值。

2.数组的第一次变化

那接下来该如何完成第一次二分呢?我们前后各选定一个标记,分别记为i与j。i的使命在于找出比基准值大的数,让比基准值小的数留在左边,j的使命在于找到比基准值小的数,让大的数留在右边。
因为此处设置的基准数是最左边的数,所以需要让j先向右移,这一点非常重要,为何j先移动?大家先思考一下,我后面补充。
j向左移动,目的在于找出比基准值即6小的数,当遇到比5小的数4便停下来,然后i开始向右移动目的在于找到比基准值6大的数,遇到9停下来,然后4和9交换位置,那么此时在i的左边都是比基准值小的数,在j的右边都是比基准值大的数。

3.数组第一轮变化

参照数组的第一次,如此继续,4和8交换,然后j继续左移遇到3停下,然后i开始右移去寻找比基准值大的数,但i<j是我们的前提条件,此时i与j在4处相遇,此时4与5(基准值)交换,完成第一轮.第一轮变化便是核心,接下来便是重复上述操作。

三.具体代码实现

public class QuickSort {
    /*int[] arr;
    int low;
    int high;*/
    public static void QuickSortMini(int[] arr, int low, int high) {
        int i, j, temp,t;
        /*旨在最后就剩一个元素了,此时其内的i == j,下一步进行递归时,出现low>high跳出方法,不然就是死循环
        //将左侧的数据进行递归
        QuickSortMini(arr,low,j-1);
        //对右边的数据进行递归
        QuickSortMini(arr,j+1,high);*/
        if(low>high){
            return;
        }
        i = low;
        j = high;

        temp = arr[low];
        while (i < j) {
            //从右边开始看
            while (arr[j] >= arr[low] && j > i){
                j--;
            }
            //从左边看
            while (arr[i] <= arr[low] && i < j){
                i++;
            }
            if (arr[j] < temp && arr[i] > temp){
                t = arr[j];
                arr[j] = arr[i];
                arr[i] = t;
            }

        }
        //最后将基准值与arr[i]交换
        arr[low] = arr[i];
        arr[i] = temp;
        
        //将左侧的数据进行递归
        //在第二次及以后,较于第一次基准值右边的第二次递归后左边的数组
        // 这里的low就是上一次递归结束后的j+1
        QuickSortMini(arr,low,j-1);
        
        //对右边的数据进行递归
        //在第二次及以后,较于第一次基准值左边边的第二次递归后右边的数组
        // 这里的low就是上一次递归结束后的j-1
        QuickSortMini(arr,j+1,high);
        }
        public static void main(String[] args) {
        int[] arr = new int[]{8,1,2,3,4,5,6,99,88};
        //遍历输出
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+"\t");
        }
        System.out.println();
        //调用函数进行排序
        QuickSortMini(arr,0,arr.length-1);
        //遍历输出
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+"\t");
        }
    }
    }
        

四.补充

为何j先移动?

在前面我抛出一个问题让大家思考,下面来说一下我的看法:
j先移动,最主要的原因在于基准值是选在最左边的。j先移动确保了在j停下来处的值是大于基准值的或者是与i共同停在了比基准值小的数上,因为他停下来的条件要么是找到了比基准值小的数,要么就是和i相遇了,而是j先动,i再动,i比基准值5小的数上或者是与j共同停在了比基准值小的数上,故保证了最后和基准值交换时的数是小于基准值的,即保证了基准值的左边小于他,大于他的数在右边。

五.写在最后题

前面关于快速排序算法的文字描述我就只写到第一轮交换那里,是因为我认为那是关键核心,那里弄明白了,后续就是他的重复。另外,在注释里我特别解释了递归时表达式里的low与high,是因为有一次我在思考的时候误将这个high一直当作初始的high即arr.length来思考,一度让我走进死胡同,low也是如此。
这是我写的第一篇博客,有点生疏,表达上可能有些不恰当的地方,希望各位老师批评指正,如果对你有所帮助,那便是我分享的意义,祝好。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值