日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

c语言大顶堆数组维护,图解大顶堆的构建、排序过程

發布時間:2023/11/27 生活经验 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c语言大顶堆数组维护,图解大顶堆的构建、排序过程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這兩天在復習大頂堆和小頂堆,比起兩年前的懵懵懂懂,這次理解起來就容易了一些。又翻看了一下自己之前的筆記數據結構與算法之PHP排序算法(堆排序),發現自己這次查閱資料,和之前的思路不太一樣,遂寫下這篇筆記,算是和以前的筆記做一個對照。

一、什么是堆

堆是一種非線性結構,可以把堆看作一棵二叉樹,也可以看作一個數組,即:堆就是利用完全二叉樹的結構來維護的一維數組。

堆可以分為大頂堆和小頂堆。

大頂堆:每個結點的值都大于或等于其左右孩子結點的值。

小頂堆:每個結點的值都小于或等于其左右孩子結點的值。

如果是排序,求升序用大頂堆,求降序用小頂堆。

一般我們說 topK 問題,就可以用大頂堆或小頂堆來實現,

最大的 K 個:小頂堆

最小的 K 個:大頂堆

二、大頂堆的構建過程

大頂堆的構建過程就是從最后一個非葉子結點開始從下往上調整。

最后一個非葉子節點怎么找?這里我們用數組表示待排序序列,則最后一個非葉子結點的位置是:數組長度/2-1。假如數組長度為9,則最后一個非葉子結點位置是 9/2-1=3。

比較當前結點的值和左子樹的值,如果當前節點小于左子樹的值,就交換當前節點和左子樹;

交換完后要檢查左子樹是否滿足大頂堆的性質,不滿足則重新調整子樹結構;

再比較當前結點的值和右子樹的值,如果當前節點小于右子樹的值,就交換當前節點和右子樹;

交換完后要檢查右子樹是否滿足大頂堆的性質,不滿足則重新調整子樹結構;

無需交換調整的時候,則大頂堆構建完成。

畫個圖理解下,以 [3, 7, 16, 10, 21, 23] 為例:

代碼如下:

/**

* 構建大頂堆

* 大頂堆的性質:每個結點的值都大于或等于其左右子結點的值。

*/

function buildBigHeap(&$arr, $len) {

for ($i = floor($len/2) - 1; $i >= 0; $i--) {

//根節點小于左子樹

if (2 * $i + 1 < $len && $arr[$i] < $arr[2 * $i + 1]) {

//交換根節點和左子樹的值

swap($arr, $i, 2 * $i + 1);

// $temp = $arr[$i];

// $arr[$i] = $arr[2 * $i + 1];

// $arr[2 * $i + 1] = $temp;

//檢查左子樹是否滿足大頂堆的性質,如果不滿足,則重新調整

if ((2 * (2 * $i + 1) + 1 < $len && $arr[2 * $i + 1] < $arr[2 * (2 * $i + 1) + 1])

|| (2 * (2 * $i + 1) + 2 < $len && $arr[2 * $i + 1] < $arr[2 * (2 * $i + 1) + 2])) {

buildBigHeap($arr, $len);

}

}

//根節點小于右子樹

if (2 * $i + 2 < $len && $arr[$i] < $arr[2 * $i + 2]) {

//交換根節點和右子樹的值

swap($arr, $i, 2 * $i + 2);

// $temp = $arr[$i];

// $arr[$i] = $arr[2 * $i + 2];

// $arr[2 * $i + 2] = $temp;

//檢查右子樹是否滿足大頂堆的性質,如果不滿足,則重新調整

if ((2 * (2 * $i + 2) + 1 < $len && $arr[2 * $i + 2] < $arr[2 * (2 * $i + 2) + 1])

|| (2 * (2 * $i + 2) + 2 < $len && $arr[2 * $i + 2] < $arr[2 * (2 * $i + 2) + 2])) {

buildBigHeap($arr, $len);

}

}

}

}

/**

* 交換兩個值

* m n 為數組的下標

*/

function swap(&$arr, $m, $n) {

$temp = $arr[$m];

$arr[$m] = $arr[$n];

$arr[$n] = $temp;

}

三、大頂堆的排序過程

將待排序序列構造成一個大頂堆,此時,整個序列的最大值就是堆頂的根節點。將其與末尾元素進行交換,此時末尾就為最大值。然后將剩余n-1個元素重新構造成一個堆,這樣會得到n個元素的次小值,如此反復執行,便能得到一個有序序列了。

是不是對上面這一大段文字很頭疼?其實排序過程用下面 4 步就能概括:

第 1 步:先 n 個元素的無序序列,構建成大頂堆

第 2 步:將根節點與最后一個元素交換位置,(將最大元素"沉"到數組末端)

第 3 步:交換過后可能不再滿足大頂堆的條件,所以需要將剩下的 n-1 個元素重新構建成大頂堆

第 4 步:重復第 2 步、第 3 步直到整個數組排序完成。

/**

* 交換交換根節點和數組末尾元素的值

*/

function adjustHeap(&$heap, $len) {

$temp = $heap[0];

$heap[0] = $heap[$len - 1];

$heap[$len - 1] = $temp;

}

/**

* 堆排序

*/

function heapSort(&$arr) {

$len = count($arr);

for ($i = $len; $i > 0; $i--) {

buildBigHeap($arr, $i);

adjustHeap($arr, $i);

}

}

總結

以上是生活随笔為你收集整理的c语言大顶堆数组维护,图解大顶堆的构建、排序过程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。