堆是一种树状的数据结构,它满足堆的特性。最常见的堆有两种:最大堆(每个节点的值都大于或等于其孩子的值)和最小堆(每个节点的值都小于或等于其孩子的值)。
这里,我们将实现一个最小堆。使用数组来存储堆结构是最常见的方法,其中索引0是堆的顶部,其他元素按从左到右,从上到下的顺序排列。
class MinHeap {
constructor() {
this.heap = []; // 使用数组存储堆
}
// 获取父节点的索引
getParentIndex(index) {
return Math.floor((index - 1) / 2);
}
// 获取左孩子的索引
getLeftChildIndex(index) {
return 2 * index + 1;
}
// 获取右孩子的索引
getRightChildIndex(index) {
return 2 * index + 2;
}
// 交换两个节点的值
swap(index1, index2) {
[this.heap[index1], this.heap[index2]] = [this.heap[index2], this.heap[index1]];
}
// 向上调整节点,确保堆的特性不被破坏
siftUp(index) {
let parentIndex = this.getParentIndex(index);
while (index > 0 && this.heap[parentIndex] > this.heap[index]) {
this.swap(parentIndex, index);
index = parentIndex;
parentIndex = this.getParentIndex(index);
}
}
// 向下调整节点,确保堆的特性不被破坏
siftDown(index) {
let leftChildIndex = this.getLeftChildIndex(index);
let rightChildIndex = this.getRightChildIndex(index);
let smallestIndex = index;
if (leftChildIndex < this.heap.length && this.heap[leftChildIndex] < this.heap[smallestIndex]) {
smallestIndex = leftChildIndex;
}
if (rightChildIndex < this.heap.length && this.heap[rightChildIndex] < this.heap[smallestIndex]) {
smallestIndex = rightChildIndex;
}
if (smallestIndex !== index) {
this.swap(smallestIndex, index);
this.siftDown(smallestIndex);
}
}
// 插入一个新元素
insert(value) {
this.heap.push(value);
this.siftUp(this.heap.length - 1); // 调整堆
}
// 获取堆顶元素
getTop() {
return this.heap[0];
}
// 弹出堆顶元素
popTop() {
if (this.heap.length === 0) return null;
let top = this.heap[0];
this.heap[0] = this.heap[this.heap.length - 1];
this.heap.pop();
this.siftDown(0); // 调整堆
return top;
}
// 返回堆的大小
size() {
return this.heap.length;
}
// 检查堆是否为空
isEmpty() {
return this.heap.length === 0;
}
}
最大堆是一种特殊的树状数据结构,其中每个父节点的值都大于或等于其孩子节点的值。使用数组来表示堆是常见的,其中索引0表示堆顶,其他元素从左至右,从上至下排序。
class MaxHeap {
constructor() {
this.heap = []; // 使用数组存储堆
}
// 获取父节点的索引
getParentIndex(index) {
return Math.floor((index - 1) / 2);
}
// 获取左孩子的索引
getLeftChildIndex(index) {
return 2 * index + 1;
}
// 获取右孩子的索引
getRightChildIndex(index) {
return 2 * index + 2;
}
// 交换两个节点的值
swap(index1, index2) {
[this.heap[index1], this.heap[index2]] = [this.heap[index2], this.heap[index1]];
}
// 向上调整节点,确保堆的特性不被破坏
siftUp(index) {
let parentIndex = this.getParentIndex(index);
while (index > 0 && this.heap[parentIndex] < this.heap[index]) {
this.swap(parentIndex, index);
index = parentIndex;
parentIndex = this.getParentIndex(index);
}
}
// 向下调整节点,确保堆的特性不被破坏
siftDown(index) {
let leftChildIndex = this.getLeftChildIndex(index);
let rightChildIndex = this.getRightChildIndex(index);
let largestIndex = index;
if (leftChildIndex < this.heap.length && this.heap[leftChildIndex] > this.heap[largestIndex]) {
largestIndex = leftChildIndex;
}
if (rightChildIndex < this.heap.length && this.heap[rightChildIndex] > this.heap[largestIndex]) {
largestIndex = rightChildIndex;
}
if (largestIndex !== index) {
this.swap(largestIndex, index);
this.siftDown(largestIndex);
}
}
// 插入一个新元素
insert(value) {
this.heap.push(value);
this.siftUp(this.heap.length - 1); // 调整堆
}
// 获取堆顶元素
getTop() {
return this.heap[0];
}
// 弹出堆顶元素
popTop() {
if (this.heap.length === 0) return null;
let top = this.heap[0];
this.heap[0] = this.heap[this.heap.length - 1];
this.heap.pop();
this.siftDown(0); // 调整堆
return top;
}
// 返回堆的大小
size() {
return this.heap.length;
}
// 检查堆是否为空
isEmpty() {
return this.heap.length === 0;
}
}