排序算法總結

一、概述

排序算法概念

在計算機科學與數學中,一個排序算法是將一組雜亂無章的數據按一定的規律順次排列起來的算法。排序的目的是便于查找。

衡量排序算法好壞的三個重要依據

  • 時間效率,即排序的速度,用時間復雜度來描述算法的運行時間。
  • 空間效率,即占內存輔助空間的大小,用空間復雜度來描述算法占用額外空間的大小。
  • 穩定性,若兩個記錄A和B的關鍵字值相等,但排序后A、B的先后次序保持不變,則稱這種排序算法是穩定的。不穩定排序算法可能會在相等的鍵值中改變紀錄的相對次序,在這個狀況下,有可能產生不同的排序結果。

內部排序與外部排序

若待排序記錄都在內存中,則稱為內部排序。若待排序記錄一部分在內存,一部分在外存,則稱為外部排序。

按排序的規則不同,內部排序可分為5類:

  • 插入排序(直接插入排序、折半插入排序、希爾排序),其基本思想是每步將一個待排序的對象,按其關鍵碼大小,插入到前面已經排好序的一組對象的適當位置上,直到對象全部插入為止。簡言之,邊插入邊排序,保證子序列中隨時都是排好序的。

  • 交換排序(冒泡排序、快速排序),其基本思想是兩兩比較待排序記錄的關鍵碼,如果發生逆序(即排列順序與排序后的次序正好相反),則交換之,直到所有記錄都排好序為止。

  • 選擇排序(簡單選擇排序,堆排序),其基本思想是在待排序的序列中依次選擇關鍵字最?。ɑ蜃畲螅┑脑刈鳛橛行蛐蛄械淖詈笠粋€元素,直至全部記錄選擇完畢。

  • 歸并排序

  • 基數排序

按排序算法的時間復雜度不同,內部排序可分為3類:

  • 簡單的排序算法:時間效率低,$O(n^2)$
  • 先進的排序算法:時間效率高,$O(nlog_2n)$
  • 基數排序算算法:時間效率高,$O(d \times n)$

二、常見排序算法

1、直接插入排序

基本思想

在已形成的有序表中線性查找,并在適當位置插入,把原來位置上的元素向后順移。

算法描述

設關鍵字數組為a[0…n-1]。

  1. 初始時,a[0]自成1個有序區,無序區為a[1..n-1]。令i=1

  2. 將a[i]并入當前的有序區a[0…i-1]中形成a[0…i]的有序區間。

  3. i++,并重復第二步直到 i==n-1,排序完成。

如待排序序列 T =(20,16,31,23,19,32,85,0),直接插入排序的中間過程為:

【20】,16,31,23,19,32,85,0

【16,20】,31,23,19,32,85,0

【16,20,31】,23,19,32,85,0

【16,20,23,31】,19,32,85,0

【16,19,20,23,31】,32,85,0

【16,19,20,23,31,32】,85,0

【16,19,20,23,31,32,85】,0

【0,16,19,20,23,31,32,85】

算法分析

  • 若設待排序的對象個數為 n,則算法需要進行 n-1 次插入。

  • 最好情況下,排序前對象已經按關鍵碼大小從小到大有序,每趟只需與前面的有序對象序列的最后一個對象的關鍵碼比較 1 次,移動 2 次對象。因此,總的關鍵碼比較次數為 n-1,對象移動次數為 2(n-1)。

  • 最壞情況下,第 i 趟插入時,第 i 個對象必須與前面 i-1 個對象都做關鍵碼比較,并且每做 1 次比較就要做 1 次數據移動。則總的關鍵碼比較次數 CN 和對象移動次數 MN 分別為

CN = \sum_{i=1}^{n-1}i={n(n-1)}/2 \approx {n^2}/2

MN = \sum_{i=1}^{n-1}(i+2) = {(n+4)(n-1)}/2 \approx {n^2}/2
  • 若待排序對象序列中出現各種可能排列的概率相同,則可取上述最好情況和最壞情況的平均情況。在平均情況下的關鍵碼比較次數和對象移動次數約為 $n^2/4$。因此,直接插入排序的時間復雜度為 $O(n^2)$。

  • 直接插入排序是一種穩定的排序方法。

算法實現

public static void InsertSort(int[] data) 
{
    int i, j;
    int count = data.Length;
    
    for (i = 1; i < count; i++) 
    {
        int t = data[i];
        for(j = i - 1; j >= 0 && data[j] > t; j--)
        {
            data[j + 1] = data[j];
        }
            
        data[j + 1] = t;
    }
}

2、折半插入排序

基本思想

在已形成的有序表中折半查找,并在適當位置插入,把原來位置上的元素向后順移。

算法描述:

在將一個新元素插入已排好序的數組的過程中,尋找插入點時,將待插入區域的首元素設置為a[low],末元素設置為a[high],則輪比較時將待插入元素與a[m],其中m=(low+high)/2相比較,如果比參考元素大,則選擇a[low]到a[m-1]為新的插入區域(即high=m-1),否則選擇a[m+1]到a[high]為新的插入區域(即low=m+1),如此直至low<=high不成立,即將此位置之后所有元素后移一位,并將新元素插入a[high+1]。

算法分析:

  • 折半插入排序是直接插入排序的改進,比較的次數大大減少,全部元素比較次數僅為 $O(nlog_2n)$;

  • 算法的平均時間復雜度為 $O(n^2)$,雖然比較次數大大減少,但移動次數并未減少;

  • 在最好情況下,即待排記錄序列已經是從小到大排好順序時,其時間復雜度為 $O(n)$

  • 當待排記錄基本有序或待排序序列的元素個數 n 很小時,算法的效率也比較高。

  • 空間復雜度為 $O(1)$;

  • 折半插入排序是一種穩定的排序方法。

算法實現:

public static void BinaryInsertSort(int[] data)
{
    for (int i = 1; i < data.Length; i++)
    {
        int low = 0;
        int high = i - 1;
        int tmp = data[i];

        while (low <= high)
        {
            int mid = (low + high) / 2;

            if (data[i] > data[mid])
            {
                low = mid + 1;
            }
            else
            {
                high = mid - 1;
            }
        }

        for (int j = i; j > low; j--)
        {
            data[j] = data[j - 1];
        }

        data[low] = tmp;
    }
}

3、希爾排序

基本思想

希爾排序,又稱縮小增量排序,是插入排序的一種更高效的改進版本。其基本思想是對待排記錄序列先作“宏觀”調整,再作“微觀”調整。所謂“宏觀”調整,指的是,“跳躍式”的插入排序。具體做法為:將記錄序列分成若干子序列,分別對每個子序列進行插入排序。

例如:將 n 個記錄{R[1]…R[n]}分成 d 個子序列:

{ R[1],R[1+d],R[1+2d],…,R[1+kd] }

{ R[2],R[2+d],R[2+2d],…,R[2+kd] }

...

{ R[d],R[2d],R[3d],…,R[kd],R[(k+1)d] }

其中,d 稱為增量,它的值在排序過程中從大到小逐漸縮小,直至最后一趟排序減為 1。

希爾排序示例:關鍵字序列 T=(49,38,65,97, 76, 13, 27, 49*,55, 04),請寫出希爾排序的具體實現過程。

希爾排序的實現

取定步長序列,如dk=5,3,1。

對每一步長dk,重復執行如下過程:

把每一子序列第一個元素看成是有序的,對后面的每一個元素r[i],重復執行如下過程:

把r[i]暫存在第0號單元;

尋找相應子序列中應該插入的位置:從后向前依次比較相應子序列中的元素,直到找到不大于r[i]的元素。

把r[i]放到適當的位置。

希爾排序算法分析

時間效率:
當增量序列為$d(k)=2^{t-k+1}-1$時,時間復雜度為$O(n^{1.5})$

空間效率:$O(1)$

算法的穩定性: 不穩定

初始: (49,38,65,97, 76, 13, 27, 49*,55, 04)

結束: (04,13,27,38, 49*, 49, 55, 65,76, 97)

4、冒泡排序

基本思想

每趟不斷將記錄兩兩比較,并按“前小后大”(或“前大后小”)規則交換。

算法描述

待排序序列 T=(21,25,49,25*,16,08),冒泡排序的排序過程為:

初態: 21,25,49, 25*,16, 08

第1趟: 21,25,25*,16, 08 , 49

第2趟: 21,25, 16, 08 ,25*,49

第3趟: 21,16, 08 ,25, 25*,49

第4趟: 16,08 ,21, 25, 25*,49

第5趟: 08,16, 21, 25, 25*,49

算法分析

  • 每趟結束時,不僅能擠出一個最大值到最后面位置,還能同時部分理順其他元素;一旦下趟沒有交換發生,還可以提前結束排序。

  • 時間效率:$O(n^2)$ —因為要考慮最壞情況

  • 空間效率:$O(1)$ ——只在交換時用到一個緩沖單元

  • 冒泡排序是一種穩定的排序方法,25和25*在排序前后的次序未改變

  • 最好情況下,即初始排列已經有序,只執行一趟起泡,做 n-1 次關鍵碼比較,不移動對象。

  • 最壞情況下, 即初始排列逆序,算法要執行 n-1 趟起泡,第 i 趟(1<= i< n) 做了n- i 次關鍵碼比較,執行了n-i 次對象交換。此時的比較總次數 CN 和記錄移動次數 MN 為:

CN = \sum_{i=1}^{n-1}{(n-i)}={n(n-1)}/2

MN = 3\sum_{i=1}^{n-1}(n-i) = 3n{(n-1)}/2

算法實現

/// <summary>
/// 冒泡排序
/// </summary>
/// <param name="data"></param>
public static void BubbleSort(int[] data)
{
    int temp = 0;
    bool swapped;

    for (int i = 0; i < data.Length; i++)
    {
        swapped = false;

        for (int j = 0; j < data.Length - 1 - i; j++)
        {
            if (data[j] > data[j + 1])
            {
                temp = data[j];
                data[j] = data[j + 1];
                data[j + 1] = temp;

                if (!swapped)
                {
                    swapped = true;
                }
            }
        }

        if (!swapped)
        {
            return;
        }
    }
}

5. 快速排序

基本思想

從待排序列中任取一個元素 (例如取中間值)作為中心,所有比它小的元素一律前放,所有比它大的元素一律后放,形成左右兩個子表;然后再對各子表重新選擇中心元素并依此規則調整,直到每個子表的元素只剩一個。此時便為有序序列了。

算法分析

  • 快速排序是一個不穩定的排序算法

  • 最大遞歸調用層次數與遞歸樹的深度一致,理想情況為 $log_2(n+1)$ ,要求存儲開銷為 $O(log_2n)$。

  • 如果每次劃分對一個對象定位后,該對象的左側子序列與右側子序列的長度相同,則下一步將是對兩個長度減半的子序列進行排序,這是最理想的情況。此時,快速排序的趟數最少。

  • 就平均計算時間而言,快速排序是我們所討論的所有內部排序方法中最好的一個。因為每趟可以確定的數據元素是呈指數增加的!
    設每個子表的支點都在中間(比較均衡),則:
    第1趟比較,可以確定1個元素的位置;
    第2趟比較(2個子表),可以再確定2個元素的位置;
    第3趟比較(4個子表),可以再確定4個元素的位置;
    第4趟比較(8個子表),可以再確定8個元素的位置;
    ……
    只需 $log_2n+1$ 趟便可排好序。而且,每趟需要比較和移動的元素也呈指數下降,加上編程時使用了交替逼近技巧,更進一步減少了移動次數,所以速度特別快。快速排序的平均排序效率為 $O(nlog_2n)$;

  • 在最壞的情況,排序效率仍為$O(n^2)$。即待排序對象序列已經按其關鍵碼從小到大排好序的情況下,其遞歸樹成為單支樹,每次劃分只得到一個比上一次少一個對象的子序列。這樣,必須經過 (n-1) 趟才能把所有對象定位,而且第 i 趟需要經過 (n-i) 次關鍵碼比較才能找到第 i 個對象的安放位置,總的關鍵碼比較次數將達到 $n^2/2$ 。

代碼實現

  • 每一趟的子表的形成是采用從兩頭向中間交替式逼近法;
  • 由于每趟中對各子表的操作都相似,主程序可采用遞歸算法。

以數組 data = {16, 20, 19, 20*, 11, 3} 作為示例,取子表中間元素作為基準。初始時數組如下:

index | 0 | 1 | 2 | 3 | 4 | 5
---|---|---|---|---|---|---|---
value | 16 | 20 | 19 | 20* | 11 | 3

此時,i = 0, j = 5, middle = data[(i + j) / 2] = 19, 將中間元素與第一個元素交換,數組變為:

index | 0 | 1 | 2 | 3 | 4 | 5
---|---|---|---|---|---|---|---
value | 19 | 20 | 16 | 20* | 11 | 3

采用從兩頭向中間交替式逼近法,首先,從索引 j 開始向前尋找一個小于等于 middle 的數,當 j = 5 時,符合條件,將 j=5 的值賦到索引 i 的值,i 做累加操作(即 data[0]=data[5]; i++),數組如下:

index | 0 | 1 | 2 | 3 | 4 | 5
---|---|---|---|---|---|---|---
value | 3 | 20 | 16 | 20* | 11 | 3

然后,再從索引 i (此時 i=1 )開始向后尋找一個大于等于 middle 的數,當 i = 1 時,符合條件,將索引 i=1 的值賦給索引 j 的值上,j 做累減操作(即 data[5]=data[1]; j--;),此時數組為

index | 0 | 1 | 2 | 3 | 4 | 5
---|---|---|---|---|---|---|---
value | 3 | 20 | 16 | 20* | 11 | 20

這時又從索引 j (此時 j=4)開始向前尋找一個小于等于 middle 的數,當 j=4 時,符合條件,將 j=4 的值賦到索引 i 的值,i 做累加操作(即 data[1]=data[4]; i++),數組如下:

index | 0 | 1 | 2 | 3 | 4 | 5
---|---|---|---|---|---|---|---
value | 3 | 11 | 16 | 20* | 11 | 20

此時 i=2, j=4, 又從索引 i 開始向后尋找一個大于等于 middle 的數,當 i=3 時,符合條件,將索引 i=3 的值賦到索引 j(j=4) 的值上,j 做累減操作(即 data[4]=data[3]; j--;),此時數組為

index | 0 | 1 | 2 | 3 | 4 | 5
---|---|---|---|---|---|---|---
value | 3 | 11 | 16 | 20* | 20* | 20

此時 i=3,j=3,即 i=j,剛將 middle 的值賦到索引為 3 的值上,數組變為

index | 0 | 1 | 2 | 3 | 4 | 5
---|---|---|---|---|---|---|---
value | 3 | 11 | 16 | 19 | 20* | 20

至此,排序第一趟結束,排序后的結果如下:

index | 0 | 1 | 2 | 3 | 4 | 5
---|---|---|---|---|---|---|---
初態 | 16 | 20 | 19 | 20* | 11 | 3
第一趟 | 3 | 11 | 16 | 19 | 20* | 20

可以看出第一趟排序后,data[3] 前面的數字都小于它,a[3] 后面的數字都大于它。再對各子表(a[0,1,2]和a[4,5]這二個子表)重新選擇中心元素并依此規則調整,直到每個子表的元素只剩一個,此時便為有序序列了。

C#代碼

/// <summary>
/// 快速排序
/// </summary>
/// <param name="data"></param>
public static void QuickSort(int[] data)
{
    QuickSort(data, 0, data.Length - 1);
}

/// <summary>
/// 快速排序,遞歸方式(采用從兩頭向中間交替式逼近法)
/// </summary>
/// <param name="data"></param>
/// <param name="left"></param>
/// <param name="right"></param>
private static void QuickSort(int[] data, int left, int right)
{
    if (left < right)
    {
        int midIndex = (left + right)/2;

        // 取中間元素作為基準
        int middle = data[midIndex];

        // 將中間元素與第一個元素交換
        int tmp = data[left];
        data[left] = data[midIndex];
        data[midIndex] = tmp;
        
        int i = left;
        int j = right;

        while (i < j)
        {
            while (data[j] >= middle && i < j)
            {
                j--;
            }

            if (i < j)
            {
                data[i++] = data[j];
            }

            while (data[i] < middle && i < j)
            {
                i++;
            }

            if (i < j)
            {
                data[j--] = data[i];
            }
        }

        data[i] = middle;

        QuickSort(data, left, i - 1);
        QuickSort(data, i + 1, right);
    }
}

6. 選擇排序

基本思想

在待排序的序列中依次選擇關鍵字最小(或最大)的元素作為有序序列的最后一個元素,直至全部記錄選擇完畢。

如待排序的序列 data = [47 38 25 17 16 12 25* 20 49],使用簡單選擇排序(選擇關鍵字最小的元素),其過程如下:

[47 38 25 17 16 12 25* 20 49]

12 [38 25 17 16 47 25* 20 49]

12 16 [25 17 38 47 25* 20 49]

12 16 17 [25 38 47 25* 20 49]

12 16 17 20 [38 47 25* 25 49]

12 16 17 20 25* [47 38 25 49]

12 16 17 20 25* 25 [38 47 49]

12 16 17 20 25* 25 38 [47 49]

12 16 17 20 25* 25 38 47 [49]

12 16 17 20 25* 25 38 47 49

12[47 38 25 17 16 12 20 49]
13[38 65 97 76 49 27 49]
13 27[65 97 76 49 38 49]
13 27 38[65 97 76 49 49]
13 27 38 49[65 97 76 49]
13 27 38 49 49[65 97 76]
13 27 38 49 49 65[97 76]
13 27 38 49 49 65 76 97

特點:

  1. 算法簡單, 時間復雜度為O(n2)
  2. 序列存儲:順序、鏈式
  3. 穩定
/// <summary>
/// 簡單選擇排序
/// </summary>
/// <param name="data"></param>
public static void SelectionSort(int[] data)
{
    for (int i = 0; i < data.Length - 1; i++)
    {
        int min = i;
        for (int j = i + 1; j < data.Length; j++)
        {
            if (data[min] > data[j])
            {
                min = j;
            }
        }

        if (min != i)
        {
            int tmp = data[min];
            data[min] = data[i];
            data[i] = tmp;
        }
    }
}

7. 堆排序

若有n個元素(a1,a2,a3,…,an),當滿足如下條件:
ai≤a2i ai≥a2i
(1) ai≤a2i+1 或 (2) ai≥a2i+1

其中i=1,2,…,?n/2?,則稱此n個元素a1,a2,a3,…,an為一個堆。

若將此元素序列按順序組成一棵完全二叉樹,則(1)稱為小根堆(二叉樹的所有根結點值小于或等于左右孩子的值),(2)稱為大根堆(二叉樹的所有根結點值大于或等于左右孩子的值)。


堆節點的訪問[編輯]
通常堆是通過一維數組來實現的。在數組起始位置為0的情形中:
父節點i的左子節點在位置(2i+1);
父節點i的右子節點在位置(2
i+2);
子節點i的父節點在位置floor((i-1)/2);
堆的操作[編輯]
在堆的數據結構中,堆中的最大值總是位于根節點(在優先隊列中使用堆的話堆中的最小值位于根節點)。堆中定義以下幾種操作:
最大堆調整(Max_Heapify):將堆的末端子節點作調整,使得子節點永遠小于父節點
創建最大堆(Build_Max_Heap):將堆所有數據重新排序
堆排序(HeapSort):移除位在第一個數據的根節點,并做最大堆調整的遞歸運算

原地堆排序[編輯]
基于以上堆相關的操作,我們可以很容易的定義堆排序。例如,假設我們已經讀入一系列數據并創建了一個堆,一個最直觀的算法就是反復的調用del_max()函數,因為該函數總是能夠返回堆中最大的值,然后把它從堆中刪除,從而對這一系列返回值的輸出就得到了該序列的降序排列。真正的原地堆排序使用了另外一個小技巧。堆排序的過程是:
創建一個堆H[0..n-1]
把堆首(最大值)和堆尾互換
把堆的尺寸縮小1,并調用shift_down(0),目的是把新的數組頂端數據調整到相應位置
重復步驟2,直到堆的尺寸為1
平均復雜度[編輯]
堆排序的平均時間復雜度為 {\displaystyle O(n\mathrm {log} n)} O(n\mathrm{log}n),空間復雜度為 {\displaystyle \Theta (1)} \Theta(1)。

96 50 85 45 17 31 63 24 17

8.歸并排序

歸并排序指的是將兩個或兩個以上的有序序列組合成一個新的有序序列操作。

2-路歸并排序

設初始序列含有n個記錄,則可看成n個有序的子序列,每個子序列長度為1。

兩兩合并,得到?n/2?個長度為2或1的有序子序列。

再兩兩合并,……如此重復,直至得到一個長度為n的有序序列為止。

時間復雜度:
T(n)=O(nlogn)

空間復雜度:
S(n)=O(n)

它是一個穩定的排序方法。

迭代法[編輯]

申請空間,使其大小為兩個已經排序序列之和,該空間用來存放合并后的序列
設定兩個指針,最初位置分別為兩個已經排序序列的起始位置
比較兩個指針所指向的元素,選擇相對小的元素放入到合并空間,并移動指針到下一位置
重復步驟3直到某一指針到達序列尾
將另一序列剩下的所有元素直接復制到合并序列尾

遞歸法[編輯]

原理如下(假設序列共有n個元素):
將序列每相鄰兩個數字進行歸并操作,形成 {\displaystyle floor(n/2)} floor(n/2)個序列,排序后每個序列包含兩個元素
將上述序列再次歸并,形成 {\displaystyle floor(n/4)} floor(n/4)個序列,每個序列包含四個元素
重復步驟2,直到所有元素排序完畢

三、總結

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,786評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,656評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,697評論 0 379
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,098評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,855評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,254評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,322評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,473評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,014評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,833評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,016評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,568評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,273評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,680評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,946評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,730評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,006評論 2 374

推薦閱讀更多精彩內容

  • 作者:大海里的太陽原文地址:http://www.cnblogs.com/wxisme/ 前言 查找和排序算法是算...
    IT程序獅閱讀 2,515評論 0 63
  • 題記: 直接插入排序(穩定)-->希爾排序 : 屬于插入排序 簡單選擇排序(穩定)-->堆排序 :屬于選擇排序...
    Pitfalls閱讀 2,820評論 2 3
  • 1.簡介插入排序(Insertion Sort)的算法描述是一種簡單直觀的排序算法。它的工作原理是通過構建有序序列...
    AngerCow閱讀 377評論 0 1
  • 大公司、小公司,各有各的好,看我們自己想要什么,正好又遇到了什么樣的機會。我在大公司呆過,也換過幾家小公司,從大小...
    曼詩閱讀 1,405評論 4 10
  • ;今天是小五班小朋友入學的第三天,較之以前兩天的撕心裂肺、驚天動地,今天算平靜很多,哭鬧的小朋友在減少,教學活動也...
    孫一女閱讀 714評論 0 0