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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

二叉堆是什么?

發(fā)布時間:2024/1/23 编程问答 57 豆豆
生活随笔 收集整理的這篇文章主要介紹了 二叉堆是什么? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

二叉堆是一種應(yīng)用很廣的數(shù)據(jù)結(jié)構(gòu),今天,我們就來簡單講講二叉堆。

什么是二叉堆?

?

二叉堆是一種特殊的堆。具有如下的特性:

  • 具有完全二叉樹的特性。

  • 堆中的任何一個父節(jié)點的值都大于等于它左右孩子節(jié)點的值,或者都小于等于它左右孩子節(jié)點的值。

  • 根據(jù)第二條特性,我們又可以把二叉堆分成兩類:

    1、最大堆:父節(jié)點的值大于等于左右孩子節(jié)點的值。

    ? ? ? ? ? ?

    2.最小堆:父節(jié)點的值小于等于左右孩子節(jié)點的值。

    ? ? ??

    ? ? 我們把二叉堆的根節(jié)點稱之為堆頂。根據(jù)二叉堆的特性,堆頂要嘛是整個堆中的最大元素,要嘛是最小元素

    今天,我們主要來講講二叉堆的三個主要操作:

  • 插入一個節(jié)點。

  • 刪除一個節(jié)點。

  • 構(gòu)建一個二叉堆。

  • 不過這里需要注意的是,在二叉堆這種結(jié)構(gòu)中,對于刪除一個節(jié)點,我們一般刪的是根節(jié)點

    下面我們以最小堆為例子,來講講這些操作。

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?插入一個節(jié)點

    剛才我們說二叉堆具有完全二叉樹的特性,因此,我們在插入一個節(jié)點的時候,應(yīng)該先保證節(jié)點插入后,它仍然是一顆完全二叉樹,然后再來進行調(diào)整,使它滿足二叉堆的另一個特性。

    所以,在插入的時候,我們把新節(jié)點插到完全二叉樹的最后一個位置。例如:

    ?

    插入0

    之后我們再來進行調(diào)整,調(diào)整的原則是:讓新插入的節(jié)點與它的父節(jié)點進行比較,如果新節(jié)點小于父節(jié)點,則讓新節(jié)點上浮,即和父節(jié)點交換位置。

    上浮之后繼續(xù)和它的父節(jié)點進行比較,直到父節(jié)點的值小于或等于該節(jié)點,才停止上浮,即插入結(jié)束。例如:

    0比5小,上浮。

    0比2小于,上浮。

    0比1小,上浮。

    已經(jīng)到達堆頂了,插入結(jié)束。

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?刪除節(jié)點

    ?

    前面說了,刪除節(jié)點一般刪除的是根節(jié)點。

    和插入一樣,由于二叉堆具有完全二叉樹的特性,因為刪除時候,首先我們是要馬上恢復(fù)它具有完全二叉樹的特性,所以我們是采取這樣的策略:把根節(jié)點刪除之后,用二叉堆的最后一個元素頂替上來,然后在進行調(diào)整恢復(fù)。例如:

    把0刪除了之后,5替換上來。

    之后再來調(diào)整,調(diào)整的規(guī)則和插入差不多類似,采取下沉的策略:讓5和左右孩子節(jié)點相比較,如果左右節(jié)點有小于5的,則讓那個較小的孩子代替5的位置,然后5下沉。

    下沉之后,5繼續(xù)和左右孩子相比,直到左右孩子都大于或等于5才結(jié)束。

    如:5比1,3都大,1代替5的位置

    5比4,2都大,2代替5的位置。

    5已經(jīng)不在具有左右孩子了,刪除結(jié)束。

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 構(gòu)建二叉堆

    ?

    所謂構(gòu)建,就是給你一個有n個節(jié)點的無序的完全二叉樹,然后把它構(gòu)建成二叉堆。

    剛才我們在刪除一個節(jié)點的時候,把最后一個元素補到根元素的位置上去,然后再讓這個元素依次下沉,實際上,在這個元素還沒有下沉之前,它就可以看作是一顆無序的完全二叉樹了

    也就是說,要把一個無序的完全二叉樹調(diào)整為二叉堆,我們可以讓所有非葉子節(jié)點依次下沉。不過下沉的順序不是從根節(jié)點開始下沉(想一下相必你就 知道不能從根節(jié)點開始下沉),而是從下面的非葉子節(jié)點下稱,在依次往上。舉個例子:

    對于這樣一顆無序的完全二叉樹

    8進行下沉。

    接著,5進行下沉。

    2沒問題,之后讓7進行下沉

    調(diào)整完成,構(gòu)建結(jié)束。

    ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?代碼實現(xiàn)

    ?

    不過這里需要說明的是,我們二叉樹一般是采用鏈表的方式來實現(xiàn)的,但二叉堆我們是采用數(shù)組的方式來存儲的。

    如果知道了一個節(jié)點的位置,如何知道一個節(jié)點的左右孩子節(jié)點的位置呢?

    這其實不難,根據(jù)完全二叉樹的特點,假如一個節(jié)點的下標(biāo)為n,則可以求得它左孩子的下標(biāo)為:2?n+1;右孩子下標(biāo)為:2?n+2。

    下面是構(gòu)建代碼的實現(xiàn):

    public class BinaryHeap {/*上浮操作,對插入的節(jié)點進行上浮 * @param arr* @param length : 表示二叉堆的長度*/public static int[] upAdjust(int arr[], int length) {//標(biāo)記插入的節(jié)點int child = length - 1;//其父親節(jié)點int parent = (child - 1) / 2;//把插入的節(jié)點臨時保存起來int temp = arr[child];//進行上浮while(child > 0 && temp < arr[parent]) {//其實不用進行每次都進行交換,單向賦值就可以了//當(dāng)temp找到正確的位置之后,我們再把temp的值賦給這個節(jié)點arr[child] = arr[parent];child = parent;parent = (child - 1) / 2;}//退出循環(huán)代表找到正確的位置arr[child] = temp;return arr;}/***//*** 下沉操作,執(zhí)行刪除操作相當(dāng)于把最后* * 一個元素賦給根元素之后,然后對根元素執(zhí)行下沉操作* @param arr* @param parent 要下沉元素的下標(biāo)* @param length 數(shù)組長度*/public static int[] downAdjust(int[] arr, int parent, int length) {//臨時保證要下沉的元素int temp = arr[parent];//定位左孩子節(jié)點位置int child = 2 * parent + 1;//開始下沉while (child < length) {//如果右孩子節(jié)點比左孩子小,則定位到右孩子if (child + 1 < length && arr[child] > arr[child + 1]) {child++;}//如果父節(jié)點比孩子節(jié)點小或等于,則下沉結(jié)束if (temp <= arr[child])break;//單向賦值arr[parent] = arr[child];parent = child;child = 2 * parent + 1;}arr[parent] = temp;return arr;}/*** 構(gòu)建操作** @param arr*/public static int[] buildHead(int[] arr,int length) {//從最后一個非葉子節(jié)點開始下沉for (int i = (length - 2) / 2; i >= 0; i--) {arr = downAdjust(arr, i, length);}return arr;} }

    參考鏈接:https://mp.weixin.qq.com/s?__biz=MzUxNzg0MDc1Mg==&mid=2247484201&idx=1&sn=9cbea904fbe08b85b6aeb54a8ea7d7bb&chksm=f9934936cee4c0202cac39df919bce12f1501e2fc211551806254a7a7f4fe1360913415594a1&scene=21#wechat_redirect

    總結(jié)

    以上是生活随笔為你收集整理的二叉堆是什么?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。