快速排序

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

    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章