数据结构(Java)-排序算法-快速排序

介绍

        快速排序(Quicksort)是对冒泡排序的一种改进。基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列

代码思路

        我们要先设定一个基准策略,可以是序列的第一个、中间、最后一个数。我觉得选取第一个数作为基准比较容易理解,也容易实现。

        1.首先有一个大前提,左边界 < 右边界,(并非左右指针)如果违反就说明已经排好了 !就可以退出!

        2.每次排序都要定义三个变量:left-左指针right-右指针base-基准值(序列首位

        3.寻找满足条件的两个逆序数,进行交换。细节如下:

                3.1 让 right 左移,遇到小于base的数就停下

                3.2 让 left 右移,遇到大于base的数就停下

                3.3 交换 left、right 指向的数

                        (以上3个步骤有大前提!left < right!不控制的话就越界!会死循环)

                3.4 重复执行 3.1-3.3 的操作,直到 left=right

        4.走到这说明本次排序已经接近尾声了,我们让base指针所指的数交换位置,那么base左右两边的数都是符合条件的了

        5.修改边界,分别递归地对左右两个子列进行快速排序。直到每个子列只有一个数,即左右边界相等。再往下面递归的话就被 1 的条件 return 了

代码演示

 public static Integer[] QuickSort(Integer[] arr,Integer left,Integer right){
        if(left>right) return arr;
        int l=left;
        int r=right;
        Integer base=arr[l];//以序列的首位元素为基准
        //左指针循环右移,右指针循环左移,直到二者相遇就终止
        while(l!=r){
            //右指针左移,直到遇到比基准小的数时停止移动
            while (arr[r]>=base && l<r) r--;
            //左指针右移,直到遇到比基准大的数时停止移动
            while (arr[l]<=base && l<r) l++;
                //交换左右指针所指元素。注意这里面 l<r 的条件都是必须的,因为不能让左右指针越界啊!!,没有这个条件的话就无限执行了...
            if(l<r) {
                Integer temp = arr[l];
                arr[l] = arr[r];
                arr[r] = temp;
            }
            }
        //左右指针相遇时,交换基准元素与指针指向的元素,此时基准元素的左边数都比他小,右边数都比它大
        arr[left]=arr[l];
        arr[l]=base;
        //分别对基准元素的左右子序列执行同样的操作
        QuickSort(arr,left,l-1);
        QuickSort(arr,l+1,right);
        return arr;
    }

测试

 @Test
    public void testSelectSort(){
        Integer[] arr = init();
        System.out.println("原始数据为:");
        print(arr);
        Long beginTime= System.currentTimeMillis();
        Integer[] result = QuickSort(arr,0,arr.length-1);
        Long endTime= System.currentTimeMillis();
        System.out.println("排序结果为:");
        print(result);
        System.out.println("耗时:"+(endTime-beginTime)+" ms");
    }

总结

 快速排序是对冒泡排序的改进,其效率还是挺高的

  1. 明确快排终止条件左边界 < 右边界,即只有一个元素或者没有元素。
  2. 明确指针移动条件:left <= right,即左指针在右指针左边时才能移动,越界会死循环
  3. 明确指针移动顺序:当选取首元素作为基准元素时,先移动的指针一定要是右指针(当选取最右边的元素为基准元素时,先移动的指针一定要是左边的指针)。因为右指针找的是小于基准元素的数,一轮排序的最后要让基准元素、指针所指元素互换,先让右指针移动才能保证互换后的序列满足条件! 

        这是错误的例子:以首元素为基准,先移动左指针,左指针找的是大于基准的数。再移动右指针,左右指针重合。交换元素,显然结果是错的!!

        来源:快速排序指针移动先后顺序问题分析 - .有梦想的咸鱼丶 - 博客园

注:这是一个优化后的代码

public void quickSort(String[] strs,int left,int right){
        if(left>=right) return;
        String base=strs[left];
        int l=left;
        int r=right;
        //与基准元素比较大小,交换左右指针元素
        while(l<r){
            while(strs[r]>strs[left] && l<r) r--;
            while(strs[l]<strs[left] && l<r) l++;
            String tmp = strs[l];
            strs[l] = strs[r];
            strs[r] = tmp;
        }
        //移动基准元素
        strs[left]=strs[l];
        strs[l]=base;
        quickSort(strs,left,l-1);
        quickSort(strs,l+1,right);
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值