第7章 快速排序
此篇博客很早之前写的,格式不够优雅,优化版请移步再谈快速排序。
摘要:
快速排序是一种排序算法,对包含n个数的输入数组,最坏情况运行时间为O(n2)。由于平均性能比较好,期望的运行时间为O(nlgn),且O(nlgn)记号中隐含的常数因子很小,快速排序通常用于排序的最佳的实用选择。
7.1 快速排序的描述
快速排序是基于分治模式构思的,具体描述如下:
分解:数组A[p..r]被划分成两个(可能空)子数组A[p..q-1]和A[q+1..r],使得A[p..q-1]中的每个元素都小于等于A(q),而且,小于等于A[q+1..r]中的元素。下标q也在这个划分过程中进行计算。
解决:通过递归调用快速排序,对子数组A[p..q-1]和A[q+1..r]排序。
合并:因为两个子数组是就地排序的,将它们合并不需要操作:整个数组A[p..r]已排序。
下面的过程实现快速排序:
QUICKSORT(A, p, r)
if p < r
then q <- PARTITION(A, p, r)
QUICKSORT(A, p, q–1)
QUICKSORT(A, q+1, r)
为排序一个完整的数组A,最初的调用是QUICKSORT(A,1, length[A])。
数组划分:
快速排序算法的关键是PARTITION过程,它对于子数组A[p..r]进行就地重排:
PARTITION(A, p, r)
x <- A[r]
i <- p–1
for j <- p to r–1
do if A[j]<= x
theni <- i+1
exchangeA[i] <-> A[j]
exchange A[i+1] <-> A[r]
return i+1
图7.1展示PARTITION中一个包含8个元素的数组上的操作过程。PARTITION总是选择一个x=A[r]作为主元,并围绕它来划分子数组A[p..r]。随着该过程的执行,数组被划分成四个(可能有空的)区域。
图7.1PARTITION中一个样例数组上的运行过程。(摘自算法导论)
具体执行步骤如下:
a) i=p-1, j=p, x=A[r]
b) 因为A[i]<=x,i=p,A[i]和A[j]交换
c) A[j]=7>x,j递增
d) 当A[j]=1时,因为A[i]<=x,i=p+1,A[i]和A[j]交换
e) 当A[j]=3时,因为A[i]<=x,i=p+2,A[i]和A[j]交换
f) A[j]=5>x,j递增
g) A[j]=6>x,j递增
h) j=r,A[r]和A[i+1]交换
7.2 快速排序算法程序(C++)
//QuickSort.h
bool Swap(int *data, int lhs, int rhs);
//数组划分
int Partition(int *data, int left, intright)
{
if(data == NULL || left < 0 || right < 0 || left > right)
return-1;
intpivot = data[right];
inti = left;
intj = left - 1;
inttemp = 0;
while(i <= right)
{
if(data[i] <= pivot)
{
++j;
Swap(data,i, j);
}
++i;
}
returnj;
}
//快速排序
bool QuickSort(int *data, int left, intright)
{
if(data == NULL || left < 0 || right < 0 || left >right)
returnfalse;
if(left < right)
{
intmid = Partition(data, left, right);
QuickSort(data,left, mid - 1);
QuickSort(data,mid + 1, right);
}
returntrue;
}
//交换数据
bool Swap(int *data, int lhs, int rhs)
{
if(data == NULL)
returnfalse;
inttemp = data[lhs];
data[lhs]= data[rhs];
data[rhs]= temp;
returntrue;
}
//测试程序Test.cpp
#include <iostream>
#include <stdio.h>
#include "QuickSort.h"
using namespace std;
bool Input(int *data, int num);
bool Output(int *data, int num);
const int Number = 100; //测试数组样例个数
int main()
{
int*data = NULL;
intnum = Number;
data= new int[num];
Input(data,num);
Output(data,num);
boolretValue = false;
if((retValue = MergeSort(data, 0, num - 1)) == false)
{
cout<< "Data Error!" << endl;
return-1;
}
Output(data,num);
delete[]data;
return0;
}
//Input Data
bool Input(int *data, int num)
{
if(data == NULL || num <= 0)
{
returnfalse;
}
inti = 0;
for(i = 0; i < num; ++i)
{
data[i]= rand() % num;
}
returntrue;
}
//Output Data
bool Output(int *data, int num)
{
if(data == NULL || num <= 0)
{
returnfalse;
}
inti = 0;
for(i = 0; i < num; ++i)
{
cout<< data[i] << " ";
}
cout<< endl;
returntrue;
}
快速排序结果:
图7.2 快速排序结果
7.3 总结
快速排序算法因为良好的排序性能,在排序算法中地位显著。在以后的总结中,我会列出排序性能的具体分析过程和直观性能对比,敬请关注。
参考文献:
[1] Thomas H.Cormen, Charles E.Leiserson,etc. 算法导论