快速排序
快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)。
算法步骤:
1 从数列中挑出一个元素,称为 “基准”(pivot),
2 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
3 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会退出,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。
实现一趟快速排序的逻辑可以参考:http://jingyan.baidu.com/article/d45ad148905ccf69552b80d9.html
算法关键的点是如何实现“所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面”,这个逻辑。
一趟排序:选取数组的左边第一个元素为基准元素,记录在一个变量里面,然后从右边第一个元素向左搜索,找到一个比基准小的元素j,放到基准元素的位置,这个时候之前j位置为空;再从左向右搜索比基准元素大的元素i,然后将i放到j的位置,最后i==j的时候,将原来记录好的基准元素放到这里,至此一趟排序就完成了。
C#实现:
namespace QuikSort { public class Program { public static void Main(string[] args) { int[] arr = { 6, 2, 7, 3, 8, 9, 1, 4, 9, 9, 3, 8, 0, 4, 2 }; QuikSort(arr, 0, arr.Length - 1); Console.Read(); } /// <summary> /// 快速排序算法 /// </summary> /// <param name="arr">需要排序的数组</param> /// <param name="startIndex">开始的索引</param> /// <param name="endIndex">结束的索引</param> private static void QuikSort(int[] arr, int startIndex, int endIndex) { if (startIndex >= endIndex) { return; } int balance = Partition( arr, startIndex, endIndex); //left QuikSort(arr, startIndex, balance - 1); //right QuikSort(arr, balance + 1, endIndex); } /// <summary> /// 实现一躺快速排序 /// </summary> /// <param name="arr">需要排序的数组</param> /// <param name="startIndex">开始的索引</param> /// <param name="endIndex">结束的索引</param> /// <returns></returns> private static int Partition( int[] arr, int startIndex, int endIndex) { //以第一个元素为平衡点 int balance = arr[startIndex]; while (startIndex < endIndex) { //从右往左搜索 while (arr[endIndex] >= balance && startIndex != endIndex) { endIndex--; } arr[startIndex] = arr[endIndex]; //从左往右搜索 while (arr[startIndex] <= balance && startIndex != endIndex) { startIndex++; } arr[endIndex] = arr[startIndex]; } arr[startIndex] = balance; return startIndex; } } }