快速排序
快速排序采用的是分治策略: 在一个list中选择一个基准值(pivot value),将list中比基准值小的元素排在基准值的左侧,比基准值大的元素排在基准值的右侧,形成两个sub-list;然后对sub-list进行同样的操作,直至整个list排序完成。
Partition伪代码
// pseudocode of Partition function Partition(a, left, right) pivotIndex := (left + right) / 2; pivotValue := a[pivotValue]; storeIndex := left; for i from left to right-1 if a[i] < pivotValue swap(a[i], a[storeIndex]); storeIndex := storeIndex; swap(a[right], a[storeIndex]); return storeIndex;
pivotIndex有多种选择方式,这里采用list的中间index作为pivotIndex .
storeIndex是所有小于pivotValue的元素的后面一个index,每次交换就是a[storeIndex]和a[i].
Quicksort伪代码
// psedocode of Quicksort function Quicksort(a, left, right) if right > left pivotIndex := Partition(a, left, right); Quicksort(a, left, pivotIndex-1); Quicksort(a, pivotIndex+1, right);
寻找最小的k个数
与快速排序类似,仍然采用分治策略,不同的是,不必对每个sub-list都进行partition, 只对需要的sub-list进行partition。执行结束后,最小的k个数排在数组的前k个位置,但是,这k个数可能并没有经过排序。
算法导论第9章有该算法的实现:
代码:
template<typename Type> void my_swap(Type& a, Type& b) { Type tmp = a; a = b; b = tmp; } template<typename Type> int partition(Type* a, int left, int right) { int pivotIndex = (left + right)/2; int storeIndex = left; Type pivotValue = a[pivotIndex]; my_swap(a[pivotIndex], a[right]); for(int i = left; i < right; i++){ if(a[i] < pivotValue){ swap(a[i], a[storeIndex]); storeIndex ++; } } my_swap(a[storeIndex], a[right]); return storeIndex; } template<typename Type> void my_quick_sort(Type* a, int left, int right) { if(right > left){ int pivotIndex = partition(a, left, right); my_quick_sort(a, left, pivotIndex-1); my_quick_sort(a, pivotIndex+1, right); } } template<typename Type> void my_select(Type* a, int p, int r, int i) { if(p == r) return; int q = partition<Type>(a, p, r); int k = q - p + 1; if(i == k) return; else if(i < k) my_select(a, p, q-1, i); else my_select(a, q+1, r, i-k); }
[1] http://zh.wikipedia.org/zh-cn/%E5%BF%AB%E9%80%9F%E6%8E%92%E5%BA%8F
[2] 算法导论,第三版,第9章