表排序
又稱間接排序,排序時不調整元素的實際位置,而是定義一個額外的數組作爲“表”(table)。根據元素的關鍵字大小來調整元素對應下標在表中的位置。
例
初始
A | [0] | [1] | [2] | [3] | [4] | [5] | [6] | [7] |
---|---|---|---|---|---|---|---|---|
key | f | d | c | a | g | b | h | e |
table | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
初始的一個結構體數組,需要根據key的大小來進行排序,但是這裏只調整table中下標的位置。表排序在調整下標的位置時可以使用其他的排序算法,例如直接插入排序。
調整後
A | [0] | [1] | [2] | [3] | [4] | [5] | [6] | [7] |
---|---|---|---|---|---|---|---|---|
key | f | d | c | a | g | b | h | e |
table | 3 | 5 | 2 | 1 | 7 | 0 | 4 | 6 |
如果僅要求按順序輸出,則輸出:
物理排序
經過表排序後,得到了排好序的table數組,但是如果需要調整元素的實際位置,那就需要物理排序。
實現
- N個數字的排序由若干個獨立的環組成
- 在每個環中進行元素實際位置的交換
- 使用
temp
來保存第一個元素 - 把
A[table[i]]
的元素放置於i
,同時修改table[i] = i
- 如果
table[i] == i
說明環結束,並把temp置於這個位置
- 使用
struct Element {
ElementType Data; // data可以是任意類型
ElementType key; // 關鍵字只要可比即可
}
// 物理排序過程 Elements = 元素數組, table = 表數組,假設表數組已經排好了
void Sort(Element[] Elements, int[] table, int N) {
for (i = 0; i < N; i++) {
Temp = Elements[i];
int j = i;
while (table[j] != j) {
Elements[j] = Elements[table[j]]; // 把實際該置於j位置的元素置於J
NextIndex = table[j]; // 記錄下一個元素的位置
table[j] = j;
j = NextIndex; // 讓j跳到下一個元素
}
if (Elements[j] != Temp) { // 說明該環不止一個元素,需要進行temp的賦值
Elements[j] = Temp;
}
}
}
複雜度分析
- 最好情況:初始即有序
- 最壞情況:
- 有
⌊N/2⌋ 個環,每個環包含2 個元素 - 需要
⌊3N/2⌋ 次元素移動
- 有
T=O(mN) ,m是每個元素複製的時間