Heap——数据结构之堆

来源:互联网 发布:淘宝美工兼职招聘 编辑:程序博客网 时间:2024/06/06 03:30

简介堆

堆是一种数据结构,是一棵二叉树(尽量地满足完全二叉树的规律)。他有一个特点,就是两个儿子的值均大于或小于父节点。那么这个堆就被称为大顶堆或小顶堆。同一级的元素不比较大小,它可以用到优先队列之中,还有其他很神奇的应用。

操作

I.维护队的性质

其实就是一个步骤:如果它不满足堆的性质,那么就继续维护,否则结束。
1.向上维护
如果节点x与它的父亲x/2的关系不合法,则x与x/2交换。

void up(LL x){    LL p=x;    while (p>1 && d[p/2]<d[p])swap(d[p],d[p/2]),p/=2;}

2.向下维护
如果节点x与它的儿子的关系不合法,则比较左儿子和右二子的大小,较大(或较小)的那个和x交换。

void down(LL x){    LL l=x*2,r=x*2+1;    while (l<=tot && d[x]<=d[l] || (r<=tot) && d[x]<=d[r])    {        LL mx=l;        if (r<=tot && d[r]>d[l]) mx=r;//比较大小        swap(d[x],d[mx]);x=mx;        l=x*2,r=x*2+1;    }}

II.建立堆

首先我们要将一个数组转化成一个堆。那么我们对于数组中的每一个元素,都要维护堆的性质。

void build(){    for(int i=tot/2;i>=1;i--) down(i);    //其中tot表示这个数组的元素个数。}

III.删除堆顶的元素

当我们要取最优值的时候,我们要将堆顶的元素删掉,然后最后一个元素到堆顶,维护堆。

void del(LL x){    if (d[tot]<d[x])    {        memcpy(d[x],d[tot],sizeof(d[x]));tot--;        down(x);    } else    {        memcpy(d[x],d[tot],sizeof(d[x]));tot--;        up(x);    }}

PS:删除操作可以应用到优先队列之中

IV.插入操作

向堆中添加一个元素到堆末,然后向上维护堆。

void ins(LL x){    d[++tot]=x;    up(tot);}

总结

堆时间复杂度:O(nlogn)
堆多应用于优先队列或者是堆排序。
堆是一个重要的数据结构,在很多题目中容易遇到。

3 0
原创粉丝点击