堆和堆排序

"""
堆是一种完全二叉树,有最大堆和最小堆
完全二叉树:叶子节点从左到右填充

最大堆:孩子的值大于父亲的值,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

 

posted @ 2020-05-05 02:48  SBJBA  阅读(102)  评论(0)    收藏  举报