一、堆的简介
堆(英语:heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质:
堆中某个节点的值总是不大于或不小于其父节点的值;
堆总是一棵完全二叉树。
大顶堆:每个节点的值都大于或者等于它的左右子节点的值。
小顶堆:每个节点的值都小于或者等于它的左右子节点的值。
堆的定义如下:
n个元素的序列{k1,k2,ki,…,kn}当且仅当满足下关系时,称之为堆。
(ki <= k2i,ki <= k2i+1)或者(ki >= k2i,ki >= k2i+1), (i = 1,2,3,4...n/2)
二、堆的实现
1、结点数据结构
const max = 1000;
function Heap() {
this.heap = [max];//0号位为哨兵位
this.length = 0;
}
2、插入元素
在插入的时候,首先将数据放置到完全二叉树的下一个子节点上。然后判断其与父节点值得大小,如果父节点的值小,那么将父节点和子节点的值进行交换;交换完成之后,接着判断插入数值所在的节点与其父节点的值大小,如果仍旧是父节点的数值小,则继续交换……直到满足父节点的数值更大或者不存在父节点的情况发生。insert(value) {
this.length++;
let i = this.length
for (; this.heap[Math.floor(i / 2)] < value; i = Math.floor(i / 2)) {
this.heap[i] = this.heap[Math.floor(i / 2)];
}
this.heap[i] = value;
}
3、删除元素
按定义,堆中每次都只能删除第0个数据。为了便于重建堆,实际的操作是将最后一个数据的值赋给根结点,然后再从根结点开始进行一次从上向下的调整。调整时先在左右儿子结点中找最小的,如果父结点比这个最小的子结点还小说明不需要调整了,反之将父结点和它交换后再考虑后面的结点。相当于从根结点将一个数据的“下沉”过程。 delete() {
if (this.isEmpty()) {
console.log("堆已经为空");
return;
}
let parent = 1;
let max_node = this.heap[1];
let tmp = this.heap[this.length--];
for (; parent * 2 <= this.length;)
{
let child = parent * 2;
if (child != this.length && this.heap[child] < this.heap[child + 1]) {
child++;
}
if (tmp > this.heap[child]) {
break;
}
else {
this.heap[parent] = this.heap[child];
}
parent = child;
}
this.heap[parent] = tmp;
this.heap.length--;
return max_node;
},
4、判断堆是否为空
isEmpty() {
return this.length == 0;
},
5、创建堆
创建堆的思想是首先将所以元素都添加到数组中,然后再调整为堆,由删除操作我们可以联想到如果左右孩子都是堆,我们只要通过下沉操作就可以调整堆,而我们从堆顶元素开始并不都是堆,所以我们想到从底部开始,而最后一个结点的父亲结点开始往前的节点的和他们的左右孩子满足堆的定义,所以我们就从最后一个结点的父节点开始构造堆。max_heap(p)
{
let child = 2 * p;
if (child != this.length && this.heap[child] < this.heap[child + 1]) {
child++;
}
if (this.heap[p] < this.heap[child]) {
let tmp = this.heap[p];
this.heap[p] = this.heap[child];
this.heap[child] = tmp;
max_heap(child);
}
}
create(...arg) {
arg.forEach(item => {
this.heap[++this.length] = item;
});
let p = Math.floor(this.length / 2);
while(p>0)
{
max_heap(p);
p--;
}
}
6、堆排序
有了前面的操作,堆排序就是在前面的基础上,建堆,在一次删除堆顶元素就可以了function heap_sort(A)
{
let heap=new Heap();
heap.create(...A);//初始化堆
console.log(heap.heap)
for(let i=0;i<A.length;i++)
{
A[i]=heap.delete();
}
}