介绍
快速排序是对冒泡排序的一种改进。
思想:将排序的数据分为两部分,一部分数据所有数据小于另一部分所有数据,然后在分别进行快速排序,排序过程可递归,从而得到有序序列。
它使用分治法(Divide and conquer)策略,把一个串行分为两个子串行。
步骤
1. 从数列中选一个元素,作为“基准”(pivot);
2. 重新排序数列,比基准小的值在左边(left),大的值在右边(right),等值随意;得到两个子数列:left、right;
3. left子数列重复1和2;right子数列重复1和2;递归。
代码

/// <summary>
/// 一次排序单元,左边小,右边大
/// </summary>
/// <param name="array">排序数组</param>
/// <param name="left">排序起始位置</param>
/// <param name="right">排序结束位置</param>
/// <returns></returns>
private static int SortUnit(int[] array, int left, int right)
{
int pivot = array[left];
while (left < right)
{
// 从后向前搜索比 pivot 小的值
while (array[right] >= pivot && right > left)
{
--right;
}
// 比 pivot 小的放左边
array[left] = array[right];
// 从前向后搜索比 key 大的值
while (array[left] <= pivot && right > left)
{
++left;
}
// 比 pivot 大的放右边
array[right] = array[left];
}
// 左边都比 pivot 小,右边都比 pivot 大
// 将 pivot 放在游标当前位置。此时 left 等于 right
array[left] = pivot;
foreach (var i in array)
{
Console.Write("{0}\t", i);
}
Console.WriteLine();
return right;
}
/// <summary>
/// 左边小,右边大
/// </summary>
/// <param name="array">排序数组</param>
/// <param name="left">排序起始位置</param>
/// <param name="high">排序结束位置</param>
/// <returns></returns>
public static void QuickSort(int[] array, int left, int right)
{
if (left >= right)
return;
// 完成一次单元排序
int index = SortUnit(array, left, right);
// 对左边单元进行排序,递归
QuickSort(array, left, index - 1);
// 对右侧单元进行排序,递归
QuickSort(array, index + 1, right);
}
static void Main(string[] args)
{
#region 快速排序算法
int[] array = { 149, 100, 112, 38, 80, 35, 615, 297, 592, 976, 143, 217 };
QuickSort(array, 0, array.Length - 1);
Console.ReadLine();
#endregion
}
性能分析
算法复杂度
快速排序的性能高度依赖于选择的基准值。
最糟糕的:O(n ^ 2);
在最糟糕的情况下,栈长O(n),在调用栈的每层都涉及O(n)个元素,完成每层所需的时间都为O(n);O(n) * O(n) = O(n ^ 2);
最佳的:O(n log n);
在最佳的情况下,中间的元素作为基准值,栈长O(log n);每一层运行时间为O(n);O(n) * O(log n) = O(n log n);
平均的:O(n log n);
最佳即平均,只要每次都随机地选择一个数组元素作为基准值,快速排序的平均运行时间就将为O(n log n)。
快速排序是最快的排序算法之一。
