這篇文章帶給大家的內容是關於JavaScript中二元樹(二元堆)的介紹(程式碼範例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。
二元樹
二元樹(Binary Tree)是一種樹狀結構,它的特徵是每個節點最多只有兩個分支節點,一棵二元樹通常由根節點,分支節點,葉節點組成。而每個分支節點也常被稱為一棵子樹。
根節點:二元樹最頂層的節點
在二元樹中,我們常常也會用父節點和子節點來描述,比如圖中2為6和3的父節點,反之6和3是2子節點
二元樹的陣列表示
#透過上圖我們可以分析得到陣列表示的完全二元樹擁有以下幾個性質:
#從上圖可以看出:
sort:排序
儲存陣列長度
class Heap{ constructor(arr){ this.data = [...arr]; this.size = this.data.length; } }
max-heapify是把每一個不滿足最大堆性質的分支節點進行調整的一個操作。
如上圖:
#調整分支節點2(分支節點2不滿足最大堆的性質)
預設該分支節點為最大值
#將2與左右分支比較,從2,12, 5中找出最大值,然後和2交換位置
根據上面所將的二元堆性質,分別得到分支節點2的左節點和右節點
比較三個節點,得到最大值的下標max
#如果該節點本身就是最大值,則停止操作
將max節點與父節點交換
重複step2的運算,從2,4,7找出最大值與2做交換
遞迴
maxHeapify(i) { let max = i; if(i >= this.size){ return; } // 当前序号的左节点 const l = i * 2 + 1; // 当前需要的右节点 const r = i * 2 + 2; // 求当前节点与其左右节点三者中的最大值 if(l this.data[max]){ max = l; } if(r this.data[max]){ max = r; } // 最终max节点是其本身,则已经满足最大堆性质,停止操作 if(max === i) { return; } // 父节点与最大值节点做交换 const t = this.data[i]; this.data[i] = this.data[max]; this.data[max] = t; // 递归向下继续执行 return this.maxHeapify(max); }
我們可以看到,剛初始化的堆由陣列表示,這時候它可能無法滿足一個最大堆或最小堆的性質,而這個時候我們可能需要去將整個堆建成我們想要的。
上面我們做了max-heapify操作,而max-heapify只是將某一個分支節點進行調整,而要將整個堆構建成最大堆,則需要將所有的分支節點都進行一次max-heapify操作,如下圖,我們需要依序對12,3,2,15這4個分支節點進行max-hepify操作
##具體步驟:
rebuildHeap(){ // 叶子节点 const L = Math.floor(this.size / 2); for(let i = L - 1; i>=0; i--){ this,maxHeapify(i); } }
將最後個元素從堆中拿出,相當於堆的size-1
然後在堆根節點進行一次max-heapify操作
sort() { for(let i = this.size - 1; i > 0; i--){ swap(this.data, 0, i); this.size--; this.maxHeapify(0); } }
insert(key) { this.data[this.size] = key; this.size++ if (this.isHeap()) { return; } this.rebuildHeap(); }
delete(index) { if (index >= this.size) { return; } this.data.splice(index, 1); this.size--; if (this.isHeap()) { return; } this.rebuildHeap(); }
/** * 最大堆 */ function left(i) { return i * 2 + 1; } function right(i) { return i * 2 + 2; } function swap(A, i, j) { const t = A[i]; A[i] = A[j]; A[j] = t; } class Heap { constructor(arr) { this.data = [...arr]; this.size = this.data.length; } /** * 重构堆 */ rebuildHeap() { const L = Math.floor(this.size / 2); for (let i = L - 1; i >= 0; i--) { this.maxHeapify(i); } } isHeap() { const L = Math.floor(this.size / 2); for (let i = L - 1; i >= 0; i++) { const l = this.data[left(i)] || Number.MIN_SAFE_INTEGER; const r = this.data[right(i)] || Number.MIN_SAFE_INTEGER; const max = Math.max(this.data[i], l, r); if (max !== this.data[i]) { return false; } return true; } } sort() { for (let i = this.size - 1; i > 0; i--) { swap(this.data, 0, i); this.size--; this.maxHeapify(0); } } insert(key) { this.data[this.size++] = key; if (this.isHeap()) { return; } this.rebuildHeap(); } delete(index) { if (index >= this.size) { return; } this.data.splice(index, 1); this.size--; if (this.isHeap()) { return; } this.rebuildHeap(); } /** * 堆的其他地方都满足性质 * 唯独跟节点,重构堆性质 * @param {*} i */ maxHeapify(i) { let max = i; if (i >= this.size) { return; } // 求左右节点中较大的序号 const l = left(i); const r = right(i); if (l this.data[max]) { max = l; } if (r this.data[max]) { max = r; } // 如果当前节点最大,已经是最大堆 if (max === i) { return; } swap(this.data, i, max); // 递归向下继续执行 return this.maxHeapify(max); } } module.exports = Heap;
以上是JavaScript中二元樹(二元堆)的介紹(程式碼範例)的詳細內容。更多資訊請關注PHP中文網其他相關文章!