一般情况下,快速排序是所有排序算法中最快的一个,它被应用在很多代码框架中。由C. A. R. Hoare提出,平均时间复杂度为Θ(n log n)。快速排序采用分而治之策略,将一个序列分隔成两个序列。算法描述在很多书上网上都找得到,简单点就是选择一个基准元素,然后将比它小的排在前面,比它大的放在后面,重复这一过程直到所有有序。算法的定义就是一个递归的描述。实现的关键点是选择一个合适的基准元素,因为如果选择不够好,选择到序列中最大或者最小的,算法退化为复杂Θ(n * n)。
伪代码
function partition(a, left, right, pivotIndex) pivotValue := a[pivotIndex] swap(a[pivotIndex], a[right]) // move pivot to end storeIndex := left for i from left to right-1 if a[i] < pivotValue swap(a[storeIndex], a[i]) storeIndex := storeIndex + 1 swap(a[right], a[storeIndex]) // move pivot to last position return storeIndex function quicksort(a, left, right) if right > left select a pivot value a[pivotIndex] pivotNewIndex := partition(a, left, right, pivotIndex) quicksort(a, left, pivotNewIndex-1) quicksort(a, pivotNewIndex+1, right)
非递归的实现方法借用堆栈实现,栈和队列是消除递归的常用方法。C#实现代码如下,C++、Java改写也很容易,因为C++、Java也提供了栈这一容器。
using System; using System.Collections.Generic; using System.Text; namespace QuickSort { class Program { public static void Main(string[] args) { int[] arr = { 4, 3,2, 1, -1, 99, 12, 33, 99, 10}; q_sort(ref arr); foreach (int i in arr) { Console.WriteLine(i); } } public static void q_sort(ref int[] input) { System.Collections.Stack stack = new System.Collections.Stack(); int pivot; int pivotIndex = 0; int leftIndex = pivotIndex + 1; int rightIndex = input.Length - 1; stack.Push(pivotIndex);//Push always with left and right stack.Push(rightIndex); int leftIndexOfSubSet, rightIndexOfSubset; while (stack.Count > 0) { rightIndexOfSubset = (int)stack.Pop();//pop always with right and left leftIndexOfSubSet = (int)stack.Pop(); leftIndex = leftIndexOfSubSet + 1; pivotIndex = leftIndexOfSubSet; rightIndex = rightIndexOfSubset; pivot = input[pivotIndex]; if (leftIndex > rightIndex) continue; while (leftIndex < rightIndex) { while ((leftIndex <= rightIndex) && (input[leftIndex] <= pivot)) leftIndex++; //increment right to find the greater //element than the pivot while ((leftIndex <= rightIndex) && (input[rightIndex] >= pivot)) rightIndex--;//decrement right to find the //smaller element than the pivot if (rightIndex >= leftIndex) //if right index is //greater then only swap SwapElement(ref input, leftIndex, rightIndex); } if (pivotIndex <= rightIndex) if( input[pivotIndex] > input[rightIndex]) SwapElement(ref input, pivotIndex, rightIndex); if (leftIndexOfSubSet < rightIndex) { stack.Push(leftIndexOfSubSet); stack.Push(rightIndex - 1); } if (rightIndexOfSubset > rightIndex) { stack.Push(rightIndex + 1); stack.Push(rightIndexOfSubset); } } } private static void SwapElement(ref int[] arr, int left, int right) { int temp = arr[left]; arr[left] = arr[right]; arr[right] = temp; } } }
递归版本的实现跟我们通常接触的算法描述一样的。是一个STL的实现版本,关于STL推荐侯捷的《STL源码剖析》。
#include <functional> #include <algorithm> #include <iterator> template< typename BidirectionalIterator, typename Compare > void quick_sort( BidirectionalIterator first, BidirectionalIterator last, Compare cmp ) { if( first != last ) { BidirectionalIterator left = first; BidirectionalIterator right = last; BidirectionalIterator pivot = left++; while( left != right ) { if( cmp( *left, *pivot ) ) { ++left; } else { while( (left != right) && cmp( *pivot, *right ) ) right--; std::iter_swap( left, right ); } } if (cmp( *pivot, *left )) --left; std::iter_swap( first, left ); quick_sort( first, left, cmp ); quick_sort( right, last, cmp ); } } template< typename BidirectionalIterator > inline void quick_sort( BidirectionalIterator first, BidirectionalIterator last ) { quick_sort( first, last, std::less_equal< typename std::iterator_traits< BidirectionalIterator >::value_type >() ); }