三. 快速排序(Quick Sort)及其简单改进(严蔚敏奶奶)
1 快速排序
1.1 算法描述(文字)
快速排序的基本思想是,通过一趟排序将待排序记录分割成独立的两个部分,一部分记录均比另一部分小,然后分别对两个部分进行排序.
它是对冒泡排序的一种改进.关键在于分割的过程,它遵循下面3个条件对数组a[N]重组
- a[i]应该位于它最终的位置上
- a[0]至a[i-1]应该不大于a[i]
- a[i+1]至a[N-1]应该不小于a[i]
1.2 算法描述(草图)

1.3 代码实现(c语言)
1.3.1 原始版本v1(交换)
1.3.1.1 算法草图

1.3.1.2 代码实现(c语言 严蔚敏奶奶)
/*
v1: 分割函数,关键逻辑
双向扫描
严蔚敏奶奶-数据结构page274
*/
int Partition(SqList &L, int low, int high){
// 交换顺序表L中子表L.r[low..high]的记录,使枢轴记录到位,并返回其所在位置,此时
// 在它之前的记录均不大于它,在它之后的记录均不小于它
KeyType pivotKey = L.r[low].key; // 用子表的第一个记录作枢轴记录
while (low < high){ // 从表的两端交替地向中间扫描
while (low < high && L.r[high].key >= pivotKey) {
--high;
}
swap(&L.r[low], &L.r[high]); // 将比枢轴记录小的记录交换到低端
while (low < high && L.r[low].key <= pivotKey) {
++low;
}
swap(&L.r[low], &L.r[high]); // 将比枢轴记录大的记录交换到高端
}
return low; // 返回枢轴位置
}
void QSort(SqList &L, int low, int high){
// 对顺序表L中的子序列L.r[low..high]作快速排序
if (low < high){ // 长度大于1
int pivotloc = Partition(L, low, high); //版本v1 将L.r[low..high]一分为二
QSort(L, low, pivotloc-1); // 对低子表递归排序,pivotloc是枢轴位置
QSort(L, pivotloc+1, high); // 对高子表递归排序
}
} // QSort
1.3.2 改进版本v2(赋值)
改进点:版本v1具体实现上,每交换一对记录需进行3次记录移动的操作,而实际上,在排序过程中对,枢轴记录的赋值是多余的,因为只有在一趟排序结束时,枢轴才是最后的位置.
1.3.2.1 算法草图

1.3.2.2 代码实现(c语言 严蔚敏奶奶)
/*
v1: 分割函数,关键逻辑
双向扫描-移动
严蔚敏奶奶-数据结构page274
*/
int Partition2(SqList &L, int low, int high){
// 交换顺序表L中子表L.r[low..high]的记录,使枢轴记录到位,并返回其所在位置,此时
// 在它之前的记录均不大于它,在它之后的记录均不小于它
L.r[0] = L.r[low];
KeyType pivotKey = L.r[low].key; // 用子表的第一个记录作枢轴记录
while (low < high){ // 从表的两端交替地向中间扫描
while (low < high && L.r[high].key >= pivotKey) {
--high;
}
L.r[low] = L.r[high]; // (改进点)将比枢轴记录小的记录移到低端
while (low < high && L.r[low].key <= pivotKey) {
++low;
}
L.r[high] = L.r[low]; // (改进点)将比枢轴记录大的记录交换到高端
}
L.r[low] = L.r[0];
return low; // 返回枢轴位置
}
void QSort(SqList &L, int low, int high){
// 对顺序表L中的子序列L.r[low..high]作快速排序
if (low < high){ // 长度大于1
int pivotloc = Partition2(L, low, high); //版本v2 将L.r[low..high]一分为二
QSort(L, low, pivotloc-1); // 对低子表递归排序,pivotloc是枢轴位置
QSort(L, pivotloc+1, high); // 对高子表递归排序
}
} // QSort
1.4 Demo实例
1.4.1 完整代码
#include <iostream>
#include <stdio.h>
/*
快速排序
严奶奶 数据结构
实现: 参见严奶奶 Page264 274
*/
#define MAXSIZE 20 // 顺序表的最大长度
typedef int KeyType; // 关键字类型为整数类型
typedef int InfoType; //
typedef struct {
KeyType key; // 关键字项
InfoType otherinfo; // 其他数据项
} RedType;
typedef struct {
RedType r[MAXSIZE + 1]; // r[0]闲置或用作哨兵单元
int length; // 顺序表长度
} SqList; // 顺序表类型
/*
交换变量值
*/
void swap(RedType* x, RedType* y){
RedType t = *x;
*x = *y;
*y = t;
}
/*
v1: 分割函数,关键逻辑
双向扫描-交换
严蔚敏奶奶-数据结构page274
*/
int Partition(SqList &L, int low, int high){
// 交换顺序表L中子表L.r[low..high]的记录,使枢轴记录到位,并返回其所在位置,此时
// 在它之前的记录均不大于它,在它之后的记录均不小于它
KeyType pivotKey = L.r[low].key; // 用子表的第一个记录作枢轴记录
while (low < high){ // 从表的两端交替地向中间扫描
while (low < high && L.r[high].key >= pivotKey) {
--high;
}
swap(&L.r[low], &L.r[high]); // 将比枢轴记录小的记录交换到低端
while (low < high && L.r[low].key <= pivotKey) {
++low;
}
swap(&L.r[low], &L.r[high]); // 将比枢轴记录大的记录交换到高端
}
return low; // 返回枢轴位置
}
/*
v1: 分割函数,关键逻辑
双向扫描-移动
严蔚敏奶奶-数据结构page274
*/
int Partition2(SqList &L, int low, int high){
// 交换顺序表L中子表L.r[low..high]的记录,使枢轴记录到位,并返回其所在位置,此时
// 在它之前的记录均不大于它,在它之后的记录均不小于它
L.r[0] = L.r[low];
KeyType pivotKey = L.r[low].key; // 用子表的第一个记录作枢轴记录
while (low < high){ // 从表的两端交替地向中间扫描
while (low < high && L.r[high].key >= pivotKey) {
--high;
}
L.r[low] = L.r[high]; // 将比枢轴记录小的记录移到低端
while (low < high && L.r[low].key <= pivotKey) {
++low;
}
L.r[high] = L.r[low]; // 将比枢轴记录大的记录交换到高端
}
L.r[low] = L.r[0];
return low; // 返回枢轴位置
}
void QSort(SqList &L, int low, int high){
// 对顺序表L中的子序列L.r[low..high]作快速排序
if (low < high){ // 长度大于1
// int pivotloc = Partition(L, low, high); //版本v1 将L.r[low..high]一分为二
int pivotloc = Partition2(L, low, high); //版本v2 将L.r[low..high]一分为二
QSort(L, low, pivotloc-1); // 对低子表递归排序,pivotloc是枢轴位置
QSort(L, pivotloc+1, high); // 对高子表递归排序
}
} // QSort
void QuickSort(SqList &L){
// 对顺序表L作快速排序
QSort(L, 1, L.length);
} // QuickSort
void print(SqList L){
for (int i = 1; i<=L.length; i++){
printf("(%d, %d)", L.r[i].key, L.r[i].otherinfo);
}
printf("\n");
}
int main(int argc, char** argv) {
// 构造待排序数据
RedType arrData [] = {{35,85}, {33,90}, {1, 99}, {62, 87}, {61, 88}} ;
int arrayLength = sizeof(arrData)/sizeof(arrData[0]);
SqList l;
for (int i = 0; i< arrayLength; i++){
l.r[i+1] = arrData[i];
}
l.length = arrayLength;
print(l);
QuickSort(l);
print(l);
return 0;
}
1.4.2 执行结果

可以看到1,33,35,61,62有序
谢谢阅读完,欢迎您的留言讨论

浙公网安备 33010602011771号