1. 程式人生 > >簡單選擇排序和直接插入排序

簡單選擇排序和直接插入排序

當前 出現 一個數 堆排 逆序 排好序 int swa 數據對比

簡單選擇排序

簡單選擇排序就是通過關鍵字之間的比較,在記錄裏面找到最小(或者最大)的數字,並同當前位置交換之。

貼個代碼:

void SelectSort(SqList *L)
{
    int i, j, min;
    for (i = 0; i < L->length - 1; i++)
    {
        min = i;
        for (j = i + 1; j < L->length; j++)
        {   
            if (L->r[min] > L->r[j])
            {
                 min 
= j; } } if (i != min) swap(L, i, min); } }

分析一下:很顯然,對於一個無序數組來說,把第一個數的下標暫且作為值最小的下標,然後通過與其後的數據對比,找出真正的最小的數組的下標,如果找到,就交換,如果沒找到,說明當前數據是最小的,那麽就不用交換。然後下標遞增,再次比較。就這樣實現排序。

復雜度分析:

我們知道,交換最多需要n - 1次(最少需要0次)。而第i次排序需要n - i 次比較,那麽總共有 (n - 1) + (n - 2) + (n - 3) +..... + 1 = n * (n - 1) / 2次比較,顯然時間復雜度就是O(n ^ 2)(但是比起冒泡排序來說,簡單選擇的性能還是要比冒泡好一點。

直接插入排序

直接插入排序,就是將一個記錄插入到已經排好序的有序表中,從而得到一個新的有序表。

先給出代碼,稍後分析:

void InsertSort(SqList *L)
{
    int i, j;
    for (i = 2; i < L->length; i++)  //下標從2開始。
    {
        if ( L->r[i] < L->r[i - 1])
        {
            L->r[0] = L->r[i];
            for (j = i - 1; L->r[j] > L->r[0
]; j--) L->r[j + 1] = L->r[j]; L->r[j + 1] = L-> r[0]; //註意上面有j--,所以這裏空出來的位置應該是j + 1 } }

代碼分析:如上(升序排序),我們舉個栗子,有一個無序數組{5, 3, 2, 4 , 6},現在要把它給拍好,怎麽做呢?

首先,我們把r[1] = 5當作是有序的一個數組(這裏的L->r[0]必須要空出來當哨兵),即:{ 5 };那麽現在我們需要將剩下的{3, 2, 4, 6}插入到{5}這個有序表中,顯然現在的問題就是插入到5左邊還是右邊了,為此,下標從2開始,循環比較兩兩之間的大小,如果後者比前者小,那麽就把後者的值賦值給哨兵,再把前者適當的往後移動(這裏的適當是有條件的,也就是L->r[j] > L->r[0],即到出現比哨兵小的數據為止)。移動完之後再把哨兵的值賦值給移動出來的空位。

復雜度分析:如果要排序的數組一開始就是有序的,那麽只需要比較次數,時間復雜度為O(n),而最壞的情況(數組完全逆序),那麽這個時候,當外循環等於2(總共執行n - 2次)時,內循環執行了n - 1次,當外循環等於3時,執行了n - 2次。。。。。。所以,總的執行次數為 n - 2 + n - 3 + ....+ 1 = ( n-1) * (n - 2) / 2,也就是O(n^2)。雖然是平方階,但是它的性能比冒泡和簡單選擇要好的多。

以上。

下次寫希爾排序和堆排序

簡單選擇排序和直接插入排序