快速排序
oo
和归并排序一样, 快速排序也使用了分治思想(Divide & Conquer)
对一个数组进行快速排序, 通常分为三个步骤:
1. 分解: 数组a[p to r]被划分为两个可能为空的子数组a[p to q-1]和a[q to r], 使得a[p to q-1]中的每一个元素都<=a[q], 而a[q]也小于等于a[q+1 to r]中的每一个元素
2. 解决: 通过递归调用快速排序, 对子数组a[p to q-1]和a[q to r]进行排序.
3. 合并: 因为子数组是原址排序的, 所以不需要合并操作. 数组已经有序
快速排序中, 最核心的部分就是partition子过程: (假定采用升序排列)
首先以传入数组的最后一个元素为主元(pivot element), 从头遍历数组直到倒数第二个元素, 找到比pivot小的元素, 并且用一个计数器变量m来记录这种元素的个数. 每次遇到这种元素, 都把它交换到这列数组的第m位(相对位置), 并增加m.
结束遍历之后, 把第m位和最末位元素交换, 这样第m位左边的元素都比它小, 右边的元素都比它大(或等于). 返回第m位元素的绝对位置.
执行完partition操作, pivot element的”排名”就确定下来了, 永远不会再动.
我们再假设子数组的起始下标为from, 终止下标为to, 那么第m位元素的实际下标为from+m
附: 完整代码
#include <iostream> #include <algorithm> #include <cstdio> #include <stack> #include <ctime> using namespace std; void quicksort(int* a, int from, int to); void quicksort(int* a, int length); int partition(int* a, int from, int to); void quicksort(int* a, int from, int to) { if (from<to) { int pivot = partition(a, from, to); quicksort(a, from, pivot-1); quicksort(a, pivot+1, to); } } void quicksort(int* a, int length) { return quicksort(a,0,length-1); } int partition(int* a, int from, int to) { int x = a[to]; int i = from; for(int j = from; j<=to-1; ++j) { if (a[j]<=x) { swap(a[i],a[j]); ++i; } } swap(a[i],a[to]); return i; } int main() { int i[25] = {}; srand(time(0)); for (int k=0;k<25;++k) i[k] = rand()%103; quicksort(i,25); for(int j = 0; j<25; j++) { printf("%d ",i[j]); } }