在軟件設計相關領域,「堆(Heap)」的概念主要涉及到兩個方面:javascript
一種是數據結構,邏輯上是一顆徹底二叉樹,存儲上是一個數組對象(二叉堆)。java
另外一種是垃圾收集存儲區,是軟件系統能夠編程的內存區域。算法
本文所說的堆指的是前者,另外,這篇文章中堆中元素的值均以整形爲例編程
堆排序的時間複雜度是O(nlog2n),與快速排序達到相同的時間複雜度. 可是在實際應用中,咱們每每採用快速排序而不是堆排序. 這是由於快速排序的一個好的實現,每每比堆排序具備更好的表現. 堆排序的主要用途,是在造成和處理優先級隊列方面. 另外, 若是計算要求是類優先級隊列(好比, 只要返回最大或者最小元素, 只有有限的插入要求等), 堆一樣是很適合的數據結構.api
堆排序
堆排序是一種選擇排序。是不穩定的排序方法。時間複雜度爲O(nlog2n)。
堆排序的特色是:在排序過程當中,將排序數組當作是一棵徹底二叉樹的順序存儲結構,利用徹底二叉樹中雙親節點和孩子節點之間的內在關係,在當前無序區中選擇關鍵字最大(或最小)的記錄。數組
基本思想
1.將要排序的數組建立爲一個大根堆。大根堆的堆頂元素就是這個堆中最大的元素。
2.將大根堆的堆頂元素和無序區最後一個元素交換,並將無序區最後一個位置例入有序區,而後將新的無序區調整爲大根堆。
重複操做,無序區在遞減,有序區在遞增。
初始時,整個數組爲無序區,第一次交換後無序區減一,有序區增一。
每一次交換,都是大根堆的堆頂元素插入有序區,因此有序區保持是有序的。數據結構
大根堆和小根堆
堆:是一顆徹底二叉樹。
大根堆:全部節點的子節點比其自身小的堆
小根堆:全部節點的子節點比其自身大的堆函數
堆與數組的關係ui
堆是一種邏輯結構(形象的表示數據的存儲格式),數組則是數據的實際存儲結構(對應數據的存儲地址),堆中的根節點與左右子節點在存儲數組中的位置關係以下:假設根節點在數組中的位置(數組下標)爲 i ,那麼左節點在數組中的位置(數組下標)爲 i * 2 + 1 , 右節點在數組中的位置(數組下標)爲 i * 2 + 2 。this
//堆排序算法(傳遞待排數組名,即:數組的地址。故形參數組的各類操做反應到實參數組上)
privatestaticvoid HeapSortFunction(int[] array)
{
try
{
BuildMaxHeap(array); //建立大頂推(初始狀態看作:總體無序)
for (int i = array.Length -1; i >0; i--)
{
Swap(ref array[0], ref array[i]); //將堆頂元素依次與無序區的最後一位交換(使堆頂元素進入有序區)
MaxHeapify(array, 0, i); //從新將無序區調整爲大頂堆
}
}
catch (Exception ex)
{ }
}
///<summary>
/// 建立大頂推(根節點大於左右子節點)
///</summary>
///<param name="array">待排數組</param>
privatestaticvoid BuildMaxHeap(int[] array)
{
try
{
//根據大頂堆的性質可知:數組的前半段的元素爲根節點,其他元素都爲葉節點
for (int i = array.Length /2-1; i >=0; i--) //從最底層的最後一個根節點開始進行大頂推的調整
{
MaxHeapify(array, i, array.Length); //調整大頂堆
}
}
catch (Exception ex)
{ }
}
///<summary>
/// 大頂推的調整過程
///</summary>
///<param name="array">待調整的數組</param>
///<param name="currentIndex">待調整元素在數組中的位置(即:根節點)</param>
///<param name="heapSize">堆中全部元素的個數</param>
privatestaticvoid MaxHeapify(int[] array, int currentIndex, int heapSize)
{
try
{
int left =2* currentIndex +1; //左子節點在數組中的位置
int right =2* currentIndex +2; //右子節點在數組中的位置
int large = currentIndex; //記錄此根節點、左子節點、右子節點 三者中最大值的位置
if (left < heapSize && array[left] > array[large]) //與左子節點進行比較
{
large = left;
}
if (right < heapSize && array[right] > array[large]) //與右子節點進行比較
{
large = right;
}
if (currentIndex != large) //若是 currentIndex != large 則代表 large 發生變化(即:左右子節點中有大於根節點的狀況)
{
Swap(ref array[currentIndex], ref array[large]); //將左右節點中的大者與根節點進行交換(即:實現局部大頂堆)
MaxHeapify(array, large, heapSize); //以上次調整動做的large位置(爲這次調整的根節點位置),進行遞歸調整
}
}
catch (Exception ex)
{ }
}
///<summary>
/// 交換函數
///</summary>
///<param name="a">元素a</param>
///<param name="b">元素b</param>
privatestaticvoid Swap(refint a, refint b)
{
int temp =0;
temp = a;
a = b;
b = temp;
}