堆排序是利用堆這種資料結構而設計的一種排序演算法,堆排序是一種選擇排序,它的最壞,最好,平均時間複雜度均為o(nlogn),它也是不穩定排序。首先簡單了解下堆結構。
堆(heap)是電腦科學中一類特殊的資料結構的統稱。堆通常是乙個可以被看做一棵完全二叉樹的陣列:每個結點的值都大於或等於其左右孩子結點的值,稱為大頂堆;或者每個結點的值都小於或等於其左右孩子結點的值,稱為小頂堆。如下圖:
同時,我們對堆中的結點按層進行編號,將這種邏輯結構對映到陣列中就是下面這個樣子
該陣列從邏輯上講就是乙個堆結構,我們用簡單的公式來描述一下堆的定義就是:
堆排序的基本思想是:將待排序序列構造成乙個大頂堆,此時,整個序列的最大值就是堆頂的根節點。將其與末尾元素進行交換,此時末尾就為最大值。然後將剩餘n-1個元素重新構造成乙個堆,這樣會得到n個元素的次小值。如此反覆執行,便能得到乙個有序序列了。
將給定無序序列構造成乙個大頂堆(一般公升序採用大頂堆,降序採用小頂堆)。
將堆頂元素與末尾元素進行交換,使末尾元素最大。
然後繼續調整堆,再將堆頂元素與末尾元素交換,得到第二大元素。如此反覆進行交換、重建、交換。
/*
堆排序的基本思路:
a.將無需序列構建成乙個堆,根據公升序降序需求選擇大頂堆或小頂堆;
b.將堆頂元素與末尾元素交換,將最大元素"沉"到陣列末端;
c.重新調整結構,使其滿足堆定義,然後繼續交換堆頂元素與當前末尾元素,
反覆執行調整+交換步驟,直到整個序列有序。
*/#include
void
adjustheap
(int
*data,
int i,
int length)
if(data[k]
>temp)
else
} data[i]
= temp;
//將temp值放到最終的位置
}void
heap_sort
(int data,
int n)
//2.調整堆結構+交換堆頂元素與末尾元素
for(i=n-
1; i>=
1; i--)}
intmain()
;printf
("排序前的資料為:\n");
for(
int i=
0; i<
10;i++
)printf
("%d "
,data[i]);
printf
("\n\n");
heap_sort
(data,10)
;printf
("排序後的結果為:\n");
堆排序是一種選擇排序,整體主要由構建初始堆+交換堆頂元素和末尾元素並重建堆兩部分組成。其中構建初始堆經推導複雜度為o(n),在交換並重建堆的過程中,需交換n-1次,而重建堆的過程中,根據完全二叉樹的性質,[log2(n-1),log2(n-2)…1]逐步遞減,近似為nlogn。所以堆排序時間複雜度一般認為就是o(nlogn)級。
排序方法
時間複雜度(平均)
時間複雜度(最壞)
時間複雜度(最好)
空間複雜度
穩定性堆排序
o(nlog2n)
o(nlog2n)
o(nlog2n)
o(1)
不穩定
排序演算法 堆排序
1 什麼是堆 首先它是一顆完全二叉樹,並且父結點的值大於子節點的值 最大堆 或父結點的值小於子結點的值 最小堆 小根堆 根結點 亦稱為堆頂 的關鍵字是堆裡所有結點關鍵字中最小者的堆稱為小根堆,又稱最小堆。大根堆 根結點 亦稱為堆頂 的關鍵字是堆裡所有結點關鍵字中最大者,稱為大根堆,又稱最大堆。2 堆...
排序演算法 堆排序
花了一晚上時間研究堆排序,這個排序困擾了哥很久,終於搞清楚了。一 堆的定義 1.父結點的鍵值總是大於或等於 小於或等於 任何乙個子節點的鍵值 2 每個結點的左子樹和右子樹都是乙個二叉堆 都是最大堆或最小堆 二 已知結點 i 則它的子結點 為2 i 1 與 2 i 2 父節點為 i 1 2 三 堆排序...
排序演算法 堆排序
由於不經常使用,之前學習看過的演算法都給忘了。現在把他們寫下來,記錄下來,以方便以後查閱。本篇文章的 即為堆排序的 主函式中是對輸入檔案中的序列進行排序,並將結果輸出到乙個檔案中。這是一種形式類似於google codejam的測試方法。include include using namespace...