資料結構 堆 C

2021-09-29 14:38:18 字數 3898 閱讀 9253

二叉堆堆排序

堆(heap)分為二叉堆、二項式堆、斐波那契堆,堆是非線性資料結構,相當於一維陣列,有兩個直接後繼。堆又被稱為優先佇列,儘管名為優先佇列,但堆並不是佇列。因為佇列遵循first in, first out,但是堆是按照元素的優先順序取出元素。所以「堆」是實現排程器的理想資料結構。

堆排序與快速排序、歸併排序一樣都是時間複雜度為o(n*logn)的排序方法。

在這裡講二叉樹是因為堆通常是乙個可以被看做一棵完全二叉樹的陣列物件。

二叉樹(binary tree)是每乙個節點最多有兩個分支的樹結構,通常分支被稱作左子樹和右子樹,分支具有左右次序,不能隨意顛倒。二叉樹第i最多擁有2 ^ (i - 1)個節點,深度為k的二叉樹最多共有2 ^ (k + 1) - 1個節點。

假設某個二叉樹深度為k,第i層擁有2 ^ (i - 1)個節點,且總共擁有2 ^ (k + 1) - 1個節點,這樣的二叉樹稱為滿二叉樹。簡單來說就是,二叉樹的每一層都是滿的,除了最後一層上的節點,每乙個節點都具有左節點和右節點。

完全二叉樹是由滿二叉樹引出來的,是效率很高的資料結構,若設二叉樹的深度為h,除第h層外,其它各層(1~h-1) 的結點數都達到最大個數,第h層所有的結點都連續集中在最左邊,這就是完全二叉樹。

對於深度為k的,有n個結點的二叉樹,當且僅當其每乙個結點都與深度為k的滿二叉樹中編號從1n的結點一一對應時稱之為完全二叉樹。

所有的葉結點都出現在第k層或k - 1層(層次最大的兩層)

對任一結點,如果其右子樹的最大層次為l,則其左子樹的最大層次為l或l + 1

這裡有一點需要強調:滿二叉樹以一定是完全二叉樹,但完全二叉樹不一定是滿二叉樹

二叉堆是一種特殊的堆,二叉堆是完全二元樹(二叉樹)或者是近似完全二元樹(二叉樹)。

二叉堆分為兩種:大頂堆和小頂堆

因為二叉堆是乙個完全二叉樹,所以其必須滿足上面講述的完全二叉樹的條件。再而,為了實現堆的操作,我們額外增加乙個要求:任意節點的優先順序不小於它的子節點

所以總結,二叉堆滿足以下兩個特性:

父節點的鍵值總是大於或者等於(小於或等於)任何乙個子節點的鍵值

每個節點的左子樹和右子樹都是乙個二叉堆(都是最大堆或最小堆)

在下面的講述中採用大頂堆來進行實現。

一般都用陣列來表示堆,i為陣列的下標,那麼該節點的父節點下標為i / 2。它的左右子節點下標分別為2 * i2 * i + 1

說到這裡,大家應該可以將堆和樹聯絡在一起了,同時又因為堆通常是乙個可以被看做一棵完全二叉樹的陣列物件。為了方便後面的操作(像插入、刪除…),所以堆的結構就並不是左指標和右指標了,而是以陣列的形式。

建立堆:陣列具有對應的樹表示形式。一般情況下,樹並不滿足堆的條件,通過重新排列元素,可以建立一顆「堆化」的樹。

插入乙個元素:新元素被插入到列表層(即完全二叉樹最後的位置),將其和父節點比較。如果新元素比父節點大,那麼交換兩者。交換之後,繼續和新的父節點比較,直至新元素不比父節點大,隨後樹被更新以恢復堆次序。(其時間複雜度為o(logn)),以上操作稱為上溯(percolate up)操作。

刪除乙個元素:刪除總是發生在根節點處。樹中最後乙個元素被用來填補空缺位置,稱為暫時根節點,然後將暫時根節點不斷和子節點(左右兩子節點中大的那乙個節點)進行比較,如果他比子節點小,則交換節點位置,直到暫時根節點不小於任何乙個子節點,結果樹被更新以恢復堆條件。以上操作被稱為下溯(percolate down)。

在實現堆的過程中,我們需要先建立乙個堆,堆的底層是陣列,由於其第乙個位置不存放真實的值,所以在申請空間的時候多申請乙個。

#include

#include

#include

#include

#include

#include

using

namespace std;

template

<

typename item>

class

maxheap

~maxheap()

intsize()

bool

isempty()

};intmain()

向其中插入元素

void

insert

(item item)

//考慮索引越界的問題,k必須大於1才能有父節點

void percolate_up (

int k)

}

測試插入元素

從堆中取出(刪除操作)

item extractmax()

void

percolate_down

(int k)

if(data[k]

>= data[j]

)break

;swap

(data[k]

,data[j]);

k = j;

}}

測試取出元素

通過上面的學習我們知道了堆的儲存結構以及如何用**來實現堆的插入和刪除,在進行堆插入的時候,按照堆的結構進行儲存,當我們彈出元素的時候,永遠彈出的是堆中的最大值。我們看一下下面的**以及他的結果。

while

(!maxheap.

isempty()

)

我們發現了是一組有序的資料,這裡就引申出了堆排序。

#include

#include

"heap.h"

using

namespace std;

template

<

typename t>

void

headsort1

(t arr,

int n)

for(

int j = n -

1; j >=

0; j --

)}

C 資料結構 堆

堆 一種可被視為完全二叉樹的結構,實現有多種方法 一 c stl 優先佇列實現 1.首先寫好佇列標頭檔案 include 2.定義乙個int型 值小的數優先順序高 先出佇列 的佇列 小根堆 最後的 與 間注意留空格 priority queue,greater a 大根堆的定義 priority q...

C 資料結構 18 堆

堆的實現通過構造二叉堆 binary heap 實為二叉樹的一種 由於其應用的普遍性,當不加限定時,均指該資料結構的這種實現。這種資料結構具有以下性質。任意節點小於 或大於 它的所有後裔,最小元 或最大元 在堆的根上 堆序性 堆總是一棵完全樹。即除了最底層,其他層的節點都被元素填滿,且最底層盡可能地...

資料結構 堆

最大堆 最小堆 堆的定義是 n個元素的序列,當且僅當滿足如下關係時被成為堆 1 ki k2i 且 ki k2i 1 或 2 ki k2i 且 ki k2i 1 i 1,2,n 2 當滿足 1 時,為最小堆,當滿足 2 時,為最大堆。若將此序列對應的一維陣列堪稱是乙個完全二叉樹,則2i和2i 1個節點...