返回
JavaScript 堆数据结构与操作指南
前端
2024-01-05 01:44:01
摘要
JavaScript 中的堆数据结构以其快速的操作速度和广泛的应用场景而备受关注。本文将深入探究堆的原理、性质以及 JavaScript 中的堆实现,并通过实际案例演示其在各种场景中的应用。
正文
一、堆数据结构概述
堆是一种特殊的完全二叉树,其每个节点都满足堆的性质:
- 最大堆:每个节点的值都大于或等于其子节点的值。
- 最小堆:每个节点的值都小于或等于其子节点的值。
堆通常用数组表示,其中数组中的每个元素都对应于二叉树中的一个节点。
二、JavaScript 中的堆实现
1. 定义堆
class Heap {
constructor(arr, comparator) {
this.heap = arr ? [...arr] : [];
this.comparator = comparator || ((a, b) => a - b);
this.buildHeap();
}
buildHeap() {
for (let i = Math.floor(this.heap.length / 2) - 1; i >= 0; i--) {
this.heapify(i);
}
}
heapify(i) {
const left = 2 * i + 1;
const right = 2 * i + 2;
let largest = i;
if (left < this.heap.length && this.comparator(this.heap[left], this.heap[largest]) > 0) {
largest = left;
}
if (right < this.heap.length && this.comparator(this.heap[right], this.heap[largest]) > 0) {
largest = right;
}
if (largest !== i) {
[this.heap[i], this.heap[largest]] = [this.heap[largest], this.heap[i]];
this.heapify(largest);
}
}
insert(value) {
this.heap.push(value);
this.heapifyUp(this.heap.length - 1);
}
heapifyUp(i) {
let parent = Math.floor((i - 1) / 2);
while (i > 0 && this.comparator(this.heap[i], this.heap[parent]) > 0) {
[this.heap[i], this.heap[parent]] = [this.heap[parent], this.heap[i]];
i = parent;
parent = Math.floor((i - 1) / 2);
}
}
remove() {
if (this.heap.length === 0) {
return null;
}
const value = this.heap[0];
this.heap[0] = this.heap.pop();
this.heapifyDown(0);
return value;
}
heapifyDown(i) {
const left = 2 * i + 1;
const right = 2 * i + 2;
let smallest = i;
if (left < this.heap.length && this.comparator(this.heap[left], this.heap[smallest]) < 0) {
smallest = left;
}
if (right < this.heap.length && this.comparator(this.heap[right], this.heap[smallest]) < 0) {
smallest = right;
}
if (smallest !== i) {
[this.heap[i], this.heap[smallest]] = [this.heap[smallest], this.heap[i]];
this.heapifyDown(smallest);
}
}
peek() {
return this.heap[0];
}
size() {
return this.heap.length;
}
isEmpty() {
return this.heap.length === 0;
}
}
三、堆的应用
1. 堆排序
堆排序是一种基于堆数据结构的排序算法,其时间复杂度为 O(n log n)。
function heapSort(arr) {
const heap = new Heap(arr, (a, b) => b - a);
const sortedArr = [];
while (!heap.isEmpty()) {
sortedArr.push(heap.remove());
}
return sortedArr;
}
2. 优先队列
优先队列是一种数据结构,其中元素按照优先级排序,优先级最高的元素排在最前面。堆可以很容易地实现优先队列,因为堆的根节点始终是优先级最高的元素。
class PriorityQueue {
constructor(comparator) {
this.heap = new Heap([], comparator);
}
enqueue(value) {
this.heap.insert(value);
}
dequeue() {
return this.heap.remove();
}
peek() {
return this.heap.peek();
}
size() {
return this.heap.size();
}
isEmpty() {
return this.heap.isEmpty();
}
}
总结
堆数据结构在 JavaScript 中有着广泛的应用,其快速的操作速度和简单的实现方式使其成为许多场景的理想选择。通过本文的讲解,您已经对堆的数据结构和实现有了深入的了解,可以将其应用到自己的项目中。