数据结构——堆

(第一次写博客,如有错误请谅解)

因为是第一次,所以我们聊聊一些轻松愉快的数据结构——堆(可能会讲错QAQ)

堆是什么呢?堆通常可以看成是一棵完全二叉树

那什么是完全二叉树呢?

若设二叉树的深度为h

除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数

第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。

我们知道二叉树可以用数组模拟,堆自然也可以。现在让我们来画一棵完全二叉树:

我们很容易就可以看出一个结点的father的下标是当前结点u的下标 div 2

那么这样的一个东西有什么用呢?

我们需要让它维护一些信息,就像BST(二叉搜索树)一样{这个我们以后再讲}

现在给出堆得一些性质

  • 堆中某个节点的值总是不大于或不小于其父节点的值;(1)

  • 堆总是一棵完全二叉树。(2)

我们就很容易发现它的时间复杂度一般跟这堆的层数有关

又因为完全二叉树这个强力的形态支撑,会发现它的时间复杂度是O(logn)

堆还分为两种类型:大根堆和小根堆

顾名思义,就是保证是所结点的father的值比自己大/小(其实就是性质(1))

那么在堆的顶端就是我们整个堆中的最值了

对于这种数据结构我们又如何去维护呢?

下面给出几种操作

1.上浮

2.下降

3.插入

我们以大根堆为例,

首先我们要插入元素k的初始位置,然后再将它在这个堆中上浮同时维护堆的完全二叉树性质

下面是寻找初始位置的一段代码

procedure find(k:longint);

begin

 inc(weight);//weight表示堆的大小

 a[weight]:=k;

 up(weight);//使新插入的元素k上升到它自己合适的位置

end;

接下来是上浮操作

procedure up(id:longint);

var t:longint;

begin

 if id =1 then exit;//如果现在来到了堆顶,那么直接退出

 if a[id]>a[id div 2] then //判断当前节点是否满足堆的性质

 begin

  t:=a[id]; a[id]:=a[id div 2]; a[id div 2]:=t;

 end;

up(id div 2);//递归定义

end;

在维护了堆以后,我们要进行堆顶元素的弹出

function push:longint;

begin

 push:=a[1];//取堆顶

 a[1]:=a[weight];//将最后一个元素提到堆顶(这里维护了堆的完全二叉树性质)

 a[weight]:=0;

 dec(weight);

 down(1);//维护最上方的元素将其下放

end;

接下来是下放操作

procedure down(id:longint);

begin

 k:=max(a[id*2],a[id*2+1]);//取两者中的最大值

 if a[id]>=k then exit;//此时满足堆的性质

if k=a[id*2] then 

begin

 t:=a[id]; a[id]:=a[id*2]; a[id*2]:=t;

down(id*2);

end

else begin t:=a[id]; a[id]:=a[id*2+1]; a[id*2+1]:=a[id]; down(id*2+1); end;

end;

最基础的堆本人就讲到这里了,还有很多数据结构等待大家学习。

(代码是手写的,如果有错误请见谅)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值