AcWing算法基础课 堆

堆可以用二叉树存储。

当前节点比左右子节点的值都小或等于(小根堆)。

对于完全二叉树,根节点编号为1,则,对于编号为n的节点,左子节点编号为2n,右子节点标号为2n+1。

完全二叉树可以用一维数组存储(编号→下标)

基本操作:up和down

up:当节点数值比父节点小时,交换当前节点与父节点的值,然后递归。

down:当前节点数值比子节点大时,交换当前节点与较小的子节点的值,然后递归。

用于修改节点的值。

堆的操作:

1、插入一个数:在数组的末尾插入,然后进行up操作。heap[++size]=x; up(size);

2、求堆中最小值:返回第一个元素。heap[1];

3、删除最小值(堆顶元素),用数组中最后一个元素覆盖最小值,size--,然后进行down,heap[1]=heap[size]; size--; down(1);

4、删除任意元素,用数组中最后一个元素覆盖。heap[k]=heap[size]; up(k) or down(k) or not;

5、修改任意元素,然后调整。 heap[k]=x; up(k) or down(k) or not;

 

o(n)的快速建堆方式

在heap中读取全部元素

然后对n/2~1进行down()

for(int i=n/2;i;i--) down(i);

可以认为n/2后的节点位于叶节点位置,不需要down,其他的需要从下到上down()

 

带映射的堆:dijkstra算法中需要用

ph[k]记录第k个插入节点在数组中的位置,

hp[k]记录数组中第k个节点是第几个插入的,

ph与hp互为反函数

swap→heap_swap

void heap_swap(int a,int b)

{

  swap(ph[hp[a]],ph[hp[b]]);

  swap(hp[a],hp[b]);

  swap[heap[a],heap[b]];

}

 

posted @ 2021-12-19 20:42  80k  阅读(65)  评论(0)    收藏  举报