python堆模块_python内置堆模块

heapq

python内置heapq模块,通过import heapq导入。

heapq模块是用于堆实现优先队列。我们知道队列是先进先出(FIFO),

heapq中的优先队列指的是不论谁先进,最小的先出或者最大的先出。

# 需要注意的是heapq的堆是小根堆。

0

1 2

3 4 5 6

7 8 9 10 11 12 13 14

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

# 堆顶位置的元素最小,heapq和python一致,下标索引从0开始。

# heapq提供的主要API, Usage:

heap = [] # creates an empty heap

heappush(heap, item) # pushes a new item on the heap

item = heappop(heap) # pops the smallest item from the heap

item = heap[0] # smallest item on the heap without popping it

heapify(x) # transforms list into a heap, in-place, in linear time

item = heapreplace(heap, item) # pops and returns smallest item, and adds

# new item; the heap size is unchanged

heapq实现列表排序

基本排序流程

# -*- coding: utf-8 -*-

# created by X. Liu on 2020/3/14

import heapq

import random

li = [i for i in range(10)]

random.shuffle(li)

print('排序前', li)

# step1: 建堆(小根堆)

heapq.heapify(li)

print('小根堆', li)

# step2: 排序

# heapq.heappop()方法弹出堆顶元素,即最小的元素

new_li = []

for i in range(10):

new_li.append(heapq.heappop(li))

print('排序后', new_li)

# output:

排序前 [3, 4, 9, 0, 5, 1, 6, 2, 8, 7]

小根堆 [0, 2, 1, 3, 5, 9, 6, 4, 8, 7]

排序后 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

堆排序实现版本2 (不考虑时间复杂度)

# 借助 heapq.heappush() & heapq.heappop()

# heappush(h, item) # Push the value item onto the heap, maintaining the heap invariant.

import heapq

def heap_sort(li):

h = []

# 建小根堆

for i in li:

heapq.heappush(h, i)

# 依次弹出最小元素构成有序列表,切片回li

li[:] = [heapq.heappop() for i in range(len(li))]

对比分析

heapq的heapify建堆函数和我们自己实现的建堆函数大同小异。我们自己的sift函数一步到位(实现堆顶元素选位的过程);heapify中使用两步判断比较,其实不如我们自己写的sift好。

heappop函数实现每次弹出堆顶元素,弹出后再将整个堆调整为一个新的小根堆。它的目的是为了实现优先队列,所以才会这样设计。我们如果希望借助它实现列表排序,只能手动排序。

补充

heap的值可以是元组

>>> h = []

>>> heappush(h, (5, 'write code'))

>>> heappush(h, (7, 'release product'))

>>> heappush(h, (1, 'write spec'))

>>> heappush(h, (3, 'create tests'))

>>> heappop(h)

(1, 'write spec')

heapq.heapify(x)底层代码实现

def heapify(x):

n = len(x)

for i in reversed(range(n//2)):

_siftup(x, i)

def _siftup(heap, pos):

endpos = len(heap)

startpos = pos

newitem = heap[pos]

# Bubble up the smaller child until hitting a leaf.

childpos = 2*pos + 1 # leftmost child position

while childpos < endpos:

# Set childpos to index of smaller child.

rightpos = childpos + 1

if rightpos < endpos and not heap[childpos] < heap[rightpos]:

childpos = rightpos

# Move the smaller child up.

heap[pos] = heap[childpos]

pos = childpos

childpos = 2*pos + 1

# The leaf at pos is empty now. Put newitem there, and bubble it up

# to its final resting place (by sifting its parents down).

heap[pos] = newitem

_siftdown(heap, startpos, pos)

def _siftdown(heap, startpos, pos):

newitem = heap[pos]

# Follow the path to the root, moving parents down until finding a place

# newitem fits.

while pos > startpos:

parentpos = (pos - 1) >> 1

parent = heap[parentpos]

if newitem < parent:

heap[pos] = parent

pos = parentpos

continue

break

heap[pos] = newitem

heapq.heappop底层代码实现

def heappop(heap):

"""Pop the smallest item off the heap, maintaining the heap invariant."""

lastelt = heap.pop() # raises appropriate IndexError if heap is empty

if heap:

returnitem = heap[0]

heap[0] = lastelt

_siftup(heap, 0)

return returnitem

return lastelt

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值