本篇学习内容为堆的性质、python实现插入与删除操作、堆复杂度表、python内置方法生成堆。

区分堆(heap)与栈(stack):堆与二叉树有关,像一堆金字塔型泥沙;而栈像一个直立垃圾桶,一列下来。

堆(heap)

又被为优先队列(priority queue)。尽管名为优先队列,但堆并不是队列。回忆一下,在队列中,我们可以进行的限定操作是dequeue和enqueue。

dequeue是按照进入队列的先后顺序来取出元素。而在堆中,我们不是按照元素进入队列的先后顺序取出元素的,而是按照元素的优先级取出元素。

性质

堆的实现通过构造二叉堆(binary heap),实为二叉树的一种;由于其应用的普遍性,当不加限定时,均指该数据结构的这种实现。这种数据结构具有以下性质。

  • 任意节点小于(或大于)它的所有后裔,最小元(或最大元)在堆的根上(堆序性)。
  • 堆总是一棵完全树。即除了最底层,其他层的节点都被元素填满,且最底层尽可能地从左到右填入。

实现

  • 堆的主要操作是插入和删除最小元素(元素值本身为优先级键值,小元素享有高优先级)
  • 在插入或者删除操作之后,我们必须保持该实现应有的性质: 1. 完全二叉树 2. 每个节点值都小于或等于它的子节点

上浮(Promotion)

情境: 子节点的键值变为比父节点的键值大;如下面添加字节点

消除这种违反项:

  • 交换子节点的键和父节点的键
  • 重复这个过程直到堆的顺序恢复正常

堆的添加:

def _upheap(self, j):#往上交换
parent = self._parent(j)
if j > 0 and self._data[j] < self._data[parent]:
self._swap(j, parent)
self._upheap(parent)

下沉(Demotion)

情境:父节点的键值变得比子节点(一个或者2个) 的键值还小 ,如下面删除了根节点后拿了个小子节点补充上来的情况

消除这种违反项:

  • 把父节点的键值和比它大的子节点的键值做交换
  • 重复这个操作直到堆的顺序恢复正常

删除最大值

def _downheap(self, j):#往下交换,递归比较三个值
if self._has_left(j):
left = self._left(j)
small_child = left
if self._has_right(j):
right = self._right(j)
if self._data[right] < self._data[left]:
small_child = right
if self._data[small_child] < self._data[j]:
self._swap(j, small_child)
self._downheap(small_child)

复杂度分析

Python构建堆的代码:

#该heap为min_heap,即根节点为最小值
class PriorityQueueBase:
#抽象基类为堆 class Item:
#轻量级组合来存储堆项目
__slots__ = '_key' , '_value' def __init__ (self, k, v):
self._key = k
self._value = v def __lt__ (self, other): #比较大小
return self._key < other._key def is_empty(self):
return len(self) == 0 def __str__(self):
return str(self._key) class HeapPriorityQueue(PriorityQueueBase): def __init__ (self):
self._data = [ ] def __len__ (self):
return len(self._data) def is_empty(self):
return len(self) == 0 def add(self, key, value): #在后面加上然后加上
self._data.append(self.Item(key, value))
self._upheap(len(self._data) - 1) def min(self):
if self.is_empty():
raise ValueError( "Priority queue is empty." )
item = self._data[0]
return (item._key, item._value) def remove_min(self):
if self.is_empty():
raise ValueError( "Priority queue is empty." )
self._swap(0, len(self._data) - 1)
item = self._data.pop( )
self._downheap(0)
return (item._key, item._value) def _parent(self, j):
return (j - 1) // 2 def _left(self, j):
return 2 * j + 1 def _right(self, j):
return 2 * j + 2 def _has_left(self, j):
return self._left(j) < len(self._data) def _has_right(self, j):
return self._right(j) < len(self._data) def _swap(self, i, j):
self._data[i], self._data[j] = self._data[j], self._data[i] def _upheap(self, j):#往上交换
parent = self._parent(j)
if j > 0 and self._data[j] < self._data[parent]:
self._swap(j, parent)
self._upheap(parent) def _downheap(self, j):#往下交换,递归比较三个值
if self._has_left(j):
left = self._left(j)
small_child = left
if self._has_right(j):
right = self._right(j)
if self._data[right] < self._data[left]:
small_child = right
if self._data[small_child] < self._data[j]:
self._swap(j, small_child)
self._downheap(small_child) heap = HeapPriorityQueue()
heap.add(4, "D")
heap.add(3, "C")
heap.add(1, "A")
heap.add(5, "E")
heap.add(2, "B")
heap.add(7, "G")
heap.add(6, "F")
heap.add(26, "Z") for item in heap._data:
print(item) print("min is: ")
print(heap.min())
print() print("remove min: ")
print(heap.remove_min())
print("Now min is: ")
print(heap.min())
print() print("remove min: ")
print(heap.remove_min())
print("Now min is: ")
print(heap.min())
print() heap.add(1, "A")
print("Now min is: ")
print(heap.min())
print() #输出结果
1
2
3
5
4
7
6
26
min is:
(1, 'A') remove min:
(1, 'A')
Now min is:
(2, 'B') remove min:
(2, 'B')
Now min is:
(3, 'C') Now min is:
(1, 'A')

python内置方法创建堆有两种方式,heappush()和heapify()

'''
heaqp模块提供了堆队列算法的实现,也称为优先级队列算法。
要创建堆,请使用初始化为[]的列表,或者可以通过函数heapify()将填充列表转换为堆。
提供以下功能:
heapq.heappush(堆,项目)
将值项推入堆中,保持堆不变。
heapq.heapify(x)
在线性时间内将列表x转换为堆。
heapq.heappop(堆)
弹出并返回堆中的最小项,保持堆不变。如果堆是空的,则引发IndexError。
'''
import heapq #1 heappush生成堆+ heappop把堆从小到大pop出来
heap = []
data = [1,3,5,7,9,2,4,6,8,0]
for i in data:
heapq.heappush(heap,i)
print(heap) lis = []
while heap:
lis.append(heapq.heappop(heap))
print(lis) #2 heapify生成堆+ heappop把堆从小到大pop出来
data2 = [1,5,3,2,9,5]
heapq.heapify(data2)
print(data2) lis2 = []
while data2:
lis2.append(heapq.heappop(data2))
print(lis2) #输出结果
[0, 1, 2, 6, 3, 5, 4, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 5, 9, 5]
[1, 2, 3, 5, 5, 9]

 

python数据结构之堆(heap)的更多相关文章

  1. 算法与数据结构基础 - 堆(Heap)和优先级队列(Priority queue)

    堆基础 堆(Heap)是具有这样性质的数据结构:1/完全二叉树 2/所有节点的值大于等于(或小于等于)子节点的值: 图片来源:这里 堆可以用数组存储,插入.删除会触发节点shift_down.shif ...

  2. 数据结构之堆Heap

    1. 概述 堆(也叫优先队列),是一棵完全二叉树,它的特点是父节点的值大于(小于)两个子节点的值(分别称为大顶堆和小顶堆).它常用于管理算法执行过程中的信息,应用场景包括堆排序,优先队列等. 2. 堆 ...

  3. Python数据结构2-----队列和堆

    一.线性结构:栈.队列.双端队列.列表 二.非线性结构:树.图.堆 [算法中看堆是非线性的,因为其相当于完全二叉树,但堆的存储元素是采用线性的顺序表数组来实现的] 三.队列: 1.队列类型:FIFO. ...

  4. 数据结构 - 堆(Heap)

    数据结构 - 堆(Heap) 1.堆的定义 堆的形式满足完全二叉树的定义: 若 i < ceil(n/2) ,则节点i为分支节点,否则为叶子节点 叶子节点只可能在最大的两层出现,而最大层次上的叶 ...

  5. python数据结构与算法

    最近忙着准备各种笔试的东西,主要看什么数据结构啊,算法啦,balahbalah啊,以前一直就没看过这些,就挑了本简单的<啊哈算法>入门,不过里面的数据结构和算法都是用C语言写的,而自己对p ...

  6. 算法手记 之 数据结构(堆)(POJ 2051)

    一篇读书笔记 书籍简评:<ACM/ICPC 算法训练教程>这本书是余立功主编的,代码来自南京理工大学ACM集训队代码库,所以小编看过之后发现确实很实用,适合集训的时候刷题啊~~,当时是听了 ...

  7. 堆heap和栈Stack(百科)

    堆heap和栈Stack 在计算机领域,堆栈是一个不容忽视的概念,堆栈是两种数据结构.堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除.在单片机应用中,堆栈 ...

  8. iOS中的堆(heap)和栈(stack)的理解

    操作系统iOS 中应用程序使用的计算机内存不是统一分配空间,运行代码使用的空间在三个不同的内存区域,分成三个段:“text segment “,“stack segment ”,“heap segme ...

  9. Python之数据类型-[bisect,heap]

    bisect >>> import bisect >>> >>> b = [ 20, 34, 35, 65, 78 ] >>> ...

随机推荐

  1. 腾讯大数据平台Oceanus: A one-stop platform for real time stream processing powered by Apache Flink

    January 25, 2019Use Cases, Apache Flink The Big Data Team at Tencent     In recent years, the increa ...

  2. Hadoop从入门到精通系列之--0.Hadoop生态体系

    https://blog.csdn.net/Haidaiya/article/details/84568588#%E4%B8%80%20%E5%A4%A7%E6%95%B0%E6%8D%AE%E7%9 ...

  3. (一) Getting Started

    Elasticsearch is a highly scalable open-source full-text search and analytics engine. It allows you ...

  4. 基于SpringBoot搭建应用开发框架(二) —— 登录认证

    零.前言 本文基于<基于SpringBoot搭建应用开发框架(一)——基础架构>,通过该文,熟悉了SpringBoot的用法,完成了应用框架底层的搭建. 在开始本文之前,底层这块已经有了很 ...

  5. echarts中饼图显示百分比

    通过echarts制作饼图,需要通过鼠标移动到对应的扇形才能才看数值和百分比. 解决这个问题参考的是将鼠标移动到扇形上的显示方法:     tooltip : {         trigger: ' ...

  6. 移除Windows图标快捷方式小箭头

    以管理员身份运行cmd,输入 reg delete "HKEY_CLASSES_ROOT\lnkfile" /v IsShortcut /f & taskkill /f / ...

  7. JAVA工程师-蚂蚁金服电话面试

    今天5点半接到一个杭州的电话,是蚂蚁金服打来的,当时心里一阵发慌,由于还在上班,就和面试官约定6点下班之后再来.挂完电话,心里忐忑的不行,感觉自己这也没准备好,那也没准备好.剩下半个小时完全没有心思再 ...

  8. Asp.Net Core SignalR 与微信小程序交互笔记

    什么是Asp.Net Core SignalR Asp.Net Core SignalR 是微软开发的一套基于Asp.Net Core的与Web进行实时交互的类库,它使我们的应用能够实时的把数据推送给 ...

  9. gorose使用示例

    package main import ( "fmt" "github.com/gohouse/gorose" //import Gorose _ " ...

  10. mybatis 使用auto mapping原理实现表间关联

    Auto mapping的示例 数据库中有一个person表,结构如下: mysql> desc person; +-------+-------------+------+-----+---- ...