二叉堆

杀马特。学长 韩版系。学妹 提交于 2020-02-08 04:21:35

存储方式

二叉堆用数组存储,从下标1开始,并且因为二叉堆为完全二叉树,所以除根节点外的任意节点 i 的父节点为 i / 2,除终端节点外任意节点 i 的 左孩子为 i * 2,右孩子为 i * 2 + 1(存在右孩子时)

性质

1 是一种特殊的完全二叉树。
2 根节点为优先度最大的数据,根节点的子节点优先度稍微低于根节点,以此类推,越往下优先度越低。优先度不一定为数学意义上的大小,根据实际情况选择。
3 基础的有两种堆,/根节点值最大的堆称为大根堆,反过来,根节点最小的称为小根堆。

插入

void charu(int x)
{
    int f;
    if(x<=1)
        return;
    while(x>1)
    {
        f=x/2;
        if(s[x]<s[f])
            swap(s[x],s[f]);
        else
            break;
        x=f;
    }
    return;
}

删除

删除方式为直接将该结点后面所有结点的前移将其覆盖

int shanchu(int adress, int end) 
{
    int i;
    for(i = adress; i <= end - 1; i++)
        s[i] = s[i + 1];
    end--;
    return s[adress];
} 

例题

以上两个为二叉堆的基本操作做,现在让我们来康康小初的例题吧
小初直通车

代码

这是小初晦涩的c++代码

#include <iostream>
#include <cstdio>
using namespace std;
int s[10010],n;
void xiaqu(int i)
{
    int t,r,z;
    while(i*2<n)
    {
        r=i*2;
        z=i*2+1;
        if(s[i]<s[r])
            t=i;
        else
            t=r;
        if(z<n&&s[t]>s[z])
            t=z;
        if(i!=t)
        {
            swap(s[i],s[t]);
            i=t;
        }
        else
            break;
    }
    return;
}
int quchu(void)//取出最小的数,即根结点,再将最后一个根节点并如第一个取整
{
    int a;
    a=s[1];
    s[1]=s[n];
    xiaqu(1);
    n--;
    return a;
}
void charu(int x)
{
    int f;
    if(x<=1)
        return;
    while(x>1)
    {
        f=x/2;
        if(s[x]<s[f])
            swap(s[x],s[f]);
        else
            break;
        x=f;
    }
    return;
}
int main(void)
{
    int i,j,he,a,b;
    while(scanf("%d",&n)!=EOF)
    {
        he=0;
        for(i=1; i<=n; i++)
            scanf("%d",&s[i]);
        for(i=n/2; i>0; i--)
            xiaqu(i);
        while(n>1)
        {
            a=quchu();
            b=quchu();
            he+=a+b;
            n++;
            s[n]=a+b;
            charu(n);
        }
        printf("%d\n",he);
    }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!