排序方式(8种)详解6—快速排序

目录

1、快速排序概述

原理:

图示:

时间和空间复杂度:

2、快速排序分类

快速排序(递归版)、

快速排序(递归优化版):(筛选更好的基准数,较短区间采用插入排序)

3、代码实现及运行结果

main函数:

快速排序(递归版)

快速排序(递归优化版)

留言:为作者一人拙见,仅参考使用,如有帮助,不甚荣幸。


1、快速排序概述

      快速排序是对冒泡排序算法的一种改进。冒泡排序每次只能交换相邻的两个元素,而快速排序是跳跃式的交换,交换的距离很大,因此总的比较和交换次数少了很多,速度也快了不少。  由 C.A.R.Hoare(Charles Antony Richard Hoare,东尼·霍尔)在 1962 年提出。

      快速排序是一个不稳定的算法,在经过排序之后,可能会对相同值的元素的相对位置造成改变。快速排序基本上被认为是相同数量级的所有排序算法中,平均性能最好的。

原理:

快速排序算法通过多次比较和交换来实现排序,其排序流程如下: 

(1)首先设定一个分界值,通过该分界值将数组分成左右两部分。 

(2)将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于分界值,而右边部分中各元素都大于或等于分界值。 

(3)然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。 

(4)重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。

图示:

在这里插入图片描述

 

时间和空间复杂度:

平均时间复杂度:O(nlogn)

空间复杂度:O(nlogn)

2、快速排序分类

快速排序(递归版)、

快速排序(递归优化版):(筛选更好的基准数,较短区间采用插入排序)

3、代码实现及运行结果

main函数:

public static void main(String[] args) {
        long  starttime1=System.nanoTime();
        System.out.println("快速排序(递归版)");
        int[] nums1=new int[]{77,33,45,55,90,30,67,3,1,2,3,4,5,6,68,98,99,76,65,66,33,43,32,43};
        quicksort(nums1,0,nums1.length);
        for (int m = 0; m < nums1.length ; m++){
            System.out.print(nums1[m]+",");
        }
        System.out.println();
        long endtime1=System.nanoTime();//200ns
        System.out.println("程序运行时间:"+(endtime1-starttime1)+"ns");

        long  starttime2=System.nanoTime();
        System.out.println("快速排序(递归优化版)");
        int[] nums2=new int[]{77,33,45,55,90,30,67,3,1,2,3,4,5,6,68,98,99,76,65,66,33,43,32,43};
        quicksort1(nums2,0,nums2.length);
        for (int m = 0; m < nums2.length ; m++){
            System.out.print(nums2[m]+",");
        }
        System.out.println();
        long endtime2=System.nanoTime();//200ns
        System.out.println("程序运行时间:"+(endtime2-starttime2)+"ns");
    }

快速排序(递归版)

代码:

public static void  quicksort(int[] num ,int start,int end) {
        if ((end-start)<2)return;
        //挖坑填数法
        int temp=num[start];
        int left=start;//左标
        int right=end-1;//右标
        int c=0;//标识方便左右交换填坑
        while (left<right){
            if (c==0) {
                if(num[right]>=temp){right--;continue;}
                num[left]=num[right];
                left++;
                c=1;
                continue;
            }
            if (c==1) {
                if (num[left]<temp){left++;continue;}
                num[right]=num[left];
                right--;
                c=0;
                continue;
            }

        }
        num[left]=temp;
        quicksort(num,0,left);
        quicksort(num,left+1,end);
    }

运行结果:

快速排序(递归版)
1,2,3,3,4,5,6,30,32,33,33,43,43,45,55,65,66,67,68,76,77,90,98,99,
程序运行时间:1893400ns

快速排序(递归优化版)

代码:

//插入排序
    public static void sort(int[] num1,int start,int end){
        int[] num=new int[end-start];
        for (int i = start; i <end ; i++) {
            num[i]=num1[start+i];
        }
        if(num.length<2)return;
        int index;//标志即将插入元素
        int count=0;
        for (int i = 1; i <num.length ; i++) {//开始逐个插入
            index=num[i];//给index赋值操作
            int j;
            for ( j=i-1; j >=0; j--) {//在有序序列中倒序查找比较
                count++;
                if(num[j]<=index)break;//查找到index插入位置
                num[j+1]=num[j];//后移空出新的位置
            }
            num[j+1]=index;//插入index
        }

    }
    //快速排序优化
    public static void quicksort1(int[] num,int start,int end){
        if ((end-start)<2)return;
        //过长时,选择适当基准数
        if((end-start)>10){
        int[] buf=new int[(end-start)/3+1];
        int j=0;
        for (int i = start; i <end ; i+=3) {
            buf[j]=num[i];
            j++;
        }
        sort(buf,0,buf.length);
        int m=buf[buf.length/2];
        for (int k = 0; k < end-start; k++) {
            if(m==num[k]){
                int b=num[start];
                num[start]=m;
                num[k]=b;
                break;}
        }
        }
        //挖坑填数法
        int temp=num[start];
        int left=start;//左标
        int right=end-1;//右标
        int c=0;//标识方便左右交换填坑
        while (left<right){
            if (c==0) {
                if(num[right]>=temp){right--;continue;}
                num[left]=num[right];
                left++;
                c=1;
                continue;
            }
            if (c==1) {
                if (num[left]<temp){left++;continue;}
                num[right]=num[left];
                right--;
                c=0;
                continue;
            }

        }
        num[left]=temp;
        //对左右区间分别递归排序,长度小于10 时使用插入排序优化
        if(left<10){
            sort(num,0,left);
        }else quicksort(num,0,left);
        if ((end-left-1)<10){
            sort(num,left+1,end);
        } else quicksort(num,left+1,end);
    }

运行结果:

快速排序(递归优化版)
1,2,3,3,4,5,6,30,32,33,33,43,43,45,55,65,66,67,68,76,77,90,98,99,
程序运行时间:1014400ns

留言:为作者一人拙见,仅参考使用,如有帮助,不甚荣幸。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱打辅助的小可爱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值