堆和索引堆的实现(python)
'''
索引堆
'''
''' 实现使用2个辅助数组来做.有点像dat.用哈希表来做修改不行,只是能找到这个索引,而需要change操作
还是需要自己手动写.所以只能用双数组实现. #引入索引堆的核心就是为了改变堆里面任意一个元素的值,然后继续维护这个堆.
''' '''下面手动写堆'''
'''做大根堆然后输出升序排列'''#感觉之前写的都不对,heapify太弱了,不能按方向调整.
#需要修改成带shift up,shift down操作的堆,最终目标实现双辅助数组的最大索引堆
class Maxheap():
def __init__(self,capacity):#capacity是最大容量
self.data=[]*capacity
self.count=
self.capacity=capacity
def size(self):
return self.count
def empty(self):
return self.count== def shiftup(self,count):
while count> and self.data[(count-)//2]<self.data[count]:
self.data[(count-)//2],self.data[count]=self.data[count],self.data[(count-1)//2]
count=(count-)// def shiftdown(self,k):#把堆的k索引的元素进行shiftdown操作,
#每一次这个操作都能把k位置作为head的子树给heapify了.
while *k+<=self.count- :
left=*k+
right=min(*k+,self.count-)
tmpindex=k
if self.data[left]>self.data[k]:
tmpindex=left
if self.data[right]>self.data[tmpindex]:
tmpindex=right
if tmpindex==k:
return
else:
self.data[tmpindex],self.data[k]=self.data[k],self.data[tmpindex]
k=tmpindex def insert(self,item):#建立只需要shift up
self.data[self.count]=item self.shiftup(self.count)#把count位置的元素向上移动维护堆
self.count+= def pop(self):#弹出堆定元素
self.data[],self.data[self.count-]=self.data[self.count-],self.data[]
output=self.data[self.count-]
self.count-=
if self.count>:
self.shiftdown()#把索引为0的进行shiftdown操作
return output
def show_data(self):#因为堆,需要不动态删除,为了速度.所以不要的元素只是把它放到count- 这个
#index后面而已,通过show_data来读取data中有效元素
a=self.data[:self.count]
return a
def heapify(self,list1):#把数组直接建立成一个最大堆
self.data=list1#python的列表动态的,直接赋值即可.不用管capacity
self.capacity=len(list1)
self.count=self.capacity
for i in range((self.capacity-)//2,-1,-1):
self.shiftdown(i)
return self.data
def heapsort(self,list1):#直接pop 就实现了.因为前面都已经写好了
self.heapify(list1)
while self.count>:
self.pop()#弹出一个 return self.data #下面是测试
a=Maxheap() aa=a.heapify([,,,,,,,-])
print(aa) aaa=a.heapsort([,,,,,,,-])
print(aaa)
堆的实现
'''
索引堆 通过liubobo老师的c++算法与数据结构 (慕课网)
结构还是很复杂的,当然比dat和红黑树要简单多了.通过2个辅助数组来实现的
如果看不懂可以参考上面的视频课程的第4章的内容.里面讲解很详细,我只是把c++代码修改
成了python而已.非常强大,比如在图论中经常需要维护一个可以随意修改里面元素的堆结构.
这时候索引堆就非常管用了.最短路径特斯拉算法,liubobo就是这么实现的.
'''
''' 实现使用2个辅助数组来做.有点像dat.用哈希表来做修改不行,只是能找到这个索引,而需要change操作
还是需要自己手动写.所以只能用双数组实现. #引入索引堆的核心就是为了改变堆里面任意一个元素的值,然后继续维护这个堆.
''' '''下面手动写堆'''
'''做大根堆然后输出升序排列'''#感觉之前写的都不对,heapify太弱了,不能按方向调整.
#需要修改成带shift up,shift down操作的堆,最终目标实现双辅助数组的最大索引堆 '''
下面我们把这个堆改成索引堆,叫index_max_heap
初始化时候.把数据这个list给index_max_heap对象里面的data这个属性是隐含的数据
同时索引index数组,是暴露给用户访问的.data[i]=item,index[count+]=i
然后,我们之后的插入操作是插入索引为i,内容为item的元素, 总之:我们用索引i来替换item来进行堆里面的swap操作,然后最后堆里面第一个位置存index[],表示
存的是data[index[]].也就是index[i]表示的是堆里面第i个位置在data数据集里面的下表.(说起来很绕).
堆里面第几个元素就去index[几]里面找钥匙.然后去data[钥匙]里面去提取内容.
'''
class Maxheap():
def __init__(self,capacity):#capacity是最大容量
self.data=[]*capacity #这个默认插入0非常不好,比如我索引只插入了1,'wo' 和 ,'we'
#但是堆里面还是有10个元素.但是你如果不插入元素的画,
#你建立堆时候给的元素少了会发生bug.没法比较进行堆维护.
#所以使用的时候一定要注意,用多少capacity就给多少.
#如果需要占位的时候,空余的占位要自己补上default值.
self.indexes=[-]*capacity #因为索引不可能是负的,所以用-1占位
self.reverse=[-]*capacity #因为索引不可能是负的,所以用-1占位
self.count=
self.capacity=capacity
def size(self):
return self.count
def empty(self):
return self.count== def shiftup(self,count):
while count> and self.data[self.indexes[(count-)//2]]<self.data[self.indexes[count]]: self.indexes[(count-)//2],self.indexes[count]=self.indexes[count],self.indexes[(count-1)//2]#这一步只是交换index提高了交换效率
#下面2行是公里,因为上面变了,所以下面需要跑一下这2行.坐下对应修复
self.reverse[self.indexes[(count-)//2]]=(count-1)//
self.reverse[self.indexes[count]]=count count=(count-)// def shiftdown(self,k):#把堆的k索引的元素进行shiftdown操作,
#每一次这个操作都能把k位置作为head的子树给heapify了.
while *k+<=self.count- :
left=*k+
right=min(*k+,self.count-)
tmpindex=k
if self.data[self.indexes[left]]>self.data[self.indexes[k]]:
tmpindex=left
if self.data[self.indexes[right]]>self.data[self.indexes[tmpindex]]:
tmpindex=right
if tmpindex==k:
return
else:
self.indexes[tmpindex],self.indexes[k]=self.indexes[k],self.indexes[tmpindex]
self.reverse[self.indexes[tmpindex]]=tmpindex
self.reverse[self.indexes[k]]=k
k=tmpindex #插入索引为i的数据是item
def insert(self,i,item):#建立只需要shift up
assert(self.count+<=self.capacity)
assert(i>= and i<self.capacity)
self.data[i]=item
self.indexes[self.count]=i
self.reverse[i]=self.count self.shiftup(self.count)#把count位置的元素向上移动维护堆
self.count+= def pop(self):#弹出堆定元素
assert(self.count>)
self.indexes[],self.indexes[self.count-]=self.indexes[self.count-],self.indexes[]
self.reverse[self.indexes[]]=
self.reverse[self.indexes[self.count-]]=-#pop就不会被访问了所以给- output=self.data[self.indexes[self.count-]]
self.count-=
if self.count>:
self.shiftdown()#把索引为0的进行shiftdown操作
return output def pop_index(self):#弹出堆定元素
assert(self.count>)
self.indexes[],self.indexes[self.count-]=self.indexes[self.count-],self.indexes[]
self.reverse[self.indexes[]]=
self.reverse[self.indexes[self.count-]]=-#pop就不会被访问了所以给-
output=self.indexes[self.count-]
self.count-=
if self.count>:
self.shiftdown()#把索引为0的进行shiftdown操作
return output def show_data(self):#因为堆,需要不动态删除,为了速度.所以不要的元素只是把它放到count- 这个
#index后面而已,通过show_data来读取data中有效元素
#利用index来遍历更准确和不会bug
out=[]
index_now=self.indexes[:self.size()]
for i in index_now:
if i!=-:
out.append(self.data[i])
out return out
def heapify(self,list1):#把数组直接建立成一个最大堆
self.data=list1#python的列表动态的,直接赋值即可.不用管capacity
self.capacity=len(list1)
self.count=self.capacity
for i in range((self.capacity-)//2,-1,-1):
self.shiftdown(i)
return self.data
def heapsort(self,list1):#直接pop 就实现了.因为前面都已经写好了
self.heapify(list1)
while self.count>:
self.pop()#弹出一个 return self.data
def get_item(self,i):
return self.data[i]
def change(self,i,newitem):#需要返回索引i在堆中的第几个坐标上.比如堆中第一个元素是10,那么change()返回0
#这种操作,叫反向查找技术,非常牛逼class,实现不难,思想牛逼.常用.思想很像dat
#先修改data
self.data[i]=newitem
j=self.reverse[i]
self.shiftup(j)
self.shiftdown(j) return self.data[i] #下面是测试
a=Maxheap() a.insert(,'wo')#0是索引,'wo'是value.对value比较大小来建堆,但是堆里面的元素都是index.
a.insert(,'we') a.insert(,'a')
a.change(,'jjk')
print(a.pop_index())
print(a.indexes)#弹出的元素不会彻底删除,而只是把它的索引放到self.size后面了.
print(a.show_data()) #从这里面就看出来之前最大的wo已经被弹出了.
#并且indexMaxheap也已经效果出来了.可以随意修改index为3的元素了,并且
#自动维护这个堆.
索引堆
堆和索引堆的实现(python)的更多相关文章
- 索引堆(Index Heap)
首先我们先来看一个由普通数组构建的普通堆. 然后我们通过前面的方法对它进行堆化(heapify),将其构建为最大堆. 结果是这样的: 对于我们所关心的这个数组而言,数组中的元素位置发生了改变.正是因为 ...
- C++实现索引堆及完整测试代码
首先贴一篇我看的博客,写的很清楚.作者:Emma_U 一些解释 索引堆首先是堆,但比堆肯定是更有用. 用处: 1.加速. 索引堆存储的是索引,并不直接存储值.在堆上浮下沉的元素交换的时候,交换索引可比 ...
- Eclipse MAT:浅堆 vs 保留堆
来自:唐尤华 https://dzone.com/articles/eclipse-mat-shallow-heap-retained-heap 有没有想要搞清楚浅堆(Shallow Heap)和保留 ...
- 十二、jdk工具之jcmd介绍(堆转储、堆分析、获取系统信息、查看堆外内存)
目录 一.jdk工具之jps(JVM Process Status Tools)命令使用 二.jdk命令之javah命令(C Header and Stub File Generator) 三.jdk ...
- CJOJ 2482 【POI2000】促销活动(STL优先队列,大根堆,小根堆)
CJOJ 2482 [POI2000]促销活动(STL优先队列,大根堆,小根堆) Description 促销活动遵守以下规则: 一个消费者 -- 想参加促销活动的消费者,在账单下记下他自己所付的费用 ...
- 结构之美——优先队列基本结构(四)——二叉堆、d堆、左式堆、斜堆
实现优先队列结构主要是通过堆完成,主要有:二叉堆.d堆.左式堆.斜堆.二项堆.斐波那契堆.pairing 堆等. 1. 二叉堆 1.1. 定义 完全二叉树,根最小. 存储时使用层序. 1.2. 操作 ...
- hdu5795 A Simple Nim 求nim求法,打表找sg值规律 给定n堆石子,每堆有若干石子,两个人轮流操作,每次操作可以选择任意一堆取走任意个石子(不可以为空) 或者选择一堆,把它分成三堆,每堆不为空。求先手必胜,还是后手必胜。
/** 题目:A Simple Nim 链接:http://acm.hdu.edu.cn/showproblem.php?pid=5795 题意:给定n堆石子,每堆有若干石子,两个人轮流操作,每次操作 ...
- 《Windows核心编程系列》十四谈谈默认堆和自定义堆
堆 前面我们说过堆非常适合分配大量的小型数据.使用堆可以让程序员专心解决手头的问题,而不必理会分配粒度和页面边界之类的事情.因此堆是管理链表和数的最佳方式.但是堆进行内存分配和释放时的速度比其他方式都 ...
- SQLserver聚集表、堆和索引
SQL Server 表使用下列两种方法之一来组织其分区中的数据页: 聚集表是有聚集索引的表.数据行基于聚集索引键按顺序存储.聚集索引按 B 树索引结构实现,B 树索引结构支持基于聚集索引键值对行进行 ...
随机推荐
- 无线LoRa远传智能水表
无线远传智能水表是一款基于瑞萨芯片的水表,该水表具有电子计数.无线远传功能.欠费关阀等功能,无线水表具有的功能如下:无线通信采用SX1278的LoRa进行点对点通信,SX1278模块在通信中启用CAD ...
- ettercap的使用
ettercap -i eth0 -T -M arp:remote -q /<网关地址>// /<目标地址>// arp:remote ,表示双向 使用图形化界面 etterc ...
- css设计技巧
如果设置了样式发现没有效果,可以把需要调的元素或者父元素等设置一下背景,然后看看哪个父元素或子元素有样式控制,可以清除一下.
- Flask之before_request、after_request
1.@app.before_request在请求(request)|在视图函数 之前做出响应 解决所有问题 from flask import Flask from flask import re ...
- HDU_1024.MaxSumPlusPlus(基础DP + 滚动数组优化讲解)
这道题打破了我常规的做题思路,因为这是我刚开始训练DP,感觉这道题目好晕眼呀,emm其实就是感觉自己是真的菜...... 为什么说打破了我的做题思路呢,因为我平时看题解都是在已经AC或者完全不懂的情况 ...
- POJ-3414.Pots.(BFS + 路径打印)
这道题做了很长时间,一开始上课的时候手写代码,所以想到了很多细节,但是创客手打代码的时候由于疏忽又未将pair赋初值,导致一直输出错误,以后自己写代码可以专心一点,可能会在宿舍图书馆或者Myhome, ...
- Codeforces Beta Round #27 (Codeforces format, Div. 2)
Codeforces Beta Round #27 (Codeforces format, Div. 2) http://codeforces.com/contest/27 A #include< ...
- RocketMQ-quickstart(批量消费)
一.专业术语 Producer 消费生产者,负责产生消息,一般由业务系统负责产生消息 Consumer 消息消费者,负责消费消息,一般是后台系统负责异步消费 Push Consumer Consume ...
- AngularJs中url参数的获取
前言: angular获取通过链接形式访问的页面,要获取url中的参数,就不能通过路由的方式传递获取了,使用原生js或者jquery,又显得比较麻烦,好在angular已经封装了获取url参数的方法, ...
- eclipse启动出现Could not read metadata for ……
Could not read metadata for …… E:\workspace\.metadata\.plugins\org.eclipse.core.resources\.projects\ ...