class IndexMinHeap(object):
"""
最小反向索引堆,出堆不删除data,只删除indexs
"""
def __init__(self, n):
self.capacity = n # 堆的最大容量
self.data = [-1 for _ in range(n)] # 创建堆
self.indexs = [] # 创建索引堆
self.reverse = [-1 for _ in range(n)] # 创建反向索引
self.count = 0 # 元素数量
def size(self):
return self.count
def isEmpty(self):
return self.count == 0
def contain(self, i):
# 最小堆中是否包含i索引的元素
return self.reverse[i] != -1
def insert(self, i, item):
# 插入元素入堆
self.data[i] = item
self.indexs.append(i)
self.reverse[i] = self.count
self.count += 1
self.shiftup(self.count)
def shiftup(self, count):
# 将插入的元素放到合适位置,保持最小堆
while count > 1 and self.data[self.indexs[(count/2)-1]] > self.data[self.indexs[count-1]]:
self.indexs[(count/2)-1], self.indexs[count-1] = self.indexs[count-1], self.indexs[(count/2)-1]
self.reverse[self.indexs[(count/2)-1]] = (count/2)-1
self.reverse[self.indexs[count-1]] = count-1
count /= 2
def extractMin(self):
# 出堆
if self.count > 0:
ret = self.data[self.indexs[0]]
self.indexs[0], self.indexs[self.count-1] = self.indexs[self.count-1], self.indexs[0]
self.reverse[self.indexs[0]] = 0
self.reverse[self.indexs[self.count-1]] = self.count-1
# for i in range(self.indexs[self.count-1]+1, self.count):
# self.indexs[self.reverse[i]] -= 1
self.reverse[self.indexs[self.count-1]] = -1
# self.data[self.indexs[self.count-1]] = -1
self.indexs.pop(self.count-1)
self.count -= 1
self.shiftDown(1)
return ret
def extractMinIndex(self):
# 出堆返回索引
if self.count > 0:
ret = self.indexs[0]
self.indexs[0], self.indexs[self.count-1] = self.indexs[self.count-1], self.indexs[0]
self.reverse[self.indexs[0]] = 0
self.reverse[self.indexs[self.count-1]] = self.count-1
# for i in range(self.indexs[self.count-1]+1, self.count):
# self.indexs[self.reverse[i]] -= 1
self.reverse[self.indexs[self.count-1]] = -1
# self.data[self.indexs[self.count-1]] = -1
self.indexs.pop(self.count-1)
self.count -= 1
self.shiftDown(1)
return ret
def shiftDown(self, count):
# 将堆的索引位置元素向下移动到合适位置,保持最小堆
while 2 * count <= self.count :
# 证明有孩子
j = 2 * count
if j + 1 <= self.count:
# 证明有右孩子
if self.data[self.indexs[j]] < self.data[self.indexs[j-1]]:
# 右孩子数值比左孩子数值小
j += 1
if self.data[self.indexs[count-1]] <= self.data[self.indexs[j-1]]:
# 堆的索引位置已经小于两个孩子节点,不需要交换了
break
self.indexs[count-1], self.indexs[j-1] = self.indexs[j-1], self.indexs[count-1]
self.reverse[self.indexs[count-1]] = count-1
self.reverse[self.indexs[j-1]] =j-1
count = j
def getItem(self, i):
# 根据索引获取数值
if i >=0 and i <= self.count-1:
return self.data[i]
else:
return None
def change(self, i, newItem):
# 改变i索引位置的数值
if i >=0:
self.data[i] = newItem
j = self.reverse[i]
self.shiftup(j+1)
self.shiftDown(j+1)
【算法——Python实现】最小索引堆,最小堆的优化
最新推荐文章于 2023-12-17 00:16:54 发布