2023年,堆排序被提出,它改善了錦標賽排序的種種缺點。
錦標賽排序:
錦標賽排序,也稱為樹形選擇排序(tree selection sort),是一種按照錦標賽的思想進行選擇排序的方法。
首先對n個記錄進行兩兩比較,然後優勝者之間再進行兩兩比較,如此重複,直至選出最小關鍵字的記錄為止。這個過程可 以用一棵有n個葉子結點的完全二叉樹表示。根節點中的關鍵字即為葉子結點中的最小關鍵字。在輸出最小關鍵字之後,根據關係的可傳遞性,欲選出次小關鍵字, 僅需將葉子結點中的最小關鍵字改為「最大值」,如∞,然後從該葉子結點開始,和其左(右)兄弟的關鍵字進行比較,修改從葉子結點到根的路徑上各結點的關鍵 字,則根結點的關鍵字即為次小關鍵字。
這種演算法的缺點在於:輔助儲存空間較多、最大值進行多餘的比較。
為了彌補這些缺點,2023年,堆排序誕生。
堆排序:
堆排序(heap sort)只需要乙個記錄大小的輔助空間。
堆排序的定義如下:n個元素的序列,當且僅當滿足「任何乙個非終端結點的值都大於等於(或小於等於)它左右孩子的值」時,稱之為堆。若序列是堆,則堆頂元素(即完全二叉樹的根)必為序列中n個元素的最小值(或最大值)。
若在輸出堆頂的最小值之後,使得剩餘n-1個元素的序列重又建成乙個堆,則得到n個元素中的次小值。如此反覆執行,便能得到乙個有序序列,這個過程稱之為堆排序。
到目前為止,實現堆排序還需要解決兩個問題:
問題2的解決方法是:假設輸出堆頂元素之後,以堆中最後乙個元素替代之,此時根結點的左、右子樹均為堆,則僅需自上至下進行調整即可。我們稱自堆頂至葉子的調整過程為「篩選」。
(1)如何由乙個無序序列建成乙個堆?
(2)如何在輸出堆頂元素之後,調整剩餘元素成為乙個新的堆?
問題1的解決方法是:從乙個無序序列建堆的過程就是乙個反覆「篩選」的過程。若將此序列看成是乙個完全二叉樹,則最後乙個非終端結點是第⌞n/2⌟個元素,由此「篩選」只需從第⌞n/2⌟個元素開始。
堆排序方法對記錄數較少的檔案並不值得提倡,但對n較大的檔案還是很有效的。
堆排序在最壞情況下的時間複雜度也為o(nlogn),相對於快速排序來說,這是堆排序的最大優點。
堆排序源**:
#include
/***********************************
* 功能:調整堆
* 引數:arr - 指向堆的根的指標
* m - 堆中待調整的節點
* n - 堆中元素的個數
************************************/
void heap_adjust(int *arr, int m, int n)
arr[m] = arr[0];}
void heap_sort(int *arr, int arrsize)
//輸出堆頂元素
for(i=arrsize; i>1; i--)
}int main(void)
;int arrsize=7;
int i;
printf("quick sort:/n");
heap_sort(arr,arrsize);
printf("sorted array: ");
for(i=1;i<=arrsize;i++)
printf("/n");
return 0;
}
演算法 排序(2)錦標賽排序
用完全二叉樹定義勝者樹,前n 1個結點t 1 t n 1 為內部結點 勝者 後n個結點e 1 e n 是參賽者。t陣列存的是參賽者編號,即e t 0 才是最終勝者的值 t 1 並沒有改變 int winner const int winner int i const int winner int a...
錦標賽排序演算法 java版
今天在做遊戲的聯賽系統,假如有n 人報名參加聯賽,伺服器記錄下報名人數,並對這些人的戰鬥後的結果進行排序,決出前16強或者8強。網上找了下錦標賽排序演算法,內容真少。總結下 1 建樹 這裡說的建樹是建立一顆完全二叉樹。當參加排序的陣列不足2的n次冪,將其補足。直到滿足建立乙個完全二叉樹 2 當某結點...
錦標賽問題 遞迴
設有n位選手參加網球迴圈賽,n 2 k,迴圈賽共進行n 1天,每位選手要與其他n 1位選手比賽一場,且每位選手每天比賽一場,不能輪空,按一下要求為比賽安排日程,1 每位選手必須與其他n 1格選手格賽一場 2 每個選手每天只能賽一場 3 迴圈賽一共進行n 1天 請按此要求將比賽日程表設計成有n行和n ...