堆是一種靈巧,部分有序的資料結構,它適合用來實現優先佇列。優先佇列是元素的乙個集合,其中每個元素都包含乙個被稱作元素優先順序的可排序屬性,優先佇列支援下面的操作
找出乙個具有最高優先順序的元素(一般是最大或者最小)
刪除乙個具有最高優先順序的元素
新增乙個元素到集合中去
定義:堆可以定義為一根二叉樹,樹的節點包含鍵(每乙個節點都有乙個鍵值),並且滿足以下條件。
自底向上堆構造
初始化一顆包含n個節點的完全二叉樹,按照給定數的順序來放置鍵,然後按照下面的方法對樹進行處理,從最後的父母節點開始,直到根為止,依次檢查這些節點的鍵k是否滿足父母優勢,如果不滿足,就把該節點的鍵k和它子女的最大鍵進行交換,然後在檢查新位置上,k是否滿足父母優勢,這個過程一直繼續到對k的父母優勢要求滿足為止。對於以當前父母節點為根的子樹,在完成它的堆化後,該演算法對該節點的直接前驅進行同樣的操作,在對樹的根完成這種操作以後,該演算法就停止了。
c語言實現
void
heapbottomup
(int n)
if(v>=h[j]
) heap=1;
else}}
}
把新的鍵連續插入預先構造好的堆,來建造乙個新堆,也可以叫做自頂向下構造演算法。
通過把新的鍵插入預先構造好的堆,來構造乙個新堆,那麼我們怎麼把乙個新的鍵插入堆中呢?
首先把乙個包含鍵k的結點附加在當前堆的最後乙個葉子後面,然後按照下面的方法把k篩選到正確的位置,拿k與它的父母作比較,如果它大於父母,則交換,如果不大於或者達到樹根,演算法停止,否則交換後繼續比較與新父母的大小。
這裡我們考慮的是刪除根中的鍵,利用下面的演算法刪除根中的鍵。
根的鍵和堆最後乙個鍵k做交換。
堆的規模減一
驗證根此時的鍵是否滿足父母優勢,做法同於自底向上堆構造裡的演算法
堆排序
堆排序的步驟大致分為兩部
構造堆,就是為給定的陣列構造乙個堆
刪除最大鍵,就是對剩下的對進行n-1次根刪除操作
最後的結果是按照降序刪除了陣列的元素,但是對於堆的陣列的實現來說,乙個正在被刪除的元素是位於最後的,所以結果陣列將恰好是按照公升序排列的原始陣列。
堆排序實現**
#include
void
swap
(int
* array,
int i,
int j)
/*最小根堆調整,這裡的注釋在上面的有說明*/
void
minheapify
(int
* array,
int heapsize,
int currentnode)
if(parentvalue<=array[j]
) heap=1;
else}}
}void
maxheapify
(int
* array,
int heapsize,
int currentnode)
if(parentvalue>=array[j]
) heap=1;
else}}
}void
minheapcreate
(int
* array,
int heapsize)
}void
maxheapcreate
(int
* array,
int heapsize)
}int
main()
;//初始化陣列,也叫作待排序陣列,第乙個0不是需要排序的數,只是為了表述排序從下標1到 6的這六個數
int*res=array;
//res用作返回值,在array上做修改。
int i,heapsize=
sizeof
(array)
/sizeof
(int)-
1;//堆使用陣列實現,陣列的大小為6;
printf
("原始資料:\n");
for(i=
1;i<=heapsize;i++
)printf
("\n");
for(i=heapsize;i>=
1;i--
)//堆的規模減一(因為已經把最小的數放在陣列末尾了),繼續建立並調整最小堆。
printf
("最小堆輸出(利用最小堆實現陣列降序排列):\n");
for(i=
1;i<=heapsize;i++
)printf
("%d\t"
,array[i]);
printf
("\n");
//以下是最大堆的處理,思想同於上述最小堆。
for(i=heapsize;i>=
1;i--
)printf
("最大堆輸出(利用最大堆實現陣列公升序排列):\n");
for(i=
1;i<=heapsize;i++
)printf
("%d\t"
,array[i]);
printf
("\n");
return0;
}
執行截圖
實現最大堆,最小堆還可以有另外乙個技巧,使用函式自身呼叫。
可以參考下面的優秀部落格,寫的很清楚。
演算法 堆排序(堆)
使用情形 插入乙個數 求集合當中的最小值 刪除最小值 刪除任意乙個元素 修改任意乙個元素 用一維陣列儲存二叉樹,左兒子在陣列中為根節點在陣列中的位置的2倍,右兒子在陣列中為根節點在陣列中的位置的二倍加一。求當前堆的最小值 void down int u 輸入乙個長度為n的整數數列,從小到大輸出前m小...
排序演算法(六) 堆排序
堆定義 堆是一種完全二叉樹,每個結點都大於等於其子結點的稱為大頂堆,每個結點都小於等於其子結點的稱為小頂堆。堆排序定義 將待排序的序列構造成乙個大頂堆,此時堆頂是最大值,將其移到序列最末端後,剩餘的序列重新構造乙個大頂堆,如此反覆直到得到乙個有序序列。時間複雜度 o nlogn 實現 public ...
排序演算法6 堆排序
堆排序可以看作是簡單選擇排序的一種的改進方法,平均複雜度為 o n log n 因此應用場合較多。其原理同簡單選擇排序相似 將資料分為已排序和未排序的兩部分,並且不斷的從未排序資料中選取最大 或最小 資料加入到已排序集合中。不同之處在於,堆排序採用了一種特殊的二叉堆結構來快速的尋找最大值。如下圖,首...