2.快速排序

Posted 老咪聊计算机

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2.快速排序相关的知识,希望对你有一定的参考价值。

1.经典快速排序

快速排序作为最重要的排序算法之一,有时间还是得温习温习。

先说说Partition的过程,经典快排用数组的最后一个元素作为及基准值。将数组的所以小于基准值的数放在数组的左边,等于基准值的数放在数组的中间,大于基准值的放在数组的最后面。
一开始的情况

2.快速排序然后下面循环,直到curr < more的时候结束. 这里我们注意,整个过程像是数组中小于基准值部分推着等于基准值部分向前走.

  • 0 到 less是小于区,
  • less + 1 到 curr - 1是等于区,
  • curr 到 more - 1是待定区,
  • more到数组的最后的元素 是大于区.

最后返回等于区域的下标即可.

Partition完成后就可以写快排的代码了. 快排就是递归的进行Partitio即可.

2.快速排序然后在小于区和大于区分别进行Partition. 最终快排就完成了.

public class Sort {
    public static void swap(int[] arr, int index1,int index2){
        int temp = arr[index1];
        arr[index1] = arr[index2];
        arr[index2] = temp;
    }
    
    public static int[] partition(int[] arr, int L, int R){
        int less = L - 1;
        int more = R + 1;
        int curr = L;
        int num = arr[R];
        while (curr < more){
            if (arr[curr] == num){
                curr++;
            }else if(arr[curr] < num){
                swap(arr, ++less, curr++);
            }else if (arr[curr] > num){
                swap(arr, --more, curr);
            }
        }
        return new int[] {less + 1, more - 1};
    }
    
    public static void quickSort(int[] arr, int L, int R){
        if (L < R){
            int[] p = partition(arr, L, R);
            quickSort(arr, 0, p[0] - 1 );
            quickSort(arr,p[1] + 1, R);
        }
    }
}

我们冷静的分析一波,经典快排存在的问题. 当排序的数组中的数据状况是如下情况的时候

那么我们选取的基准值总是数组的最小值, 这时算法的复杂度就是 , 额外空间复杂度为 . 但是我们并不想这样.

2.随机快速排序

使用Math.random()令系统随机选取一个0~1之间的double类型小数,将其乘以一个数,比如25,就能得到一个0~25范围内的随机数.

public class Sort {
    public static void swap(int[] arr, int index1,int index2){
        int temp = arr[index1];
        arr[index1] = arr[index2];
        arr[index2] = temp;
    }
    
    public static int[] partition(int[] arr, int L, int R){
        int less = L - 1;
        int more = R + 1;
        int curr = L;
        int num = arr[R];
        while (curr < more){
            if (arr[curr] == num){
                curr++;
            }else if(arr[curr] < num){
                swap(arr, ++less, curr++);
            }else if (arr[curr] > num){
                swap(arr, --more, curr);
            }
        }
        return new int[] {less + 1, more - 1};
    }
    
    public static void quickSort(int[] arr, int L, int R){
        if (L < R){
            swap(arr, L + (int)(Math.random() * (R - L + 1)), R);
            int[] p = partition(arr, L, R);
            quickSort(arr, 0, p[0] - 1 );
            quickSort(arr,p[1] + 1, R);
        }
    }
}

随机快排就蕴含着很重要的思想,算法在设计的过程中想绕开它本身的数据状况该怎么办? 一般有两种处理方法,

  • 第一种就是用随机的方式打乱原始的数据状况,
  • 第二种是用Hash的方式也能绕开原始的数据状况.

总结

时间复杂度为 , 额外空间复杂度为 . 快排在工程中是最重要的排序算法之一, 在工程中大部分的排序都是使用快排.

虽然说快速排序的时间复杂度是 的和归并排序和堆排序的时间复杂度一致, 但是快排的实现代码是非常的简洁的, 这说明它的常数项操作少,常数项时间很低.

以上是关于2.快速排序的主要内容,如果未能解决你的问题,请参考以下文章

初识Spring源码 -- doResolveDependency | findAutowireCandidates | @Order@Priority调用排序 | @Autowired注入(代码片段

前端开发工具vscode如何快速生成代码片段

前端开发工具vscode如何快速生成代码片段

Xcode 快速开发 代码块

c#代码片段快速构建代码

快速排序/快速选择算法