跳到主要內容

圖解大頂堆的構建、排序過程_貨運


※回頭車貨運收費標準



宇安交通關係企業,自成立迄今,即秉持著「以誠待人」、「以實處事」的企業信念


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


一、什麼是堆


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


堆可以分為大頂堆和小頂堆。
大頂堆:每個結點的值都大於或等於其左右孩子結點的值。
小頂堆:每個結點的值都小於或等於其左右孩子結點的值。


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


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


二、大頂堆的構建過程


大頂堆的構建過程就是從最後一個非恭弘=叶 恭弘子結點開始從下往上調整。


※評比南投搬家公司費用收費行情懶人包大公開



搬家價格與搬家費用透明合理,不亂收費。本公司提供下列三種搬家計費方案,由資深專業組長到府估價,替客戶量身規劃選擇最經濟節省的計費方式




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


比較當前結點的值和左子樹的值,如果當前節點小於左子樹的值,就交換當前節點和左子樹;
交換完后要檢查左子樹是否滿足大頂堆的性質,不滿足則重新調整子樹結構;


再比較當前結點的值和右子樹的值,如果當前節點小於右子樹的值,就交換當前節點和右子樹;
交換完后要檢查右子樹是否滿足大頂堆的性質,不滿足則重新調整子樹結構;


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


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

代碼如下:


<?php
/**
* 構建大頂堆
* 大頂堆的性質:每個結點的值都大於或等於其左右子結點的值。
*/
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);
}
}
本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

※智慧手機時代的來臨,RWD網頁設計為架站首選



網動結合了許多網際網路業界的菁英共同研發簡單易操作的架站工具,及時性的更新,為客戶創造出更多的網路商機。




Orignal From: 圖解大頂堆的構建、排序過程_貨運

留言

這個網誌中的熱門文章

有了四步解題法模板,再也不害怕動態規劃!(看不懂算我輸)

導言 動態規劃問題一直是算法面試當中的重點和難點,並且動態規劃這種通過空間換取時間的算法思想在實際的工作中也會被頻繁用到,這篇文章的目的主要是解釋清楚 什麼是動態規劃 ,還有就是面對一道動態規劃問題,一般的 思考步驟 以及其中的注意事項等等,最後通過幾道題目將理論和實踐結合。 什麼是動態規劃 如果你還沒有聽說過動態規劃,或者僅僅只有耳聞,或許你可以看看 Quora 上面的這個 回答 。 How to explain dynamic 用一句話解釋動態規劃就是 " 記住你之前做過的事 ",如果更準確些,其實是 " 記住你之前得到的答案 "。 我舉個大家工作中經常遇到的例子。 在軟件開發中,大家經常會遇到一些系統配置的問題,配置不對,系統就會報錯,這個時候一般都會去 Google 或者是查閱相關的文檔,花了一定的時間將配置修改好。 過了一段時間,去到另一個系統,遇到類似的問題,這個時候已經記不清之前修改過的配置文件長什麼樣,這個時候有兩種方案,一種方案還是去 Google 或者查閱文檔,另一種方案是借鑒之前修改過的配置,第一種做法其實是萬金油,因為你遇到的任何問題其實都可以去 Google,去查閱相關文件找答案,但是這會花費一定的時間,相比之下,第二種方案肯定會更加地節約時間,但是這個方案是有條件的,條件如下: 之前的問題和當前的問題有着關聯性,換句話說,之前問題得到的答案可以幫助解決當前問題 需要記錄之前問題的答案 當然在這個例子中,可以看到的是,上面這兩個條件均滿足,大可去到之前配置過的文件中,將配置拷貝過來,然後做些細微的調整即可解決當前問題,節約了大量的時間。 不知道你是否從這些描述中發現,對於一個動態規劃問題,我們只需要從兩個方面考慮,那就是 找出問題之間的聯繫 ,以及 記錄答案 ,這裏的難點其實是找出問題之間的聯繫,記錄答案只是順帶的事情,利用一些簡單的數據結構就可以做到。 概念 上面的解釋如果大家可以理解的話,接    動態規劃 算法是通過拆分問題,定義問題狀態和狀態之間的關係,使得問題能夠以遞推(或者說分治)的方式去解決。它的幾個重要概念如下所述。    階段: 對於一個完整的問題過程,適當的切分為若干個相互聯繫的子問題,每次在求解一個子問題...

我的USB為什麼總是無法識別,到底是為甚麼呢?這真的讓我好困擾

其實判斷軟件硬件問題很簡單,在別的機器或換個系統試試就可以了.有些小的問題不妨先用專門軟件格式化下.還有提醒你WINDOWS下格式化時要選擇FAT,不要選FAT32。 倘若插入後,在右下角彈出電腦正在嘗試連接此USB設備的一些信息,有時會彈出對話框讓用戶選擇,有些用戶還沒看清就點了否,或者因為電腦一些初始的設置問題,禁止了USB的一些功能。解決辦法:右鍵點"我的電腦",選"屬性"--"硬件"--"驅動器簽名",在此選擇"忽略",點"確定"。然後重新插上usb,還是不連的話,再右鍵點"我的電腦"--"屬性"--"硬件"--"設備管理器",從中找到"通用串行總線控制器",右鍵,然後"掃描檢測硬件改動"。如果都不行那就是USB識別程序或U盤的問題從控制面板進入添加或刪除硬件將所有USB設備都刪除,重新安裝需要使用的USB設備驅動程序,重新啟動電腦 USB CONNECTOR   USB CONNECTOR  USB CONNECTOR Orignal From: 我的USB為什麼總是無法識別,到底是為甚麼呢?這真的讓我好困擾

為何 Amazon 併購 Oracle 的可能性很大 ?

  2019 年 9 月份 Trefis 團隊建議《Trefis 建議:谷歌可以斥資 90 億美元收購 Nutanix》,最近又建議亞馬遜收購 Oracle。此文是其和《福布斯》雜誌的 Great Speculations 合作撰寫。   根據 Trefis 分析,亞馬遜併購 Oracle 有望帶來巨大的價值。雖然這個想法聽起來很雄心勃勃,但是為了使自己處於雲技術食物鏈的頂端,Oracle 可能是亞馬遜有史以來最好的收購對象。我們詳細說明為什麼亞馬遜可能會收購 Oracle,還在交互式儀錶板中估計了潛在交易的價值。我們的估計基於 Oracle 的獨立價值以及它作為與亞馬遜合併后的實體中一部分而具有的價值。    為何我們認為亞馬遜會收購 Oracle?      兩家公司的概況: 亞馬遜可能是在 2000 年代中期第一家打造公共雲生態系統的供應商,但 Oracle 從事數據庫業務已有近 40 年的歷史。 AWS 的想法是可以將基礎設施出租給希望存儲和計算資源方面減少費用的客戶。根據 Trefis 的估計,AWS 的企業價值高達 4930 億美元,EV/EBITDA 是 27 倍(2020 年 EBITDA 為 180 億美元)。 Oracle 因第一代雲產品失敗而很晚進入雲市場,該公司隨後在開發方面投入大量資金,旨在向市場推出第二代雲。根據 Trefis 的估計,Oracle 的企業價值應為 2510 億美元,EV/EBITDA 是 12.7 倍(2020 年 EBITDA 為 200 億美元)。 AWS 的方法是創建產品,然後讓用戶採用它。Oracle 已經長期擁有這樣的用戶群,卻無法滿足 AWS 能夠滿足的要求。結果是,儘管 Oracle 運行着全球近 50% 的數據庫,但如今 AWS 在公共雲市場的份額超過 40%,而 Oracle 甚至沒有躋身前五名。   理由1:客戶將獲得第二代架構的安全性和 AWS 的客戶服務,因而導致差異化產品與競爭。 由於市場上面臨微軟 Azure(已成為微軟 B2B 和 B2C 產品的底層結構)、谷歌雲(迎來新的掌門人)和 IBM 雲產品(收購 Red Hat 之後)的競爭,AWS 的先行優勢如今可能在減弱。 對老牌雲領導企業構成不利的另一個因素是,原本可以遷移到...