基本数据结构——二叉堆

Posted uninstalllingyi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基本数据结构——二叉堆相关的知识,希望对你有一定的参考价值。

迅速补档,为A*做一下铺垫…

概念定义

二叉堆就是一个支持插入、删除、查询最值的数据结构。他其实是一棵完全二叉树。那么堆一般分为大根堆和小根堆

大根堆

树中的任意一个节点的权值都小于或者等于其父节点的权值,则称该二叉树满足大根堆性质。

小根堆

树中的任意一个节点的权值都大于或者等于其父节点的权值,则称该二叉树满足小根堆性质。

习惯用法

一般习惯把堆用数组保存。才用父子二倍的编号方式。即:对于某一个节点x,其左儿子节点为2*x,右儿子节点为x*2+1

支持功能及代码实现

Insert插入

向二叉堆中插入一个节点。我们首先把这个节点放在堆的末尾,然后再向上层层递归更新。时间复杂度为O(log N)

int heap[Size],n;
void up(int p)
    while(p>1)
        if(heap[p]>heap[p/2])
            swap(heap[p],heap[p/2]);
            p/=2;
        
        else
            break;
        
    

void Insert(int val)
    heap[++n]=val;
    up(n);
 

注:编者在写这篇博文的时候,由于内容过于基础,所以手速大约为20迈。如若有代码错误,敬请指出与纠正。

GetTop取首

返回二叉堆堆顶的值,时间复杂度O(1)

int GetTop()
    return heap[1];

Extract去首

操作原理是将堆首取出,然后与堆尾发生交换,然后通过自减操作删除堆尾,再进行一次向下更新。时间复杂度为O(log N)

void Down(int p)
    int s=p*2;//p的左儿子
    while(s<=n)
        if(s<n&&heap[s]<heap[s+1])
            s++;//取左右两儿子中较大者的编号 
        
        if(heap[s]>heap[p])
            swap(heap[s],heap[p]);
            //这里是大根堆,所以如果子节点大于父节点,是不满足性质的。
            p=s,s=p*2; 
        
        else
            break;
        
     

void Extract()
    heap[1]=heap[n--];
    down(1);

Remove删除

这个操作实现把下标为p的节点删除。这玩意和Extract相似,把heap[p]和heap[n]交换,然后n自减。但这时候到底需要向下更新还是向上更新并不好说。所以我们两个都要。

void Remove(int k)
    heap[k]=heap[n--];
    up(k);
    Down(k);

STL助你偷懒

写了那么多废话,然而STL里有一个priority_queue(优先队列)实现了一个大根堆。支持push插入,top取首,pop去首。然而没有Remove这种定点删除的操作。考虑到A*算法用的是小根堆,这其实对A*并没什么卵用。保险起见…我去翻了一下小蓝书…发觉……

STL可以实现小根堆,是我在口胡(口头胡扯)……

技术图片

虽然STL真的只支持大根堆…但是我们可以喂他吃一个魅惑菇啊!!

技术图片

就是说,我们通过重载“<”运算符,让STL认为大就是小,小即是大!你说的黑不是黑~

那,为了防止我们正常使用"<",我们选择用结构体让他重载。

struct rec
    int id;
    double val;
;
bool operator <(const rec &a,const rec &b)
    return a.val>b.val;

题目中的Show Time

啊只要你想到处都能Show,我还有事我先走了(逃)。

 

以上是关于基本数据结构——二叉堆的主要内容,如果未能解决你的问题,请参考以下文章

写给自己看的二叉堆:基本操作

二叉堆而不是二叉搜索树

从零开始认识堆排序

算法与数据结构二叉堆是什么鬼?

数据结构 10 基础数据结构 二叉堆 堆排序算法详解

数据结构 10 基础数据结构 二叉堆 堆排序算法详解