堆和堆排序

2021-06-21 13:03:28 字數 3021 閱讀 6615

是一種靈巧的、部分有序的資料結構,它尤其適合用來實現優先佇列。

優先佇列是元素的乙個集合,其中每個元素都包含乙個被稱為元素優先順序的可排序屬性。優先佇列支援下面的操作:

通過採用堆這種資料結構可以高效實現這些操作。

下文分兩部分:第一部分介紹堆;第二部分講解堆排序。

堆可以定義為一棵二叉樹,樹的節點中包含鍵(每個節點乙個鍵),並且滿足下面兩個條件:

樹的形狀要求--這棵二叉樹是基本完備的(或者簡稱完全二叉樹),這意味著,樹的每一層都是滿的,除了最後一層最右邊的元素有可能缺位。

父母優勢要求--每乙個節點的鍵都要大於或等於它子女的鍵(對於任何葉子我們認為這個條件都是自動滿足的)。(最大堆)

在堆中,鍵值是從上到下排序的。在任何從根到某個葉子的路徑上,鍵值的序列式遞減的。鍵值之間不存在從左到右的次序。在樹的同一層的節點之間,不存在任何關係。在同一節點的左右子樹之間也沒有任何關係。

堆的重要特徵:

只存在一棵n個節點的完全二叉樹。它的高度等於log2n。

堆的根總是包含了堆的最大元素。

堆的乙個節點以及該節點的子孫也是乙個堆。

可以用陣列來實現堆,方法是用從上到下、從左到右的方式來記錄堆的元素。為了方便起見,可以在這種陣列從1到n的位置上存放堆元素,留下h[0](可以在其中放乙個限位器)。在這種表示法中:

a.  父母節點的鍵將會位於陣列的前[n / 2]個位置中,而葉子節點的鍵將會佔據後[n / 2]個位置。

b.  在陣列中,對於乙個位於父母位置i(1<=i<=[n / 2])的鍵來說,它的子女將會位於2i和2i+1,相應地,對於乙個位於i(2<=i<=n)的鍵來說,它的父母將會位於[i/2]。

我們可以將堆定義為乙個陣列h[1…n],其中,陣列前半部分中每個位置i上的元素,總是大於等於位置2i和2i+1中的元素。

對於i=1,…,[n / 2], h[i]>=max

從最後的父母節點開始,到根為止,檢查這些節點的鍵是否滿足父母優勢要求。如果該節點不滿足,則把節點的鍵k和它子女的最大鍵進行交換,然後再檢查在新位置上,k是不是滿足父母優勢要求。這個過程一直持續到,對k的父母優勢要求滿足為止。對於以當前父母節點為根的子樹,在完成了它「堆化」以後,該演算法對於該幾點的直接前趨進行同樣的操作,直到對樹的根完成了這種操作以後,該演算法就停止。

演算法   heapbottomup(h[1..n])

//用自底向上演算法,從給定陣列的元素中構建乙個堆

//輸入:乙個可排序元素的陣列h[1..n]

//輸出:乙個堆h[1..n]

從堆中刪除最大的鍵

第一步:根的鍵和堆的最後乙個鍵k做交換。

第二步:堆的規模減一。

第三步:嚴格按照自底向上堆構造演算法把k沿著樹向下刪選,來對這棵較小的樹進行「堆化」。驗證k是否滿足父母優勢:如果它滿足,操作完成;如果不滿足,k和它較大的子女做交換;然後重複這個操作,直到k在新位置中滿足了父母優勢要求為止。

堆排序是由j.w.j.williams提出。堆排序的時間效率輸入o(nlogn)。這個演算法分為兩步:

第一步:(構造堆)為乙個給定的陣列構造乙個堆。

第二部:(刪除最大鍵)對剩下的堆應用n-1次根刪除操作。

對於堆的陣列實現來說,乙個正在被刪除元素師位於最後的,所以結果陣列將敲好是按照公升序排列的原始陣列。

#include #include //陣列從1到n的位置上存放堆元素,a[0]不參與構造堆。

//可以將a[0]空著,也可以在其中放乙個限位器。

/**********自底向上構造最大堆**************/

void heapbottomup(int a, int n)

} a[k] = tmp; }}

/**********自底向上調整最大堆**************/

void fixheapbottomup(int a, int n)

} a[i] = tmp;

}/**********自頂向下調整最大堆**************/

void fixheapupbottom(int a, int n)

} a[i] = tmp;

}/**********插入乙個數**************/

void insertnumber(int a, int n, int num)

/**********刪除最大鍵**************/

int deletenumber(int a, int n)

/**********堆排序**************/

void heapsort(int a, int n)

int main(int argc, const char *argv)

; int n = sizeof(a) / sizeof(int);

heapsort(a, n - 1);

for(int i = 1; i < 7; i ++)

printf("%d ", a[i]);

return 0;

}

堆和堆排序

這個題大意是有乙個資料結構支援兩種操作a與 get操作,其中 a x表示插入 x.get i 表示返回結構中的第 i小的數.給你 a和get操作的順序和引數 現在要你對每個 get輸出值 題解 每次取第k小元素,k不斷更新。使用兩個堆,來完成。小頂堆負責選出最小的元素,大頂堆負責選出k個元素中最大的...

堆和堆排序

堆排序演算法 優先佇列 堆的性質的維護,以下都以最大堆為例。堆的維護的主要思想是 逐層下降 舉例 某個結點i,假設其左右子結點left i right i 都已經是最大堆,那麼需要調節 或者說是調換 i,left i right i 的值,並保證調換後的子樹繼續調換下去直到子樹繼續滿足堆的性質。首先...

堆和堆排序

用陣列來儲存堆,下標為i的結點,父節點的編號為 i 1 2,子結點的編號為2 i 1,2 i 2。建立堆 每次插入乙個元素並調整堆的過程。插入乙個元素 插入到陣列最後,更新樹。刪除乙個元素 刪除發生在nums 0 將最後乙個元素調整到nums 0 處,更新樹。長度為len的陣列,最後乙個葉子節點的父...