前言
在算法导论上看到的快速排序的实现,感觉比之前在辅导书上看到的要好理解多了。算法导论真是神书。
思路
快排递归算法除分解为子情况之外的基本操作就是将主元移动到这样一个位置,主元左边都是小于主元的元素,主元右边都是大于主元的元素。然后再分别对主元左右两边进行快排即可。
实现
完整代码
#include<iostream>
using namespace std;
void mySwap(int a[], int x, int y) {
int temp = a[x];
a[x] = a[y];
a[y] = temp;
return;
}
int myPartition(int a[], int low, int high) {
int temp = a[high];
int i = low - 1;
for (int j = low; j < high; j++) {
if (a[j] <= temp) {
i++;
mySwap(a, i, j);
}
}
mySwap(a, i + 1, high);
return i + 1;
}
void myQuickSort(int a[], int low, int high) {
if (low < high) {
int mid = myPartition(a, low, high);
myQuickSort(a, low, mid - 1);
myQuickSort(a, mid + 1, high);
}
}
int main() {
int a[] = { 4, 2, 1, 3, 6, 5, 7 };
myQuickSort(a, 0, 6);
for (int i = 0; i < 7; i++)
cout << a[i];
return 0;
}
移动主元
不同于辅导书上的两个指针的元素互换,这里使用的是类似于插入排序的过程,慢慢增长已经排好的数列。
在执行过程中一直满足这样的条件
- low~i之间都是比a[high]小的数,在j++过程中如果遇到比a[high]小的数,i++之后将其与a[i]交换即可
- i+1~j之间都是比a[high]大的数,在j++过程中如果遇到比a[high]大的数,不用处理,j直接++即可
当j = high-1时,即只差主元数没有纳入了,这是将主元数与a[i+1]交换即可完成
void mySwap(int a[], int x, int y) {
int temp = a[x];
a[x] = a[y];
a[y] = temp;
return;
}
int myPartition(int a[], int low, int high) { //以a[high]为主元,将a[high]换到这样一种位置,左边都是小于它的,右边都是大于它的
int temp = a[high];
int i = low - 1;
for (int j = low; j < high; j++) {
if (a[j] <= temp) { //只有遇到比temp小的数的时候,i往前移并且交换
i++;
mySwap(a, i, j);
}
}
mySwap(a, i + 1, high); //i+1的位置肯定是比temp要大,所以直接交换即可
return i + 1; //要返回这个mid的值,方便递归使用
}
递归主体
void myQuickSort(int a[], int low, int high) {
if (low < high) {
int mid = myPartition(a, low, high);
myQuickSort(a, low, mid - 1);
myQuickSort(a, mid + 1, high);
}
}