"""
堆是一种完全二叉树,有最大堆和最小堆
完全二叉树:叶子节点从左到右填充
最大堆:孩子的值大于父亲的值,root的值最大
最小堆:父亲的值大于孩子的值,root的值最小
堆的操作:
插入节点
删除节点
对于一个节点n,n的孩子的节点的下标是 n*2+1,n*2+2,其父节点是 int((n-1)/2)
"""
class Array(object):
def __init__(self, size=32):
self.size = size
self.items = [None]*self.size
def __getitem__(self, item):
if item >= self.size and item < 1:
raise Exception('越界')
return self.items[item]
def __setitem__(self, item, value):
if item >= self.size and item < 1:
raise Exception('越界')
self.items[item] = value
def __len__(self):
return self.size
def clear(self, value=None):
for i in range(self.size):
self.items[i] = value
def __iter__(self):
for item in self.items:
yield item
class MaxHeap(object):
def __init__(self, maxsize=32):
self._maxsize = maxsize
self._elements = Array(self._maxsize)
self.count = 0
def __len__(self):
return self.count
def add(self, value):
if self.count >= self._maxsize:
raise Exception('full error')
self._elements[self.count] = value
self.count +=1
self._siftup(self.count-1)
def _siftup(self, index):
"""
递归交换
维持最大堆的特性
"""
if index > 0:
parent = int((index-1)/2)
if self._elements[index] > self._elements[parent]:
self._elements[index], self._elements[parent] = self._elements[parent], self._elements[index]
self._siftup(parent)
def extrack(self):
if self.count <= 0:
raise Exception('expty')
value = self._elements[0]
self.count -= 1
self._elements[0] = self._elements[self.count]
self._siftdown(0)
return value
def _siftdown(self, index):
left = 2*index+1
rigth = 2*index+2
largest = index
if (left < self.count and # 判断是否有左孩子
self._elements[left] >= self._elements[largest] and
self._elements[left] >= self._elements[rigth]): # 左孩子>右孩子
largest = left
if (rigth < self.count and self._elements[rigth] >= self._elements[largest]):
largest = rigth
if largest != index:
self._elements[index], self._elements[largest] = self._elements[largest], self._elements[index]
self._siftdown(largest)
def hahah(self):
for i in self._elements:
print(i)
# def test_maxheap():
# import random
# n = 5
# h = MaxHeap(n)
# for i in range(n):
# h.add(i)
# h.hahah()
# for i in reversed(range(n)):
# assert i == h.extrack()
# assert 0
# 堆实现倒序排序
def heapsort_reverse(array):
length = len(array)
maxhepa = MaxHeap(length)
for i in array:
maxhepa.add(i)
res = []
for i in range(length):
res.append(maxhepa.extrack())
return res
def test_heapsort_reverse():
import random
l = list(range(10))
random.shuffle(l)
assert heapsort_reverse(l) == sorted(l, reverse=True)
assert 0