python最小堆_最小堆实现优先队列:Python实现

堆是一种数据结构,因为Heapsort而被提出。除了堆排序,“堆”这种数据结构还可以用于优先队列的实现。

堆首先是一个完全二叉树:它除了最底层之外,树的每一层的都是满的,且最底层中的节点处于左边,相互之间没有“跳变”;其次,堆有次序属性:每个节点中的数据项都大于或者等于其子女的数据项(如果是记录,则这些记录中的某个关键域必须满足这一属性)。 当然,这是指大顶堆,小顶堆则是父节点比子节点都要小。

所谓队列,就是一个FIFO表(first in, first out)。优先队列,就是在队列的基础上,每个元素加一个优先级,last in的元素可能会first out,这就是优先级在起作用。

我想实现这样一个优先队列:

元素为整数

元素值小的优先级反而大

有入队操作,每次进入一个元素

出队操作,也行每次一个元素

那么,我的小根堆Heap应该这样考虑:

每当插入元素时,在原有Heap的最后一个叶子节点后面插入新元素val,并持续比较val和其父节点的值之间是否满足堆的次序属性,直到满足

每当删除元素时,删除的是值最小的元素,也就是根结点root,则将root和最后一个叶子节点lastleaf互换,然后删除交换后的new_lastleaf ,并从new_root开始调整堆,使满足堆的次序属性。

这样一来,代码就不难写出:

#coding:utf8

#author:HaxtraZ

#description:优先队列,用堆实现

#修改自《算法导论》2nd Edition

class ZHeap:

def __init__(self, item=[]):

# 初始化。item为数组

self.items = item

self.heapsize = len(self.items)

def LEFT(self, i):

return 2 * i + 1

def RIGHT(self, i):

return 2 * i + 2

def PARENT(self, i):

return (i - 1) / 2

def MIN_HEAPIFY(self, i):

# 最小堆化:使以i为根的子树成为最小堆

l = self.LEFT(i)

r = self.RIGHT(i)

if l < self.heapsize and self.items[l] < self.items[i]:

smallest = l

else:

smallest = i

if r < self.heapsize and self.items[r] < self.items[smallest]:

smallest = r

if smallest != i:

self.items[i], self.items[smallest] = self.items[smallest], self.items[i]

self.MIN_HEAPIFY(smallest)

def INSERT(self, val):

# 插入一个值val,并且调整使满足堆结构

self.items.append(val)

idx = len(self.items) - 1

parIdx = self.PARENT(idx)

while parIdx >= 0:

if self.items[parIdx] > self.items[idx]:

self.items[parIdx], self.items[idx] = self.items[idx], self.items[parIdx]

idx = parIdx

parIdx = self.PARENT(parIdx)

else:

break

self.heapsize += 1

def DELETE(self):

last = len(self.items) - 1

if last < 0:

# 堆为空

return None

# else:

self.items[0], self.items[last] = self.items[last], self.items[0]

val = self.items.pop()

self.heapsize -= 1

self.MIN_HEAPIFY(0)

return val

def BUILD_MIN_HEAP(self):

# 建立最小堆, O(nlog(n))

i = self.PARENT(len(self.items) - 1)

while i >= 0:

self.MIN_HEAPIFY(i)

i -= 1

def SHOW(self):

print self.items

class ZPriorityQ(ZHeap):

def __init__(self, item=[]):

ZHeap.__init__(self, item)

def enQ(self, val):

ZHeap.INSERT(self, val)

def deQ(self):

val = ZHeap.DELETE(self)

return val

a = [1, 3, 2, 4, 8, 6, 22, 9]

pq = ZPriorityQ()

n = len(a)

for i in range(n):

pq.enQ(a[i])

pq.SHOW()

for i in range(n):

pq.deQ()

pq.SHOW()

其中,ZHeap表示小根堆,ZPriorityQ表示优先队列,deQ表示退队,enQ表示入队。

我们发现以下结论:大根堆用于升序排序,小根堆用于降序排序。

为什么用堆来实现优先队列?原因只有一个:复杂度低。

如果使用列表(存放在list中),插入为O(1),删除为O(n);

如果使用按照优先级排好序的有序列表,插入和线性插入排序一样,O(n),删除则为O(1)

使用堆的时候,无论你删除还是插入,都是O(lg n)时间复杂度,对于插入和删除都比较频繁的操作来讲,这是最好不过的了。

如果认为有不正确的地方欢迎拍砖。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值