學習演算法導論 堆排序

2021-07-10 05:26:09 字數 1815 閱讀 3525

《演算法導論》第三版書中陣列下標是從1開始的,但是這裡從0開始。

堆分為兩種,即最大堆和最小堆,最大堆的定義為:當陣列a大小為n時(a中有n個元素),若2*i+1=a[2*i+1];若2*i+2=a[2*i+2],則這樣的資料結構稱為最大堆。說白了就是根節點(包括子樹的根節點)的值不小於左節點和右節點的值(如果有左或右節點的話)。

最小堆和最大堆剛好相反。

這裡以最大堆為例。

首先要了解的一些知識是對於根節點i,其左孩子節點為2*i+1,右孩子節點為2*i+2;第乙個非葉節點為(n-2)/2;其中n為陣列大小。

unsigned left_child(unsigned i)

unsigned right_child(unsigned i)

下面的max_heapily()函式是使得根節點為i的樹(子樹)為最大堆

void max_heapily(unsigned a, unsigned i,unsigned n)//維持根節點為i的樹為最大堆

}

void build_max_heap(unsigned a, unsigned n)//從第乙個非葉節點到根節點調整為最大堆

}

上面的build_max_heap()函式為什麼從第乙個非葉節點開始迴圈?因為根據最大堆的定義,不但整課樹為最大堆,所有的子樹也為最大堆,第乙個非葉節點就是第一顆子樹的根節點。存在疑問的地方是,那直接max_heapily(a,0,n)不就行了嗎?不行,該函式調整的是根節點和左右孩子節點:

只有上面中的是三個節點不符合最大堆時,它才會調整子樹。

首先,把有n個元素的陣列a初始化建立為最大堆,然後迴圈執行如下過程直到陣列為空為止:(1)把堆頂a[0]元素(為最大元素)和當前最大堆的最後乙個元素交換;(2)最大堆元素個數減1;(3)由於第(1)步後根節點不再滿足最大堆的定義,所以調整根節點使之滿足最大堆的定義。

void heap_sort(unsigned a,unsigned n)

}

int main(int argc, char* argv)

; heap_sort(a, 10);

for (unsigned i = 0; i < 10; ++i)

getchar();

return 0;

}

結果:

另一種建立最大堆的方法為插入法,我們可以這樣想像,將陣列中的元素按順序逐個插入乙個二叉樹中,如插入a[0]為根節點,接著插入a[1]為左孩子節點並和根節點a[0]比較,如果不符合最大堆,則a[1]和根節點a[0]交換值;同樣,插入a[2];插入a[3],和根節點a[1]比較,如果不符合最大堆,a[3]和a[1]交換值,此時,還需要繼續往「總根」方向比較,比較a[1]和a[0],根據最大堆的性質決定是否要交換值,其他節點插入同理。

插入法建立最大堆c++**:

void max_heap_insert(unsigned a, unsigned position)

}

void build_max_heap(unsigned a,unsigned n)

}

演算法導論 堆排序

堆排序演算法 heapsort max heapify過程,其執行時間為 lg n 是保持最大堆性質的關鍵 build max heap過程,以線性時間執行,可以在無序的輸入陣列基礎上構造出最大堆 heapsort過程,執行時間 n lg n 對乙個陣列原地進行排序 heapsort過程 1 建最大...

演算法導論 堆排序習題

1.怎樣利用最大 小 堆構成的優先實現先進先出佇列或者棧 開始看這道題沒有弄清以什麼優先,原來是先進先出佇列只要保證先進來優先順序高,棧保證後進來優先順序高,然後每次彈出堆頂元素即可 2.如何在logn時間裡刪除乙個元素 思路和如何在堆中增加乙個元素是一樣的,因為堆要的形狀要保證是一顆完全二叉樹,決...

演算法導論 堆排序實現

我建立了乙個heap的資料結構,而不是像stl那樣使用函式解決堆排序,當然stl的比較優雅一點,我只是提供第二個思路 ifndef heap sort h define heap sort h include include include ifdef debug include endif deb...