参考:《漫画算法-小灰的算法之旅》
目录
1、快速排序算法的思想
快速排序算法使用了分治法的思想,在每一轮挑选一个基准元素,并让其他比它大的元素移动到数列的一边,从而把数列拆成两个部分。
2、快速排序法的流程
每一轮的比较和交换,需要把数组全部元素都遍 历一遍,时间复杂度是O(n)。这样的遍历一共需要 多少轮呢?假如元素个数是n,那么平均情况下需要 logn轮,因此快速排序算法总体的平均时间复杂度是 O(nlogn)。
3、基准元素的选择
选择基准元素最简单的方式就是选择数列的第一个元素。醉着选择在绝大多数情况下是没有问题的。但是当一个数列是逆序时,每一轮只能确定基准元素的位置。此时(最坏的情况)的时间复杂是O(n^2)。为了避免这种情况的发生,可以随机选择一个元素作为基准元素,并让基准元素和数列首元素交换位置。
4、元素的交换(此处只介绍单边循环法)
原始数列如上所示,对其从小到大进行排序。首先选定一个基准元素pivot。同时设置一个mark指针指向数列起始位置,这个mark指针代表小于基准元素的区域边界。
从基准元素的下一个位置开始遍历数组,如果遍历的元素大于基准元素,就继续往后遍历。如果遍历到的元素小于基准元素,则需要做两件事:第一,把mark指针右移1位,因为小于pivot的区域边界增大了1;第二,让最新遍历到的元素和mark指针所在位置的元素交换位置,因为最新遍历的元素归属于小于pivot的区域。
5、快速排序代码
using namespace std;
#include<iostream>
#include<string>
int partition(int arr[], int startIndex, int endIndex) {
//取第一个位置的元素作为基元素
int pivot = arr[startIndex];
int mark = startIndex;
for (int i = startIndex + 1; i <= endIndex; i++) {
if (arr[i] < pivot) {
mark = mark + 1;
int p = arr[mark];
arr[mark] = arr[i];
arr[i] = p;
}
}
arr[startIndex] = arr[mark];
arr[mark] = pivot;
return mark;
}
void quickSort(int arr[], int startIndex, int endIndex) {
//递归结束条件:startIndex>= endIndex
if (startIndex >= endIndex) {
return;
}
//得到基准元素的位置
int pivotIndex = partition(arr, startIndex,endIndex);
quickSort(arr, startIndex, pivotIndex-1);
quickSort(arr, pivotIndex + 1, endIndex);
}
int main()
{
int arr[] = { 4, 4, 6, 5, 3, 2, 8, 1 };
int endIndex = sizeof(arr) / sizeof(arr[0])-1;
quickSort(arr, 0, endIndex);
for (int i = 0; i <= endIndex; i++) {
cout << arr[i] << endl;
}
system("pause");
return 0;
}