在 JavaScript 中实现最大堆在我们开始构建最大堆之前,先看一下我们将实现的一些方法及其用途:
- _percolateUp():将堆属性从子节点恢复到根节点 。
- _maxHeapify():将堆属性从特定节点恢复到叶节点 。
- insert():将给定值附加到堆数组并根据元素的堆属性重新排列元素 。在每个新插入中 , 堆均匀增长,并且大小增加一 。
- getMax():返回堆(根节点)中的最大值 , 不修改堆 。注意这里的时间复杂度是常数时间氧(1)欧(1 )
- removeMax():返回并删除堆中的最大值(想想pop()) 。该函数的时间复杂度为O ( log ( n ) )。
如果堆大小大于一,它将最大值存储到变量中 , 将该值与最后一个叶子交换,然后从堆中删除最大值 。该__percolateUp()方法在每个父节点上递归调用 , 直到到达根 。对于要定位在 max-heap 属性之后的每个节点,我们__maxHeapify()从堆底部开始在该数组的每个索引处调用该方法 。
如果堆只有一个元素 , 则删除并返回该元素的值,最后一个条件是如果堆为空,则返回 null 。
class maxHeap {constructor() {this.heap = [];this.elements = 0;};insert(val) {if (this.elements >= this.heap.length) {this.elements = this.elements + 1;this.heap.push(val);this.__percolateUp(this.heap.length - 1);}else {this.heap[this.elements] = val;this.elements = this.elements + 1;this.__percolateUp(this.elements - 1);}};getMax() {if (this.elements !== 0)return this.heap[0];return null;};removeMax() {let max = this.heap[0];if (this.elements > 1) {this.heap[0] = this.heap[this.elements - 1];this.elements = this.elements - 1;this.__maxHeapify(0);return max} else if (this.elements === 1) {this.elements = this.elements - 1;return max;} else {return null;}};__percolateUp(index) {const parent = Math.floor((index - 1) / 2);if (index <= 0)returnelse if (this.heap[parent] < this.heap[index]) {let tmp = this.heap[parent];this.heap[parent] = this.heap[index];this.heap[index] = tmp;this.__percolateUp(parent);}};__maxHeapify(index) {let left = (index * 2) + 1;let right = (index * 2) + 2;let largest = index;if ((this.elements > left) && (this.heap[largest] < this.heap[left])) {largest = left}else if ((this.elements > right) && (this.heap[largest] < this.heap[right]))largest = rightelse if (largest !== index) {const tmp = this.heap[largest];this.heap[largest] = this.heap[index];this.heap[index] = tmp;this.__maxHeapify(largest);}};buildHeap(arr) {this.heap = arr;this.elements = this.heap.length;for (let i = this.heap.length - 1; i >= 0; i--) {this.__maxHeapify(i);}};};let heap = new maxHeap();
如何构建最小堆直观上,我们可以说最小堆中的元素遵循最小堆属性,因为这与最大堆相反 。父节点的键始终小于两个子节点的键 。为了构建最小堆,我们:- 在堆的末尾(最后一层)创建一个新的子节点 。
- 将新键添加到该节点(将其附加到数组) 。
- 向上移动子节点 , 直到到达根节点并且满足堆属性 。
- 删除根节点 。
- 将最后一个子项的密钥移至 root 。
- 将父节点与其子节点进行比较 。
- 如果父节点的值大于子节点,则交换它们,并重复直到满足堆属性 。
class minHeap {constructor() {this.heap = []this.elements = 0;};insert(val) {if (this.elements >== this.heap.length) {this.elements = this.elements + 1this.heap.push(val);this.__percolateUp(this.heap.length - 1);}else {this.heap[this.elements] = val;this.elements = this.elements + 1;this.__percolateUp(this.elements - 1);}};getMin() {if (this.heap.length !== 0)return this.heap[0];return null;}removeMin() {const min = this.heap[0];if (this.elements > 1) {this.heap[0] = this.heap[this.elements - 1];this.elements = this.elements - 1;this.__minHeapify(0);return min;} else if (this.elements == 1) {this.elements = this.elements - 1;return min;} else {return null;}};__percolateUp(index) {let parent = Math.floor((index - 1) / 2);if (index <= 0)returnelse if (this.heap[parent] > this.heap[index]) {let tmp = this.heap[parent];this.heap[parent] = this.heap[index];this.heap[index] = tmp;this.__percolateUp(parent);}};__minHeapify(index) {let left = (index * 2) + 1;let right = (index * 2) + 2;let smallest = index;if ((this.elements > left) && (this.heap[smallest] > this.heap[left])) {smallest = left;}if ((this.elements > right) && (this.heap[smallest] > this.heap[right]))smallest = right;if (smallest !== index) {let tmp = this.heap[smallest];this.heap[smallest] = this.heap[index];this.heap[index] = tmp;this.__minHeapify(smallest);}}buildHeap(arr) {this.heap = arr;this.elements = this.heap.length;for (let i = this.heap.length - 1; i >= 0; i--) {this.__minHeapify(i)}}};let heap = new minHeap();heap.insert(12);heap.insert(10);heap.insert(-10);heap.insert(100);console.log(heap.getMin()); //你应该得到-10let newheap = new minHeap();let arr = [12, 6, 8, 3, 16, 4, 27];newheap.buildHeap(arr) //使用数组中的元素构建这个堆console.log(newheap.getMin()) //这里记录了 3newheap.removeMin();console.log(newheap.getMin())
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 掌握Python的解包技巧:*和**的最全用法
- 新手应该如何避免过度健身?
- 如何在户外进行有效的慢跑
- 太极拳如何做到脚下生根?
- 怎么保养化妆刷 如何正确清洗保养化妆刷
- 有了乳液,还要用面霜吗?学习如何选择最适合自己肌肤的护肤方法
- 看vivo手机如何换电池,iqoo手机怎么能换原装电池
- 怎样除去杯子上的标签贴纸,如何干净地去除杯子上的标签
- ppt能咋全屏显示,ppt如何使表格全屏显示
- 衣服掉色如何办 衣服掉色怎么能恢复