第一次接触堆,是在学习堆排序的时候,整个人都是糊糊的,搞不清楚那些操作到底在做什么。其实,堆本质上就是一颗特殊的完全二叉树。既然是一颗完全二叉树,就可以用数组来存储。它的特殊之处在于:根节点都不小(或者大)于子节点。对于堆的操作,如果违反了这个性质,那么就需要对堆进行调整。而调整堆无外乎两种方法:向上调整siftUp或者向下调整siftDown。下面先来看几个堆的性质:

已知一个内节点(非根节点)的下标是i,那么其父节点是i/2,其左孩子和右孩子分别是2*i2*i+1

 

下面的所有操作都是针对大顶堆而言的。

siftUp:

pre:H[1…,i-1]构成了一个堆,除了最后一个元素H[i]之外,其余元素构成了一个大顶堆

postH[1,…,i]构成一个堆

siftUp(H,i)

         j=i/2

         while j>0

                   if(H[j] < H[i])

                            交换H[i]H[j]

                   I=j

 

siftDown

pre:H[i+1,…,n]构成了一个堆,H[i,…,n]除了第一个元素H[i]之外,其余元素构成了一个大顶堆

postH[i,…,n]构成一个堆

siftDown(H, i)

j=2*i

while j<length[H]

                   if(j < length[H]-1 && H[j]<H[j+1])

                            j++

                   if(H[i] < H[j])

                            交换H[i]H[j]

                   I=j

                   J=2*i

 

时间复杂度分析:

求父节点:O(1)

求子节点:O(1)

调整堆(siftUp或者siftDown):O(nlgn)

 

应用:

堆主要有两个应用:一个是在堆排序中,另一个是构造优先级队列。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值