二叉堆的定義:
二叉堆是一顆完全二叉樹(shù)。
完全二叉樹(shù):把元素順序排列成樹(shù)的形狀。這里的順序是自上而下,從左到右。
最大堆:
????最大堆是一種特殊的二叉堆,頂部為最大元素,并且每個(gè)子樹(shù)的根節(jié)點(diǎn)大于等于左右孩子節(jié)點(diǎn)。
? ? 我們可以用數(shù)組來(lái)存放最大堆的每個(gè)元素,如下圖:
其中,根節(jié)點(diǎn)的下標(biāo)為 0 ,每個(gè)子樹(shù)中父親節(jié)點(diǎn)和左右孩子節(jié)點(diǎn)的下標(biāo)關(guān)系為: parent(i) = (i - 1)/2;leftChild(i) = 2*i + 1;rightChild(i) = 2*i + 2。
最大堆的結(jié)構(gòu):
泛型必須具有可比性。
最大堆的父親節(jié)點(diǎn)和左右孩子下標(biāo)的關(guān)系:
向最大堆添加元素:
????思路:首先向數(shù)組的末尾新增元素,然后比較新元素(末尾元素)的值與其父親元素的值,如果前者大于等于后者,則不符合最大堆的規(guī)則,需要上浮操作(交換二者的值),上浮操作完成之后,繼續(xù)對(duì)比,直到符合最大堆規(guī)則為止。
向最大堆取出元素(最大值):
????最大堆只能取出最大值,因?yàn)樗灰獫M足父親節(jié)點(diǎn)大于等于左右孩子就行了,所以左右孩子位置可以互換,即無(wú)法通過(guò)下標(biāo)找到其他節(jié)點(diǎn),這就是最大堆的限制。
? ? 思路:先在數(shù)組的頭部找出最大元素,然后讓數(shù)組的末尾元素替換頭部元素,并且刪除末尾元素。然后讓頭節(jié)點(diǎn)和其左右孩子中較大值進(jìn)行比較,如果前者小于后者,則需要下沉(交換二者的值)。下沉操作完成之后,繼續(xù)對(duì)比,直到符合最大堆規(guī)則為止。
向最大堆中取出最大元素后,放入一個(gè)新元素:
? ? 思路:找到數(shù)組的頭部的,將新元素替換為頭部元素,然后執(zhí)行下沉操作。
將任意數(shù)組整理成最大堆的形狀:
????思路:使用構(gòu)造函數(shù),將傳入的數(shù)組轉(zhuǎn)換為集合并賦值給 data,然后找到最后一個(gè)非葉子的節(jié)點(diǎn)(最后一個(gè)元素的父親節(jié)點(diǎn)),即 index = parent(arr.length - 1),從最后一個(gè)非葉子結(jié)點(diǎn)開(kāi)始往上遍歷,執(zhí)行下沉操作。因?yàn)橄鲁敛僮鲿?huì)涉及到左右孩子,所以已經(jīng)能夠比較到所有元素了。
將最大堆封裝成優(yōu)先隊(duì)列PriorityQueue:
優(yōu)先隊(duì)列:普通隊(duì)列為先進(jìn)先出,然而優(yōu)先隊(duì)列出隊(duì)列卻是優(yōu)先度最高的元素,
優(yōu)先度是可以根據(jù)業(yè)務(wù)自定義的。我們就可以約定元素值越大,優(yōu)先級(jí)越高。故最大堆可以很容易的符合,因?yàn)樗淖畲笤鼐褪菙?shù)組首位。