八大排序算法--快速排序(动图理解)

快速排序

概念

快速排序是对冒泡排序的一种改进。其基本原理是通过选取一个基准元素,将数组划分为两个子数组,分别对子数组进行排序,最终实现整个数组的有序排列。快速排序的时间复杂度最好为O(nlogn),最坏为O(n^2),是一种高效的排序算法。

算法思路

快速排序的基本思想是:选择一个基准元素,将数组划分为两个子数组,一趟排序完后,比基准元素小的元素都在左边,比基准元素大的元素都在右边,然后分别对左右子数组进行排序,最终实现整个数组的有序排列。具体地,排序过程如下:

1.选择一个基准元素;
2.将数组划分为两个子数组,比基准元素小的元素放在左边,比基准元素大的元素放在右边;
3.分别对左右子数组进行排序,重复上述操作;
4.直到整个数组有序为止。

动画演示

算法代码


    public  static void qSort(int[] a,int left,int right){   //主体
        if(left >= right) return;
        int i = left;
        int j = right;
        int pos = a[left];   //基准数

        while(i < j){
            while(i < j && a[j] >= pos) {
                j--;
            }
            a[i] = a[j];
            while(i < j && a[i] <= pos) {
                i++;
            }
            a[j] = a[i];
        }

        a[i] = pos;  //这步是 left==right了 ,最后把基准值放进去

        qSort(a,left,i-1);  //基准值的左边
        qSort(a,i+1,right);  //基准值的右边

    }

复杂度分析

时间复杂度 最好O(nlogn)  最坏O(n^2)

空间复杂度  最好O(logn)   最坏O(n)

稳定性  不稳定

时间复杂度测试

接下来我们试着用大量数据测试一下。

扫描二维码关注公众号,回复: 16114263 查看本文章

int[] a = new int[10_0000];  //10万个数据测试

1.orderArray函数实现生成一个基本有序数列,即从小到大排列。

public static void orderArray(int[] a) {
        for (int i = 0; i < a.length; i++) {
            a[i] = i;
        }
 }

2.notOrderArray函数生成一个倒序数列,即从大到小排列。

public static void notOrderArray(int[] a) {
        for (int i = 0; i < a.length; i++) {
            a[i] = a.length-i;
        }
 
}

3.randomArray函数生成一个随机无序数列。

 public static void randomArray(int[] a) {
        Random random = new Random();
        for (int i = 0; i < a.length; i++) {
            a[i] = random.nextInt(10_0000);
        }
 }

4.testInsertSort函数测试   System.currentTimeMillis() 返回值单位是毫秒。

 public static void testInsertSort(int[] a){
        int[] tmpArray = Arrays.copyOf(a,a.length);
        long startTime = System.currentTimeMillis();    //注意用long接收
        shellSort(tmpArray);
        long endTime = System.currentTimeMillis();  //返回单位是毫秒
        System.out.println("快速排序耗时:"+(endTime-startTime));
 }

5.main函数调用执行

public static void main(String[] args) {
 
        int[] a = new int[10_0000];
        //有序
        System.out.println("基本有序数列");
        orderArray(a);
        testInsertSort(a);
 
        //倒序
        System.out.println("逆序数列");
        notOrderArray(a);
        testInsertSort(a);
 
        //随机乱序
        System.out.println("无序数列");
        randomArray(a);
        testInsertSort(a);
 
    }


测试结果


当用10万个数据测试时:

 结果显示栈溢出了。因为在不断的递归过程中,都一分为二,函数不断被调用,就像二叉树一样,数据越多,二叉树就越来越大。而调用一次,就得在栈中开辟一块空间。这时候就得考虑用非递归去实现了。

当用1万个数据测试时: 正常

 完整代码


import java.util.Arrays;
import java.util.Random;

public class sort {
    public static void main(String[] args) {
        
        int[] a = new int[10000];
        //有序
        System.out.println("基本有序数列");
        orderArray(a);
        testInsertSort(a);

        //无序
        System.out.println("逆序数列");
        notOrderArray(a);
        testInsertSort(a);

        //乱序
        System.out.println("无序数列");
        randomArray(a);
        testInsertSort(a);
    }

    
    public static void quickSort(int[] a){//包装一下,当我调用的时候就方便了,只需要传一个参数
                                          //int[] a
        qSort(a,0,a.length-1);
    }
    public  static void qSort(int[] a,int left,int right){   //主体
        if(left >= right) return;
        int i = left;
        int j = right;
        int pos = a[left];   //基准数

        while(i < j){
            while(i < j && a[j] >= pos) {
                j--;
            }
            a[i] = a[j];
            while(i < j && a[i] <= pos) {
                i++;
            }
            a[j] = a[i];
        }

        a[i] = pos;  //这步是 left==right了 ,最后把基准值放进去

        qSort(a,left,i-1);  //基准值的左边
        qSort(a,i+1,right);  //基准值的右边

    }


    //生成有序数组  从小到大排列
    public static void orderArray(int[] a) {
        for (int i = 0; i < a.length; i++) {
            a[i] = i;
        }
    }


    //n无序 其实就是从大到小排列
    public static void notOrderArray(int[] a) {
        for (int i = 0; i < a.length; i++) {
            a[i] = a.length-i;
        }

    }


    //乱序 随机生成序列
    public static void randomArray(int[] a) {
        Random random = new Random();
        for (int i = 0; i < a.length; i++) {
            a[i] = random.nextInt(10_0000);
        }
    }


    //大量数据测试
    public static void testInsertSort(int[] a){
        int[] tmpArray = Arrays.copyOf(a,a.length);
        long startTime = System.currentTimeMillis();    //注意用long接收
        quickSort(tmpArray);
        long endTime = System.currentTimeMillis();
        System.out.println("快速排序耗时:"+(endTime-startTime));
    }
}

 创作不易,如果本篇博客对您有一定的帮助,大家记得留言+点赞哦。

猜你喜欢

转载自blog.csdn.net/m0_73381672/article/details/132031340