快速排序是基于交换思想对冒泡排序的一种改进的交换排序方法,又称分区交换排序,它采用分治的策略。
分治思想:将原问题划分为若干个与原问题结构相似的子问题,递归的解决这些子问题,然后将子问题的解组合为原问题的解.
快速排序:在待排序列中,任取一个记录(通常是第一个记录),并以该关键字作为基准,经过一趟交换之后,所有的比他小的记录都交换到他的左边,而所有比它大的记录都交换到它的右边,此时,该记录在序列中的位置就以确定。同时我们把这个问题划分成了两部分,然后在分别对这两个部分重复上述过程,直到每一个部分最终划为一个记录为止。
快速排序算法:QuickSort(RecordType R[],int s, int e)
**{
int i;
if(s<e)
{
i = Partition(R,s,e);
QuickSort(R,s,i-1);
QuickSort(R,i+1,e);
}
}**
快速排序的核心是划分子问题:
int Partition(RecordType R[], int s , int e)
{
int temp;
temp = R[s];
while(i<j)
{
while(i<j && R[j]>=temp)
j--;
if(i < j)
{
R[i] = R[j];
i++;
}
while(i<j && R[i]<=temp)
i++;
if(i < j)
{
R[j] = R[i];
j--;
}
}
R[i] = temp;
return i;
}
Partition函数完成在给定区间 R[i]~R[j] 中一趟快速排序的划分。设置两个搜索指针 i 和 j 来指向给定区间的头一个记录和最后一个记录,并将头一个记录作为基准记录。首先从 j 指针开始从右向左搜索关键字比基准记录关键字小的记录,找到后将其交换到 i 指针处;然后 i 指针右移一个位置并由次开始自左向右搜索关键字比基准记录关键字大的记录,找到后将其交换到 j 指针处;接着 j 指针左移一个位置并继续上述自右向左搜索、交换的过程。如此两端交替向中间搜索、交换,直到 i 与 j 相等,i 左侧的记录都比基准记录小,而 j 右侧的记录及其关键字都比基准记录的关键字大,而 i 和 j 所指向的这同一个位置就是基准记录最终要放的位置。
下图是一趟快速排序的示意图:
从空间效率看:快排是递归的,每层递归调用的指针和参数都要用栈来存放。存储开销在最理想的情况下为O(log2n ),最坏情况下,递归调用是一个单支树,空间复杂度为O(n).
从时间效率上看:对n个记录的待排序列,一次划分需要约n次关键字的比较,时间效率为O(n)。若设T(n)为对n个记录进行快速排序所需的时间,则理想情况下每次划分正好将n个记录分为等长的子序列,并且每次划分所需要的比较次数为n-1;则T(n)<= n+2T(n/2) = n+2(n/2+2T(n/4))=2n+4T(n/4) = O(nlog2n)
在最坏的情况下,每次划分只得到一个子序列,即时间复杂度为O(n2)
#include <stdio.h>
void QuickSort(int array[],int left,int right);
int Partition(int array[],int left,int right);
int main()
{
int array[10] = {23,12,321,10,2,1,89,20,13,25};
int i;
QuickSort(array,0,9);
for(i=0;i<10;i++)
{
printf("%d ",array[i]);
}
return 0;
}
int Partition(int array[],int left,int right)
{
int temp;
temp = array[left];
while(left<right)
{
while(left<right && array[right]>=temp)
right--;
if(left < right)
{
array[left] = array[right];
left++;
}
while(left<right && array[left]<=temp)
left++;
if(left < right)
{
array[right] = array[left];
right--;
}
}
array[left] = temp;
return left;
}
void QuickSort(int array[],int left,int right)
{
int mid;
if(left<right)
{
mid = Partition(array,left,right);
QuickSort(array,left,mid-1);
QuickSort(array,mid+1,right);
}
}