排序---快速排序

1、概念html

快速排序由C.A.R.Hoare在1962年提出,是冒泡排序的一種改進。其基本思想爲:經過一趟排序將待排序數據分割成獨立的兩部分,其中一部分的全部值都比另外一部分的全部值都小,而後再對分割的兩部分分別進行快速排序,整個過程能夠遞歸進行,最終全部數據變爲有序序列。算法

2、算法要點數組

假設待排序數組爲a[0], a[1],…a[n-1],快速排序步驟如下:dom

一、初始化兩個變量i、j,剛開始i = 1,j=n-1。oop

二、將第一個元素a[0]做爲基準數。ui

三、從i開始向後搜索,找到第一個大於基準數的元素a[i]。spa

四、從j開始向前搜索,找到第一個小於等於基準數的元素a[j]。code

五、將a[i]與a[j]互換。htm

六、重複3到5步驟,直到i = j + 1,此時,j指向的元素是最後一個(從左邊算起)小於等於中軸的元素,而後將a[0]與a[j]對換。blog

七、序列被基準數分割成兩個分區,前面分區所有小於等於基準數,後面分區所有大於基準數。

八、遞歸對分區子序列進行快速排序,最終完成整個排序工做。

每趟快速排序的核心工做是:

選一個元素做爲基準數,而後將全部比它小的數都放到它前面,大於它的數都放在它後面。

3、算法實現

實現一:

 1 using System;
 2 using System.Collections.Generic;
 3 
 4 namespace QuickSort
 5 {
 6     class Program
 7     {
 8         static void Main(string[] args)
 9         {
10             QuickSortUnitTest(13);
11 
12         }
13         private static void QuickSort(List<int>dataList, int left, int right)
14         {
15             if(left < right)//遞歸的邊界條件,當left等於right時,元素個數爲1個
16                 {
17                 int pivot = dataList[left];//最左邊的元素做爲中軸
18                 int i = left + 1;
19                 int j = right;
20                 int tmp = 0;
21                 //當i == j時,i和j同時指向的元素尚未與中軸元素判斷,
22                 //小於等於中軸元素,i++,大於中軸元素j--,
23                 //當循環結束時,必定有i = j + 1, 且i指向的元素大於中軸,j指向的元素小於等於中軸
24                 while (i <= j)
25                 {
26                     while(i <= j && dataList[i] <= pivot)//從前向後找到第一個大於pivot的元素
27                     {
28                         i++;
29 
30                     }
31                     while(i <= j && dataList[j] > pivot)
32                     {
33                         j--;
34 
35                     }
36                     if(i < j)
37                     {
38                         tmp = dataList[i];
39                         dataList[i] = dataList[j];
40                         dataList[j] = tmp;
41                     }                    
42                 }
43                 //當循環結束時,j指向的元素是最後一個(從左邊算起)小於等於中軸的元素
44                 //將中軸元素和j所指的元素互換
45                 tmp = dataList[left];
46                 dataList[left] = dataList[j];
47                 dataList[j] = tmp;
48                 Console.WriteLine();
49                 foreach (var item in dataList)
50                 {
51                     Console.Write($" {item} ");
52                 }
53                 Console.WriteLine();
54                 QuickSort(dataList, left, j - 1);
55                 QuickSort(dataList, j + 1  , right);
56             }
57         }
58         private static void QuickSortUnitTest(int loopNum)
59         {
60             Random random = new Random();
61             List<int> dataList = new List<int>();
62             for (int i = 0; i < loopNum; i++)
63             {
64                 dataList.Add(random.Next(100));
65             }
66             Console.Write("Original data:");
67             foreach(var item in dataList)
68             {
69                 Console.Write($" {item} ");
70             }
71 
72             QuickSort(dataList, 0, dataList.Count - 1);
73             Console.Write("Quick sorted data:");
74 
75             foreach (var item in dataList)
76             {
77                 Console.Write($" {item} ");
78             }
79             Console.WriteLine();
80         }
81     }
82 }

 實現二:

基本思想:「挖坑填坑」

使用兩個變量i和j分別指向最左邊和最右邊的元素,咱們將首元素做爲中軸,並複製到變量pivot中,這時咱們能夠將首元素i所在的位置當作一個坑,咱們從j的位置從右向左掃描,找一個小於等於中軸

的元素A[j],來填補A[i]這個坑,填補完成後,拿去填坑的元素所在的位置j又能夠看作一個坑,這時咱們在以i的位置從前日後找一個大於中軸的元素來填補A[j]這個新的坑,如此往復,直到

i和j相遇(i == j,此時i和j指向同一個坑)。

最後咱們將中軸元素放到這個坑中。而後,咱們按照相同的方法分別對左右兩個數組執行相同的操做。

private static void QuickSort2(List<int>dataList, int left, int right)
        {
            if(left < right)
            {
                //最左邊的元素做爲中軸複製到pivot,這時最左邊的元素能夠看作一個坑
                int pivot = dataList[left];
                //注意這裏 i = L,而不是 i = L+1, 由於i表明坑的位置,當前坑的位置位於最左邊
                int i = left;
                int j = right;
                while(i < j)
                {
                    //下面面兩個循環的位置不能顛倒,由於第一次坑的位置在最左邊
                    while (i < j && dataList[j] > pivot)
                    {
                        j--;
                    }
                    //填A[i]這個坑,填完後A[j]是個坑

                    //注意不能是A[i++] = A[j],當因i==j時跳出上面的循環時

                    //坑爲i和j共同指向的位置,執行A[i++] = A[j],會致使i比j大1,

                    //但此時i並不能表示坑的位置 
                    dataList[i] = dataList[j];
                    while(i < j && dataList[i] <= pivot)
                    {
                        i++;
                    }
                    dataList[j] = dataList[i];
                }
                //循環結束後i和j相等,都指向坑的位置,將中軸填入到這個位置
                dataList[i] = pivot;
                QuickSort2(dataList, left, i - 1);
                QuickSort2(dataList, i + 1, right);
               

            }
        }

 更多方法請參考:

http://www.javashuo.com/article/p-qqxterok-gm.html

相關文章
相關標籤/搜索