1. 程式人生 > >排序演算法--兩種選擇排序

排序演算法--兩種選擇排序

    選擇排序是一種以重複選擇為思想的排序演算法.其中直接選擇排序是最簡單的一種.

直接選擇排序:

演算法:

    假設有一個A[n]的陣列,首先找到最小的元素,將其儲存在A[1]中,然後找到剩下的n - 1個元素中的最小元素,放在A[2]中,重複此過程直到找到第二大的元素.

程式碼:

#include <stdio.h>

constint MAX =10;

void selectionSort(int*A)
{
    
int i, j, k, temp;
    
for(i =0; i < MAX -1; i++)
    
{
        k 
= i;
        
for(j = i +1; j < MAX; j++)
            
if(A[j] < A[k])
                k 
= j;
        
if(k != i)
        
{
            temp 
= A[k];
            A[k] 
= A[i];
            A[i] 
= temp;
        }

    }

}



int main()
{
    
int A[MAX];
    
int i;
    
int nums = MAX;
    printf(
"Please input %d numbers: ", nums);
    
for(i =0; i < MAX; i++)
        scanf(
"%d"&A[i]);
    selectionSort(A);
    
for(i =0; i < MAX; i++)
        printf(
"%d ", A[i]);
    
return0;
}

    可以看出元素交換的最小次數是0,最大是n - 1.同時交換過程中的元素賦值次數介於0與3(n - 1)之間,還有關鍵字的比較次數,均為n(n - 1) / 2,所以演算法的時間複雜度為O(n2).

    選擇排序的主要操作是元素之間的關鍵字比較.因此,改進直接選擇排序可以從減少比較的次數入手.

    有這樣的一個定理:

    任何以比較元素對偶為基礎的在n個元素中尋找極大者的演算法,必須至少做n - 1次的比較.(<<計算機程式設計藝術>>)

    不過仔細思考一下就可以明白,這個定理僅適用於頭一個選擇步驟.我們可以用模仿體育比賽選拔的方式來改進直接選擇演算法,既隨後的選擇可以用頭一次選擇後產生資訊來進行.

錦標排序:

    錦標排序又叫樹型選擇排序,通過這個名字可以清楚的理解到錦標排序的樣子.

演算法:

    我們可以用有n個葉子節點的滿二叉樹來組織這個演算法.

    首先讓元素兩兩之間進行比賽,當葉子節點的優勝者向上一個分枝移動以後,用一個特殊的標誌位來代替原來它所出的位置(比如-).當一個非葉子節點的優勝者向上移動的時候,他原來的位置由它下面節點的優勝者來填補,如此迴圈往復.

分析:

    當一個滿二叉樹有n個葉子節點的時候,他的深度應當是log2n + 1,所以出了最小(大)的關鍵字以外,每選擇一個次小的關鍵字僅需要進行log2n次的比較,因此它的時間複雜度就是O(nlog2n).

    但是錦標排序的缺點很明顯,需要額外的輔助空間,而且選擇最值的時候有多餘的比較.堆排序同樣做為一種選擇排序很好的解決了這個問題.