排序演算法--兩種選擇排序
選擇排序是一種以重複選擇為思想的排序演算法.其中直接選擇排序是最簡單的一種.
直接選擇排序:
演算法:
假設有一個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;
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);
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).
但是錦標排序的缺點很明顯,需要額外的輔助空間,而且選擇最值的時候有多餘的比較.堆排序同樣做為一種選擇排序很好的解決了這個問題.