快速排序
思想:运用递归将数据以大化小,将排序看成是让每个元素大于左边,小于右边。
算法:选取数据区段内一个元素作为基准,对数据从左右分别向中间扫描,将左边大于基准的值依次放到右边,将右边小于基准的值依次放到左边,将基准放在最后左右指针相遇的位置,这样该基准将这个区段划分为左右两个子区间,基准相对于左右子区间是有序的。对基准左边和右边迭代该算法,
直到原始数据的每个元素都轮到作为基准,便实现每个元素都有序,都大左小右。
代码:(C++实现)
1
void QuickSork(SeqList R, int low, int high)
2
{
3
int pivotpos; // 划分之后的基准的位置变量
4
if(low < high) // 迭代的出口是low=high,即当区间长度=high-low+1=1时,便已完成排序,无需再划分子区间:每条记录都大左小右
5
pivotpos=Partition(R, low, high); // 若区间长度大于1,则对该区间继续划分子区间,划分结果是左区间均小于 // 基准(选R[low]),右区间均大于基准,并返回基准位置
6
QuickSork(R, low, pivotpos-1); // 对左区间递归排序
7
QuickSork(R, pivotpos+1, high); // 对右区间递归排休 (左右子区间都不包含基准,因为基准已经有序:大于左区间,小于右区间)
8
}
9
10
int Partition(SepList R, int i, int j)
11
{
12
ReceType pivot=R[i]; // 用区间的第一个记录作为基准,这样第一个位置便为空,即可以存放换序过来的小于基准的记录
13
while(i<j) // 从区间两端向中间扫描,直到i=j为止
14
{
15
while(i<j&&R[j].key>=pivot.key) // R[j]从后向前扫描,直到遇到第一个小于pivot的记录
16
j--;
17
if(i<j) // 该条件为避免上面的循环结束时,i=j,即两指针之间的所有记录都比pivot大,便不用交换顺序
18
{
19
R[i]=R[j]; // 把R[j]放在R[i]的位置,此时R[j]位置为空,可以存放换序过来的大于pivot的记录
20
i++; // R[i]已完成扫描并存入新纪录,i指针右移一位,等待参与下一轮向右扫描
21
}
22
while(i<j&&R[i].key<=pivot.key) // R[i]从前面向后面扫描,直到遇到第一个大于pivot的记录。条件i<j,为保证两指针没有重叠,即尚有未扫描到的记录
23
i++;
24
if(i<j) // 该条件为避免上面的循环结束时,i=j,即两指针之间的所有记录都比pivot小
25
{
26
R[j]=R[i]; // 把R[i]放在前面空出来的R[j]的位置上,此时R[i]为空,可以存放换序过来的小于pivot的记录
27
j--; // R[j]已完成扫描并存入新纪录,j指针左移一位,等待参与下一轮向左扫描
28
}
29
}
30
R[i]=pivot.key; // 区间内所有记录都扫描完后,即i=j,将基准记录存放在最后空出来的R[i]位置处
31
return i; // 返回基准的位置,此时该区间完成调序,使得基准大于左边记录,小于右边记录
32
}