数据结构——堆的实现以及STL标准库

数据结构——堆的实现以及STL标准库

堆说的清新脱俗一点就是用类似完全二叉树的方式来维护一组数据,增删改查的时间复杂度在O(1)~O(logn)之间,一听就很心动吧:)
堆大致分为两类:大根堆和小根堆,简单来说就是根节点是所有数据中最大/小,并且让小的节点在上方。
给一组数据{7,2,3,1,5,6,9,8,4}
在这里插入图片描述
当然,现在这还只是个二叉树:)
然后介绍几个堆的基本操作
上浮,下沉,插入,弹出。
以下代码以小根堆为例。
1 上浮
从上图可以看出,这组没有被处理的数据中,根节点的元素7不是最小的,并且可以看出,他的左子节点上的元素2更适合在根节点,那么直接交换不就可以了?
可接下来就会发现,元素2的左子节点上的元素1更适合在根节点,这个时候就无法直接与根节点交换,这就需要上浮:
在这里插入图片描述
过程如下:
在这里插入图片描述

void up(int i)
{
    while(i>1)
    {
        if(a[i]<a[i>>1])
            swap(a[i],a[i>>1]);
        i>>=1;
    }
}

2 下沉
在这次上浮之后,我们可以看到虽然元素1到了根节点,但元素7和元素2的位置还有问题,这个时候,让我们换一种方式,用下沉。
在这里插入图片描述
过程如下:
在这里插入图片描述

void down(int i)
{
    while((i<<1)<=len)///len为数组大小
    {
        int next=i<<1;
        if(next<len&&a[next+1]<a[next])
            next++;
        if(a[i]<a[next])
            swap(a[i],a[next]);
        else return ;
    }
}

3 插入
我们前面用的插入是直接插入,所以数据才会杂乱无章,那么我们如何在插入的时候进行维护堆呢?
仔细一想,在插入的时候插到最后一位,在进行上浮!

void push(int x)
{
    a[++len]=x;
    up(len);
}

4 弹出
弹出就是从堆顶去掉,这样不就全乱套了?
仔细一想,先把堆顶和堆尾的元素进行交换,再把堆顶下沉:)

void pop()
{
    swap(a[1],a[len]);
    len--;
    down(1);
}

然后
.
.
.
.
.
.
.
.
.
.
.
.
就是最最最方便的STL啦!
堆的应用在STL中需要用到vector
首先是存入

for(int i=1;i<=n;i++)
    {
        scanf("%d",&x);
        a.push_back(x);
     }

然后要用到#include algorithm

 make_heap(a.begin(),a.end(),cmp);

这一行就是创建一个堆:)
cmp则是根据大小根堆来写,和快排类似,不同的是小根堆的cmp是这么写的

bool cmp(int x,int y)
{
    return x>y;
}

没错,小根堆的中是大于号
之后往堆中插入数据则是和存入类似

a.push_back(x);
push_heap(a.begin(),a.end(),cmp);

推出则是

pop_heap(a.begin(),a.end(),cmp);
    a.pop_back();

本人小白,第一次写博客,也借鉴了一些大牛的博客,侵权则删:)

扫描二维码关注公众号,回复: 3541168 查看本文章

猜你喜欢

转载自blog.csdn.net/qq_42792291/article/details/82971756