排序算法---快速排序(java版)

快速排序

原理

快速排序(Quick Sort)算法,简称快排,利用的也是分治的思想,快排的思路是:如果要对 m->n 之间的数列进行排序,我们选择 m->n 之间的任意一个元素数据作为分区点(Pivot),然后我们遍历 m->n 之间的所有元素,将小于 pivot 的元素放到左边,大于 pivot 的元素放到右边,pivot 放到中间,这样整个数列就被分成三部分了,m->k-1 之间的元素是小于 pivot 的,中间是 pivot,k+1->n 之间的元素是大于 pivot 的。然后再根据分治递归的思想处理两边区间的的元素数列,直到区间缩小为 1,就说明整个数列都已有序了。

算法描述如下:

  • 从数列中挑出一个元素,称为 “基准”(pivot);
  • 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
  • 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序,直到区间缩小为1。

代码实现

public class QuickSort {
    
    
    public static void main(String[] args) {
    
    
        int[] arr = {
    
    5, 2, 6, 9, 0, 3, 4};
        quickSort(arr,0,arr.length-1);
        System.out.println(Arrays.toString(arr));
    }
    public static void quickSort(int[] arr, int begin, int end) {
    
    
        if (arr.length <= 1 || begin >= end) {
    
    
            return;
        }
        //进行分区得到分区下标
        int pivotIndex = partition(arr, begin, end);
        //分区左侧进行快排
        quickSort(arr, begin, pivotIndex - 1);
        //分区右侧进行快排
        quickSort(arr,pivotIndex+1,end);
    }
    public static int partition(int[] arr, int begin, int end) {
    
    
        //默认使用 最后一个元素作为基准点
        int pivot = arr[end];
        //定义分区后的pivot元素下标
        int pivotIndex = begin;
        for (int i = begin; i < end; i++) {
    
    
            判断如果该区间内如果有元素小于 pivot 则将该元素从区间头开始一直向后填充 有点类似选择排序
            if (arr[i] < pivot) {
    
    
                if (i > pivotIndex) {
    
    
                    swap(arr,i,pivotIndex);
                }
                pivotIndex++;
            }
        }
        swap(arr,pivotIndex,end);
        //得到基准点
        return pivotIndex;
    }

    //交换元素
    public static void swap(int[] arr, int i, int j) {
    
    
        int temp = arr[j];
        arr[j] = arr[i];
        arr[i] = temp;
    }
}

1:快速排序的时间复杂度是多少?

快排的时间复杂度最好以及平均情况下的复杂度都是 O(nlogn),只有在极端情况下会变成 O(n^2)。

2:快速排序的空间复杂度是多少?

通过快排的代码实现我们发现,快排不需要额外的存储空间,所有的操作都能在既定的空间内完成,因此快排的空间复杂度为 O(1),也就是说快排是一种 in-place的排序算法。

3:快速排序是稳定的排序算法吗?

因为分区的过程涉及交换操作,如果数组中有两个相同的元素,比如序列 6,8,7,6,3,5,9,4,在经过第一次分区操作之后,两个 6 的相对先后顺序就会改变。所以,快速排序并不是一个稳定的排序算法。

4:快排和归并的异同

首先快排和归并都用到了分治递归的思想,在快排中对应的叫分区操作,递推公式和递归代码也非常相似,但是归并排序的处理过程是由下到上的由局部到整体,先处理子问题,然后再合并。而快排正好相反,它的处理过程是由上到下由整体到局部,先分区,然后再处理子问题。归并排序虽然是稳定的、时间复杂度为 O(nlogn) 的排序算法,但是它是一种 out-place 排序算法。主要原因是合并函数无法在原地(数组内)执行。快速排序通过设计巧妙的原地(数组内)分区函数,可以实现原地排序,解决了归并排序占用太多内存的问题。

猜你喜欢

转载自blog.csdn.net/qq_33626996/article/details/113177707