快速排序使用分治法(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; } } }