排序算法之快速排序分析(未完)

快速排序

快排思想:

如果要排序数组中下标从 p 到 r 之间的一组数据,我们选择 p 到 r 之间的任意一个数据作为 pivot(分区点)。

我们遍历 p 到 r 之间的数据,将小于 pivot 的放到左边,将大于 pivot 的放到右边,将 pivot 放到中间。

数组 p 到 r 之间的数据就被分成了三个部分:

前面 p 到 q-1 之间都是小于 pivot 的,中间是 pivot,后面的 q+1 到 r 之间是大于 pivot 的。

用递归排序下标从 p 到 q-1 之间的数据和下标从 q+1 到 r 之间的数据,直到区间缩小为 1,就说明所有的数据都有序了。

快排和归并一样,利用的也是分治的思想

归并排序的处理过程是由下到上的,先处理子问题,然后再合并。

而快排正好相反,它的处理过程是由上到下的,先分区,然后再处理子问题。

快速排序常用递归来实现,可以推出快速排序排序的递推公式和中止条件为:

递推公式:
quick_sort(p…r) = quick_sort(p…q-1) + quick_sort(q+1… r)

终止条件:
p >= r
这里和归并排序的终止条件不同,归并排序终止条件也可以写为p>=r,但是实际上p==r就够了。
但是在快排中若写成p==r,则会栈溢出,因为快排中q+1,也就是p,会大于r。

归并排序中有一个merge函数,而快速排序中有一个 partition() 分区函数。partition() 分区函数实际上我们就是随机选择一个元素作为 pivot,然后对 A[p…r]分区,函数返回 pivot 的下标。(一般情况下,可以选择 p 到 r 区间的最后一个元素作为pivot)

分区函数的处理有点类似选择排序,通过游标 i 把 A[p…r-1]分成两部分。

A[p…i-1]的元素都是小于 pivot 的,我们暂且叫它“已处理区间”

A[i…r-1]是“未处理区间”。我们每次都从未处理的区间 A[i…r-1]中取一个元素 A[j],与 pivot 对比,如果小于 pivot,则将其加入到已处理区间的尾部,也就是 A[i]的位置。

在数组某个位置插入元素,需要搬移数据,非常耗时。但是在这里,我们可以交换。

只需要将 A[i]与 A[j]交换,就可以在 O(1) 时间复杂度内将 A[j]放到下标为 i 的位置。

快速排序的执行效率

最好情况下时间复杂度

O(nlogn)

最坏情况下时间复杂度

O(n²)

平均情况下时间复杂度

O(nlogn)

快速排序的内存消耗

快速排序算法的运行并不需要额外的存储空间,所以空间复杂度是 O(1),是一个原地排序算法

快速排序的稳定性

因为快速排序涉及数据的交换,所以快速排序是不稳定的排序算法。

比如序列 6,8,7,6,3,5,9,4,在经过第一次分区操作之后,第一个6会与3交换位置,两个 6 的相对先后顺序就会改变。

快速排序的代码实现

public class QuickSort {
    public void quickSort(int[] array, int n) {
        quickSortInternally(array, 0, n - 1);
    }
    
    private void quickSortInternally(int[] array, int p, int r) {
        if (p >= r) return;
        int q = partition(array, p, r);
        quickSortInternally(array, p, q - 1);
        quickSortInternally(array, q + 1, r);
    }

    private static int partition(int[] a, int p, int r) {
        int pivot = a[r];
        int i = p;
        for(int j = p; j < r; ++j) {
            if (a[j] < pivot) {
                if (i == j) {
                    ++i;
                } else {
                    int tmp = a[i];
                    a[i++] = a[j];
                    a[j] = tmp;
                }
            }
        }
        int tmp = a[i];
        a[i] = a[r];
        a[r] = tmp;

        return i;
    }
}
发布了91 篇原创文章 · 获赞 22 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_42006733/article/details/104428073