快速排序(Quicksort)是对冒泡排序的一种改进。由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)。
步骤为:
- 从数列中挑出一个元素,称为 "基准"(pivot),(定基准,有随机版本)
- 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作(分割操作)
- 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。(递归实现)
递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会退出,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。
从别人的博客里知道了三种版本的快排。
代码一:霍尔快排
/* * Author: Tanky Woo * Blog: www.WuTianQi.com * Note: 快速排序版本1 --- Hoare-Partition */ #include <iostream> using namespace std; int num; void swap(int &a, int &b) { int temp = a; a = b; b = temp; } void PrintArray(int *arr) { for(int i=1; i<=num; ++i) cout << arr[i] << " "; cout << endl; } int Partition1(int *arr, int beg, int end) { int low = beg, high = end; int sentinel = arr[beg]; while(low < high) { while(low<high && arr[high]>=sentinel) --high; arr[low] = arr[high]; while(low<high && arr[low]<=sentinel) ++low; arr[high] = arr[low]; } arr[low] = sentinel; cout << "排序过程:"; PrintArray(arr); return low; } void QuickSort(int *arr, int beg, int end) { if(beg < end) { int pivot = Partition1(arr, beg, end); QuickSort(arr, beg, pivot-1); QuickSort(arr, pivot+1, end); } } int main() { int arr[100]; cout << "Input the num of the elements: "; cin >> num; cout << "Input the elements: "; for(int i=1; i<=num; ++i) cin >> arr[i]; QuickSort(arr, 1, num); cout << "最后结果:"; PrintArray(arr); return 0; }
代码二:算法导论当中的快排
/* * Author: Tanky Woo * Blog: www.WuTianQi.com * Note: 快速排序版本2---《算法导论》 */ #include <iostream> using namespace std; int num; void swap(int &a, int &b) { int temp = a; a = b; b = temp; } void PrintArray(int *arr) { for(int i=1; i<=num; ++i) cout << arr[i] << " "; cout << endl; } int Partition2(int *arr, int beg, int end) { int sentinel = arr[end]; int i = beg-1; for(int j=beg; j<=end-1; ++j) { if(arr[j] <= sentinel) { i++; swap(arr[i], arr[j]); } } swap(arr[i+1], arr[end]); cout << "排序过程:"; PrintArray(arr); return i+1; } void QuickSort(int *arr, int beg, int end) { if(beg < end) { int pivot = Partition2(arr, beg, end); QuickSort(arr, beg, pivot-1); QuickSort(arr, pivot+1, end); } } int main() { int arr[100]; cout << "Input the num of the elements: "; cin >> num; cout << "Input the elements: "; for(int i=1; i<=num; ++i) cin >> arr[i]; QuickSort(arr, 1, num); cout << "最后结果:"; PrintArray(arr); return 0; }
随机化快排:
/* * Author: Tanky Woo * Blog: www.WuTianQi.com * Note: 快速排序版本3 --- 随机化版本 * 解决待排序元素相差很大的情况 */ #include <iostream> #include <cstdlib> using namespace std; int num; void swap(int &a, int &b) { int temp = a; a = b; b = temp; } void PrintArray(int *arr) { for(int i=1; i<=num; ++i) cout << arr[i] << " "; cout << endl; } int Partition3(int *arr, int beg, int end) { int sentinel = arr[end]; int i = beg-1; for(int j=beg; j<=end-1; ++j) { if(arr[j] <= sentinel) { i++; swap(arr[i], arr[j]); } } swap(arr[i+1], arr[end]); cout << "排序过程:"; PrintArray(arr); return i+1; } int RandomPartition(int *arr, int beg, int end) { int i = beg + rand() % (end-beg+1); swap(arr[i], arr[end]); return Partition3(arr, beg, end); } void RandomQuickSort(int *arr, int beg, int end) { if(beg < end) { int pivot = RandomPartition(arr, beg, end); RandomQuickSort(arr, beg, pivot-1); RandomQuickSort(arr, pivot+1, end); } } int main() { int arr[100]; cout << "Input the num of the elements: "; cin >> num; cout << "Input the elements: "; for(int i=1; i<=num; ++i) cin >> arr[i]; RandomQuickSort(arr, 1, num); cout << "最后结果:"; PrintArray(arr); return 0; }
随机化的快排一般适用于待排序的数据之间相差较大的情况下。
模版:
1 /* 2 快速排序:模版 3 */ 4 5 #include <iostream> 6 using namespace std; 7 8 9 void swap(int *a, int *b) 10 { 11 int temp = *a; 12 *a = *b; 13 *b = temp; 14 } 15 16 int Partition(int *arr, int beg, int end) 17 { 18 int sentinel = arr[end]; 19 int i = beg-1; 20 for(int j=beg; j<=end-1; ++j) 21 { 22 if(arr[j] <= sentinel) 23 { 24 i++; 25 swap(&arr[i], &arr[j]); 26 } 27 } 28 swap(&arr[i+1], &arr[end]); 29 return i+1; 30 } 31 32 void QuickSort(int *arr, int beg, int end) 33 { 34 if(beg < end) 35 { 36 int pivot = Partition(arr, beg, end); 37 QuickSort(arr, beg, pivot-1); 38 QuickSort(arr, pivot+1, end); 39 } 40 }