数据结构二叉堆

二叉堆

一 二叉堆的性质

 在二叉堆中,二叉堆被分为大根堆和小根堆,大根堆满足手元素最大,小根堆满足首元素最小。在二叉堆中满足一个节点的左右子节点都小于或大于它本身。

二 二叉堆的数组实现方式

1. 储存方式

 我们通常借助数组实现二叉堆的操作,类似于满二叉树,在数组中,第x个元素的左子树在2x个,它的右子树在第 2x-1个。

2. 基础操作的实现

初始化二叉堆
void Init()
{
   for (int i = 1; i < N; i++)
   {
        elem[i] = inf;
   }
}
弹出头部节点

在弹出节点后我们让最后一个节点去到头部的位置,然后从上向下调整我们的关系

// 弹出头部节点后用最后一个节点去代替他,
void pop()
{
    elem[1] = elem[num];
    elem[num--] = inf;
    ModifyFromTop(1);
   // 从头部向下继续调整顺序
}
输入一个节点

输入节点的后我们先让他处在尾部的位置,然后从下向上去调整关系

void push(int x)
{
    elem[++num] = x;
    ModifyFromBottom(num);
}
从头部向下修改二叉堆
void ModifyFromTop(int x)
{
    if(elem[x]==inf) return;
    // 如果修改到了没有值的地方,说明超出范围,直接返回
    int target = (elem[ls(x)]<elem[rs(x)])? ls(x): rs(x);
    // 判断左右边的大小,若该节点小于存储左右子树中的较小数,那么进行交换
    if(elem[x]>elem[target])
    {
        swap(elem[x],elem[target]);
        ModifyFromTop(target);
    }
}
从底部向上修改二叉堆
void ModifyFromBottom(int x)
{
    if(x==1) return;
    if(elem[x] < elem[father(x)])
    {
        swap(elem[x],elem[father(x)]);
        ModifyFromBottom(father(x));
    }
}

三 例题和解法

例题

一道洛谷的模版题
在这里插入图片描述

思路

按照上面给的几种基础操作,并封装到一个结构体中去,得到我们的heap数据结构

解法
#include<stdio.h>
#include <string.h>
#include <iostream>
#define father(x) (x/2)
#define ls(x) (2*x)
#define rs(x) (2*x+1)
#define N 1000020
#define inf 1000000000
using namespace std;
struct heap
{
    int num; // record the number of the elem in the heap
    int elem[N];
    void Init()
    {
        for (int i = 1; i < N; i++)
        {
            elem[i] = inf;
        }
    }
    inline int top()
    {
        return elem[1];
    }
    void ModifyFromBottom(int x)
    {
        if(x==1) return;
        if(elem[x] < elem[father(x)])
        {
            swap(elem[x],elem[father(x)]);
            ModifyFromBottom(father(x));
        }
    }
    void ModifyFromTop(int x)
    {
        if(elem[x]==inf) return;
        int target = (elem[ls(x)]<elem[rs(x)])? ls(x): rs(x);
        if(elem[x]>elem[target])
        {
            swap(elem[x],elem[target]);
            ModifyFromTop(target);
        }
    }
    void push(int x)
    {
        elem[++num] = x;
        ModifyFromBottom(num);
    }
    void pop()
    {
        elem[1] = elem[num];
        elem[num--] = inf;
        ModifyFromTop(1);
    }
}Heap;
inline int read()//快读
{
    int sum=0,w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0' && ch<='9') {sum=sum*10+ch-'0';ch=getchar();}
    return sum*w;
}
int main()
{
    int n = read();
    Heap.Init();
    int op;
    for (int i = 0; i < n; i++)
    {
        op = read();
        if(op==1)
        {
            int x = read();
            Heap.push(x);
        }
        else if (op==2)
        {
            printf("%d\n",Heap.top());
        }
        else
            Heap.pop();
    }
}



希望大家三连关注,谢谢大家

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值