一、二叉堆
二叉堆本质上是一种完全二叉树。
它分为两类:最大堆和最小堆。最大堆的任何一个父节点的值都大于或等于它左右孩子节点的值;最小堆的任何一个父节点的值,都小于或等一它左右孩子节点的值。
二叉堆虽然是一个完全二叉树,但它的存储方式并不是链式存储,而是顺序存储。换句话说,二叉堆的所有节点都存储在数组中。
假设"第一个元素"在数组中的索引为i,则父节点和子节点的位置关系如下:
索引为i的父节点的下标:(i-1)/2
索引为i的左孩子的下标:2*i+1
索引为i的右孩子的下标:2*i+2
二、二叉堆操作
1、添加节点
1、新元素一律先插入到堆的尾部
2、依次向上调整整个堆的结构(一直到根即可)
元素添加到队尾
持续向上移动并交换
如上图所示:
class BinaryHeap:
def __init__(self):
'''初始化数组'''
self.data = [None]
def get_parent_index(self, index):
'''
父节点索引
:param index:
:return:
'''
# 判断数组是否越界
if index == 0 or len(self.data) - 1 < index:
return None
# 返回父节点 等价于 (index -1)>>1
return (index -1) // 2
def insert(self, data):
"""
1. 先把元素放到最后, 然后从后往前依次堆化
2. 大堆顶为例, 如果插入元素比父节点大, 则交换, 直到最后
:param data: 插入元素
:return: 返回数组
"""
self.data.append(data)
index = len(self.data) - 1 # 插入元素的下标
parent = self.get_parent_index(index)
# 判断父节点不为空,且父节点元素<子节点元素,循环
while parent is not None and self.data[parent] < self.data[index]:
# 交换
self.data[parent], self.data[index] = self.data[index], self.data[parent]
#元素下标为之前父节点,继续初始化值
index = parent
parent = self.get_parent_index(parent)
return self.data
# 使用示例
if __name__ == '__main__':
#二叉堆对象
heap = BinaryHeap()
ll=[100,90,80,70,60,20,33,15,50]
print(ll)
#数组
heap.data=ll
#添加数据
print(heap.insert(95))
2、删除节点
1、将堆尾元素替换到顶部(即对顶被替代删除掉)
2、依次从根部向下调整整个堆的结构(一直到堆尾即可)
删除元素100
如上图所示:
class BinaryHeap:
def __init__(self):
'''初始化数组'''
self.data = [None]
def removeMax(self):
# 保存删除的元素
remove_data = self.data[0]
# 首尾互换参数
self.data[0] = self.data[-1]
#删除最后一个
del self.data[-1]
# 堆化
self.heapify(0)
return self.data
def heapify(self, index):
# 从上往下堆化,从index 开始堆化操作 (大顶堆)
total_index = len(self.data) - 1
while True:
maxvalue_index = index
# 左右子节点索引
left = 2 * index + 1
right = 2 * index + 2
#查找根,左,右中最大值
if left <= total_index and self.data[left] > self.data[maxvalue_index]:
maxvalue_index = left
if right <= total_index and self.data[right] > self.data[maxvalue_index]:
maxvalue_index = right
if maxvalue_index == index:
break
self.data[index], self.data[maxvalue_index] = self.data[maxvalue_index], self.data[index]
index = maxvalue_index
if __name__ == '__main__':
#二叉堆对象
heap = BinaryHeap()
ll=[100,90,80,70,60,20,33,15,50,40]
print(ll)
#数组
heap.data=ll
#删除最大元素
print(heap.removeMax())
由此得出:Binaey Heap 的 find Min/Max 的时间复杂度为 o(1),其余时间复杂度为 o(logn)。