二叉堆数据结构是一种特殊的二叉树,他能高效、快速的找出最大值和最小值,常应用于优先队列和著名的堆排序算法中。
二叉堆
二叉堆有以下两个特性:
- 是一颗完全二叉树,表示数的每一层都有左侧和右侧子节点(除最后一层的叶节点),并且最后一层的叶节点尽可能是左侧子节点
- 二叉堆不是最小堆就是最大堆,所有节点都大于等于(最大堆)或者小于等于(最小堆)每个他的子节点。
创建最小堆类
class MinHeap {
constructor(compareFn = defaultCompare) {
this.compareFn = compareFn;
this.heap = [];
}
}
二叉堆的数组表示
static getLeftIndex(index) {
return (2 * index) + 1;
}
static getRightIndex(index) {
return (2 * index) + 2;
}
static getParentIndex(index) {
if (index === 0) {
return undefined;
}
return Math.floor((index - 1) / 2);
}
size() {
return this.heap.length;
}
isEmpty() {
return this.size() <= 0;
}
clear() {
this.heap = [];
}
查找二叉堆最小值或者最大值
findMinimum() {
return this.isEmpty() ? undefined : this.heap[0];
}
交换函数实现
function swap(array, a, b) {
/* const temp = array[a];
array[a] = array[b];
array[b] = temp; */
[array[a], array[b]] = [array[b], array[a]];
}
向堆中插入新值
insert(value) {
if (value != null) {
const index = this.heap.length;
this.heap.push(value);
this.siftUp(index);
return true;
}
return false;
};
//上移操作
siftUp(index) {
let parent = this.getParentIndex(index);
while (
index > 0
&& this.compareFn(this.heap[parent], this.heap[index]) === Compare.BIGGER_THAN
) {
swap(this.heap, parent, index);
index = parent;
parent = this.getParentIndex(index);
}
}
二叉堆中导出最大值或最小值
extract() {
if (this.isEmpty()) {
return undefined;
}
if (this.size() === 1) {
return this.heap.shift();
}
const removedValue = this.heap[0];
this.heap[0] = this.heap.pop();
this.siftDown(0);
return removedValue;
};
//下移操作
siftDown(index) {
let element = index;
const left = MinHeap.getLeftIndex(index);
const right = this.getRightIndex(index);
const size = this.size();
if (
left < size
&& this.compareFn(this.heap[element], this.heap[left]) === Compare.BIGGER_THAN
) {
element = left;
}
if (
right < size
&& this.compareFn(this.heap[element], this.heap[right]) === Compare.BIGGER_THAN
) {
element = right;
}
if (index !== element) {
swap(this.heap, index, element);
this.siftDown(element);
}
}
创建最大堆类
class MaxHeap extends MinHeap {
constructor(compareFn = defaultCompare) {
super(compareFn);
this.compareFn = compareFn;
this.compareFn = reverseCompare(compareFn);
}
}
其他操作跟最小堆类一样,这里就不多加赘述。
堆排序算法
heapify(array) {
if (array) {
this.heap = array;
}
const maxIndex = Math.floor(this.size() / 2) - 1;
for (let i = 0; i <= maxIndex; i++) {
this.siftDown(i);
}
return this.heap;
};
getAsArray() {
return this.heap;
};
//构建最大堆函数
function buildMaxHeap(array, compareFn) {
for (let i = Math.floor(array.length / 2);i >= 0; i -= 1){
heapify(array, i, array.length, compareFn);
return array;
}
}
//堆排序算法实现
function heapSort(array, compareFn = defaultCompare) {
let heapSize = array.length;
//用数组创建一个最大堆用作源数据
buildMaxHeap(array, compareFn);
while(heapSize > 1){
//创建最大堆后,最大的值会被存储在堆的第一个位置,我们将它替换为堆的最后一个值,将堆的大小-1
swap(array, 0, --heapSize);
//将堆的根节点下移并重复步骤2直到堆的大小为1
heapify(array, 0, heapSize, compareFn);
}
return array;
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。