啥是堆?
堆分为小堆和大堆
小堆就是父节点都小于孩纸节点
大堆相反
每次从堆顶去得的元素都是最小值,但是每次插入元素和取出元素都要进行平衡堆,时间主要消耗在平衡上
Python内置堆函数
注意是原地修改数组的
heap=[1,4,89,3,2,6]
heapq.heapify(heap) #将数组转化成堆
print(heap)
# heapq.heappush(heap,99)
# print(heapq.heappop(heap))
# print(heapq.heappop(heap))
# print(heapq.heappop(heap))
# print(heapq.heappop(heap))
#print(heapq.heappop(heap))
print(heapq.heappushpop(heap,0)) #放入一个元素push -->pop 并且出一个元素 long-n
print(heap)
print(heapq.heapreplace(heap,-1)) #pop-->push
print(heap)
自己实现一个!
这里用数组实现堆结构
1、初始化工作【内置操作函数】
为上浮和下沉提供方便的函数
def __init__(self):
self.data = []
def __len__(self):
return len(self.data)
def __str__(self):
return str(self.data)
def _parent(self,j): #返回父亲节点位置
return (j-1)//2
def _left(self,j):
return j*2+1
def _right(self,j):
return j*2+2
def _hasLeft(self,j): 如果计算出来的孩纸节点长度超过数组长度,就判断没有孩纸
return self._left(j)<len(self)
def _hasRight(self,j):
return self._right(j)<len(self)
def _swap(self,i,j): 交换元素 主要用于删除操作
self.data[i],self.data[j] = self.data[j],self.data[i]
2、平衡堆
上浮
def _upheap(self,j):
parent = self._parent(j) #找到j的父亲节点
if j>0 and self.data[j]<self.data[parent]: 如果j小于父亲,则和父亲换
self._swap(j,parent)
self._upheap(parent) #继续平衡堆
下沉
def _downheap(self,j):
if self._hasLeft(j):
left = self._left(j)
small = left
if self._hasRight(j):
right = self._right(j)
small = min(left,right)
if self.data[small] < self.data[j]:
self._swap(small,j)
self._downheap(small)
3、插入操作
插入元素先插入在堆的最后,然后进行上浮冒泡操作来平衡堆
def add(self,value):
self.data.append(value)
self._upheap(len(self)-1)
4、取堆顶操作
先将堆顶元素和最后一个元素换,如何删除最后一个元素【也就是堆顶元素】
如何将堆顶元素【也就是原来的最后一个元素】下沉
def remove(self):
if not self.data:
raise Exception("error---->empty")
self._swap(0,len(self)-1) #和最后一个换
item = self.data.pop()
self._downheap(0)
return item
5、查找最小元素
def min(self):
if not self.data:
raise Exception("error---->empty")
return self.data[0]
6、完整代码
class MyHeap():
def __init__(self):
self.data = []
def __len__(self):
return len(self.data)
def __str__(self):
return str(self.data)
def _parent(self,j): #返回父亲节点位置
return (j-1)//2
def _left(self,j):
return j*2+1
def _right(self,j):
return j*2+2
def _hasLeft(self,j):
return self._left(j)<len(self)
def _hasRight(self,j):
return self._right(j)<len(self)
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._hasLeft(j):
left = self._left(j)
small = left
if self._hasRight(j):
right = self._right(j)
small = min(left,right)
if self.data[small] < self.data[j]:
self._swap(small,j)
self._downheap(small)
def add(self,value):
self.data.append(value)
self._upheap(len(self)-1)
def min(self):
if not self.data:
raise Exception("error---->empty")
return self.data[0]
def remove(self):
if not self.data:
raise Exception("error---->empty")
self._swap(0,len(self)-1) #和最后一个换
item = self.data.pop()
self._downheap(0)
return item