快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为两个子序列(sub-lists)。
步骤为:
- 从数列中挑出一个元素,称为"基准"(pivot),
- 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
- 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。By the way,快速排序的时间复杂度为(nlogn).
下面为c语言代码:
#include<stdio.h>
#define MaxSize 100
struct DataType
{
int data;
};
struct Sqlist
{
DataType R[MaxSize];
int length;
};
//寻找基准的放入位置
int Partition(Sqlist *l,int left,int right)
{
l->R[0] = l->R[left];//置为哨点
while(left < right)
{
//从右向左开始查找第一个小于哨点的数
while(left<right && l->R[right].data >= l->R[0].data)
{
right--;
}
if(left<right)
{
//将较小数移至左边
l->R[left] = l->R[right];
left++;
}
//从左向右开始查找第一个大于哨点的数
while(left<right && l->R[left].data <= l->R[0].data)
{
left++;
}
if(left<right)
{
//将较大数移至右边
l->R[right] = l->R[left];
right--;
}
//测试或者便于理解使用代码
/*
printf("\n查看该趟排序结果:\n");
for(int i=0;i<l->length;i++)
{
printf("%d ",l->R[i+1].data);
}
printf(" left=%d right=%d \n",left,right);
*/
}
//将基准送至准确的位置(左边的数比它小,右边的数比它大)
l->R[left] = l->R[0];
return left;
}
//快速排序
void QuickSort(Sqlist *l,int left,int right)
{
int position;
if(left<right)
{
position = Partition(l,left,right);
QuickSort(l,left,position-1);
QuickSort(l,position+1,right);
}
}
int main()
{
Sqlist list;
list.length = 11;
int data[11] = {3,1,9,2,4,7,5,6,2,3,1};
//初始化
for(int i=0;i<list.length;i++)
{
list.R[i+1].data = data[i];
}
//Partition(&list,1,11);
QuickSort(&list,1,11);
for(int i=0;i<list.length;i++)
{
printf("%d ",list.R[i+1].data);
}
return 0;
}
运行结果:
有什么意见或者建议,读者可以给我说说,大家一块进步。Thanks.