1.完全二叉树的一个父节点编号为k,那么他的左二子的编号为2*k+1,右二子节点的编号为2*k+2
2.如果已知儿子(左儿子或者右儿子)的编号为x,那么他的父节点的编号为(x-1)//2(取整除,就是计算机里的/)
3.最小堆是所有的父节点都比他的子节点小,最大堆是所有的父节点都比他的子节点大
4.像这样支持插入元素和寻找元素(最大值和最小值)的数据结构成为优先队列,如果使用普通队列,那么寻找最大元素就需要枚举整个队列,时间复杂度为O(n),时间复杂度比较高,如果是已经排好序的数组,那么插入一个元素需要移动大量的数据,时间复杂度依旧很高,而堆就是一种优先队列的实现,可以很好地解决这两种操作
5.堆经常被用来求一个数列中第K大的数,只需要建立一个大小为K的最小堆,堆顶就是第K大的数(举个例子,假设有事十个数,要求第3大的数,将前三个数建成最小堆,然后从第四个数开始,与堆顶元素比较,如果比堆顶元素大,则舍弃当前堆顶元素,而将这个新数作为堆顶,然后堆顶开始向下调整,如果比堆顶元素小,则不进入堆),同理如果求第K小的数,那么就建一个最大堆,这种方法的时间复杂度为O(NlogK)
6.创建堆的过程是,要么是对一个已经存在的数组进行调整顺序然后,调整成一个合法的heap。要么是往一个heap里面添加元素。
class Heap:
def __init__(self, heap):
self.heap = heap
def shift_down(self, i):
finished = False
i_min = i
child_i = i_min * 2 + 1
length = len(self.heap) - 1
while child_i <= length and not finished:
if self.heap[child_i] < self.heap[i]:
i_min = child_i
child_i += 1
if child_i <= length and self.heap[i_min] > self.heap[child_i]:
i_min = child_i
if i_min != i:
self.heap[i], self.heap[i_min] = self.heap[i_min], self.heap[i]
i = i_min
child_i = i * 2 + 1
else:
finished = True
def shift_up(self, i):
finished = False
f_i = (i - 1) // 2
while f_i >= 0 and not finished:
if self.heap[f_i] > self.heap[i]:
self.heap[i], self.heap[f_i] = self.heap[f_i], self.heap[i]
i = f_i
f_i = (i - 1) // 2
else:
finished = True
def create(self):
i = (len(self.heap) - 2) // 2
while i >= 0:
self.shift_down(i)
i -= 1
def pop(self):
val = self.heap[0]
length = len(self.heap) - 1
self.heap[0], self.heap[length] = self.heap[length], self.heap[0]
self.heap.pop()
self.shift_down(0)
return val
def push(self, val):
self.heap.append(val)
self.shift_up(len(self.heap) - 1)
def print(self):
for val in self.heap:
print(val)