快速排序是对冒泡排序的一种改进。
基本算法思想:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
假设待排序的序列为
{L.r[s],L.r[s+1],…,L.r[t]}
,首先任意选取一个一个记录(通常可选第一个记录
L.r[s]
)作为枢轴(pivot),然后按下述原则重新排列其余记录:将所有关键字较它喜爱哦的记录都安置在它的位置之前,将所有的关键字较它大的记录都安置在它的位置之后。由此可以该枢轴记录最后所落的位置i作为分界线,将序列
{L.r[s],L.r[s+1],…,L.r[t]}
分割成两个子序列
{L.r[s],L.r[s+1],…,L.r[i−1]}
和
{L.r[i+1],L.r[i+2],…,L.r[t]}
。这个过程称作一趟快速排序(或一次划分)。
一趟快速排序的具体做法是:附设两个指针low和high,它们的初值分别为low和high,设枢轴记录的关键字为pivotkey,则首先从high所指的位置起向前搜索找到第一个关键字小于pivotkey的记录和枢轴记录相互交换,然后从low所指的位置起向后搜索,找到第一个关键字大于pivotkey的记录和枢轴记录相互交换,重复这两步直至low=high为止。
若待排序列中止呕一个记录,显然已经有序,否则进行一趟快速排序后再分别对分割所得的两个子序列进行快速排序,如下图所示。
- 类型定义
#define MAXSIZE 20 /* 一个用作示例的小顺序表的最大长度 */
typedef int InfoType; /* 定义其它数据项的类型 */
typedef int KeyType; /* 定义关键字类型为整型 */
typedef struct
{
KeyType key; /* 关键字项 */
InfoType otherinfo; /* 其它数据项,具体类型在主程中定义 */
}RedType; /* 记录类型 */
typedef struct
{
RedType r[MAXSIZE+1]; /* r[0]闲置或用作哨兵单元 */
int length; /* 顺序表长度 */
}SqList; /* 顺序表类型 */
- 快速排序函数
void QuickSort(SqList *L)
{ /* 对顺序表L作快速排序。 */
QSort(L,1,(*L).length);
}
void QSort(SqList *L,int low,int high)
{ /* 对顺序表L中的子序列L.r[low..high]作快速排序。算法10.7 */
int pivotloc;
if(low<high)
{ /* 长度大于1 */
pivotloc=Partition(L,low,high); /* 将L.r[low..high]一分为二 */
QSort(L,low,pivotloc-1); /* 对低子表递归排序,pivotloc是枢轴位置 */
QSort(L,pivotloc+1,high); /* 对高子表递归排序 */
}
}
int Partition(SqList *L,int low,int high)
{ /* 交换顺序表L中子表L.r[low..high]的记录,使枢轴记录到位, */
/* 并返回其所在位置,此时在它之前(后)的记录均不大(小)于它。 */
RedType t;
KeyType pivotkey;
pivotkey=(*L).r[low].key; /* 用子表的第一个记录作枢轴记录 */
while(low<high)
{ /* 从表的两端交替地向中间扫描 */
while(low<high&&(*L).r[high].key>=pivotkey)
--high;
t=(*L).r[low]; /* 将比枢轴记录小的记录交换到低端 */
(*L).r[low]=(*L).r[high];
(*L).r[high]=t;
while(low<high&&(*L).r[low].key<=pivotkey)
++low;
t=(*L).r[low]; /* 将比枢轴记录大的记录交换到高端 */
(*L).r[low]=(*L).r[high];
(*L).r[high]=t;
}
return low; /* 返回枢轴所在位置 */
}
- 主程序
#include<stdio.h>
#define N 8
void print(SqList L)
{
int i;
for(i=1;i<=L.length;i++)
printf("(%d,%d)",L.r[i].key,L.r[i].otherinfo);
printf("\n");
}
void main()
{
RedType d[N]={{49,1},{38,2},{65,3},{97,4},{76,5},{13,6},{27,7},{49,8}};
SqList l;
int i;
for(i=0;i<N;i++)
l.r[i+1]=d[i];
l.length=N;
printf("排序前:\n");
print(l);
QuickSort(&l);
printf("排序后:\n");
print(l);
}
- 测试结果