基礎排序演算法 堆 和堆排序

2021-10-04 16:34:35 字數 3030 閱讀 5651

堆是一種靈巧,部分有序的資料結構,它適合用來實現優先佇列。優先佇列是元素的乙個集合,其中每個元素都包含乙個被稱作元素優先順序的可排序屬性,優先佇列支援下面的操作

找出乙個具有最高優先順序的元素(一般是最大或者最小)

刪除乙個具有最高優先順序的元素

新增乙個元素到集合中去

定義:堆可以定義為一根二叉樹,樹的節點包含鍵(每乙個節點都有乙個鍵值),並且滿足以下條件。

自底向上堆構造

初始化一顆包含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 因此應用場合較多。其原理同簡單選擇排序相似 將資料分為已排序和未排序的兩部分,並且不斷的從未排序資料中選取最大 或最小 資料加入到已排序集合中。不同之處在於,堆排序採用了一種特殊的二叉堆結構來快速的尋找最大值。如下圖,首...