一、算法原理
快速排序(Quick sort)是一种应用最广泛的排序算法,实现简单,适用于各种不同的输入数据且在一般应用中比其他排序算法都要快得多。快速排序最大的优点是它是原址排序(只需要一个很小的辅助栈),且将规模为n的数组排序所需的时间与nlogn成正比,而前面学习过的冒泡排序、选择排序、插入排序和归并排序都无法将这两个优点结合在一起。快速排序的缺点是实现时容易造成低劣的性能,最坏情况时间能达到O(n^2)。
二、算法描述
快速排序也是一种基于分治思想的排序算法,将一个数组分成两个子数组,分别进行排序。主要过程分为下面几步:
- 分解
数组A[p…r]划分为两个子数组,A[p…q-1]中每一个元素都小于等于A[q],A[q+1…r]中每一个元素都大于等于A[q]。计算下标q是划分过程的一部分。 - 解决
通过递归调用快速排序方法,对子数组A[p…q-1]和A[q+1…r]进行排序 - 合并
因为子树组都是原址排序的,不需要归并操作。
快速排序中的划分方法Patition()是核心方法,直接决定快速排序的性能。一种常见的方法是,Patition总是选择一个x = A[r]作为主元来划分数组A[p…r],运行过程中数组被分成四个区域(可能有空),如下表所示
区域 | 元素 | 范围 |
---|---|---|
一 | A[k] <= x | p <= k <= i |
二 | A[k] > x | i+1 <= k <= j-1 |
三 | 未知元素 | j <= k <= r-1 |
四 | 主元 A[k] | k = r |
三、算法复杂度
- 时间性能:最坏情况下 T(n) = O(n^2),最佳情况下 T(n) = O(nlogn),平均情况 T(n) = O(nlogn)。
- 空间性能:O(1)
四、示例代码
//快速排序(C语言)
//交换两个数组元素
void exchange(int * a, int * b)
{
int temp = *a;
*a = *b;
*b = temp;
}
//Partiotion划分方法,取数组最后一个元素A[r]作为主元
//主元左边的都小于或等于主元,右边的都大于主元
int Partition(int A[], int p, int r)
{
int x = A[r];
int i = p - 1;
for (int j = p; j < r; j++)
{
if(A[j] <= x)
{
i++;
exchange(A + i, A + j);
}
}
exchange(A + i + 1, A + r); //将主元放置到正确位置
return i + 1; //返回主元的位置
}
//递归函数,每次传入数组A和首尾元素的下标
void QuickSort(int A[], int p, int r)
{
if(p < r)
{
int q = Partition(A, p, r);
QuickSort(A, p, q - 1);
QuickSort(A, q + 1, r);
}
}