Python 堆的实现
Python 堆的实现
- Python 堆的实现
- python实现
- 测试
1.是一个有序数据类型,分为大根堆与小根堆
2.抽象数据类型:总是一颗完全二叉树,父子节点有序。需要实现的基本功能:获取最大/最小元素;插入节点
3. 具体存储结构:一般使用顺序存储结构/数组
4. python实现:set类型:从0创建堆;插入节点;删除根节点;从现有数据直接创建堆。get类型:获取最大/最小元素
5. 根堆插入节点:自下而上,percup()辅助函数。
6. 删除根节点:将最后一个叶子节点替换根节点,然后自上而下,percdown()辅助函数。
7. 以上两种自上而下 or 自下而上 的操作,本质上是为了不在插入或删除元素的时候,移动数组元素(只做了交换操作) and 破环有序结构。
8. 如果先查找应该插入的元素的位置,再插入–>查找的时间、插入移动元素的时间。后者就已经O(n)了
注意点:
使用现有数组直接构建堆,是借助percdown() 或者 percup()辅助函数实现的。
- 从最后一个叶子节点的父节点开始遍历【索引是((heap list 的长度-1)-1)// 2,记得使用整除】,直至根节点,对每一个节点percdown()。
- 从第二层第一个节点开始遍历,直至最后一个叶子节点,对每一个节点percup()。
python实现
class Heap:
def __init__(self):
"""书上将0位置赋值0,只是为了做整数除法,这里不用这种处理"""
self.heap_list = []
self.size = 0
def insert(self, new_node):
self.heap_list.append(new_node)
new_index = self.size
self.percup(new_index)
self.size += 1
def percup(self, i):
"""
辅助函数,将节点上浮至堆中合适位置
i: 需要上浮的元素在数组中的索引
return: None
"""
# 循环直到达到根节点 or 达到合适位置
swap_flag = True
while i > 0 and swap_flag:
swap_flag = False
father_index = int((i - 1) / 2)
if self.heap_list[i] > self.heap_list[father_index]:
self.heap_list[i], self.heap_list[father_index] = self.heap_list[father_index], self.heap_list[i] # 交换
i = father_index
swap_flag = True
# 如果swap_flag是False,就说明达到合适位置。
def remove(self):
"""
删除根节点,借助辅助函数percdown
:return: None
"""
root = self.heap_list[0]
self.heap_list[0] = self.heap_list[-1] # 将根节点替换成叶子节点
self.heap_list.pop()
self.size -= 1
self.percdown(0)
return root
def percdown(self, i):
"""辅助函数:如果比两个叶子节点都小,就下沉; 直到没有叶子节点 or 合适位置"""
current = i
child_index = self.maxChild(current)
swap_flag = True
while child_index is not None and swap_flag:
swap_flag = False
if self.heap_list[current] < self.heap_list[child_index]:
self.heap_list[current], self.heap_list[child_index] = self.heap_list[
child_index], self.heap_list[current] # 交换
current = child_index
child_index = self.maxChild(current)
swap_flag = True
def maxChild(self, i):
"""
辅助函数,返回最小孩子的index,如果没有孩子,就返回None
"""
if 2 * i + 1 > self.size - 1: # 没有子节点
return None
else:
if 2 * i + 2 > self.size - 1: # 没有右子节点
return 2 * i + 1
else:
if self.heap_list[2 * i + 1] >= self.heap_list[2 * i + 2]:
return 2 * i + 1
else:
return 2 * i + 2
def getRoot(self):
return self.heap_list[0]
def isEmpty(self):
"""判断是否为空"""
return self.size == 0
def createheap(self, data):
"""将现有数据直接转换成堆
自上而下percup
这种需要从第二层遍历到底部"""
self.heap_list = data
self.size = len(data)
for i in range(self.size):
self.percup(i)
def createHeap(self, data):
"""将现有数据直接转换成堆
自下而上percdown
这种需要从导数第二层遍历到顶部
从最后一个节点的父开始"""
self.heap_list = data
self.size = len(data)
for i in range((self.size-2) // 2 , -1, -1):
self.percdown(i)
测试
rand_list = [random.randrange(200) for i in range(200)]
rand_list_copy = rand_list[:]
print("初始数组:")
print(rand_list)
my_heap = Heap()
my_heap.createheap(rand_list)
print("初始heap:")
print(my_heap.heap_list)
my_heap_oderlist = []
while not my_heap.isEmpty():
my_heap_oderlist.append(my_heap.remove())
print(my_heap_oderlist)
print()
print('----------------------------------------------------')
heap_2 = Heap()
heap_2.createHeap(rand_list_copy)
print(heap_2.heap_list)
heap_2_orderlist = []
while not heap_2.isEmpty():
heap_2_orderlist.append(heap_2.remove())
print(heap_2_orderlist)
print(heap_2_orderlist == my_heap_oderlist)