数据结构与算法 Python实现 堆和堆排序

什么是堆
堆是一种完全二叉树

  • 最大堆:对于每个非叶子节点,都比他的两个孩子大,称为最大堆最大堆特性,最大堆里的根节点往往是最大值
  • 最小堆:和最大堆相反,每个非叶子节点,两个孩子都比他大
    堆的表示:用二叉树表示
    堆提供了很有限的几个操作
    1.插入新的值,插入比较麻烦的就是需要维持对的特性,需要sift_up操作
    2.获取并移除根节点的值,每次我们都可以获取最大值和最小值,这个时候需要把底层最右边的节点值替换到root 之后siftdown操作
#实现一个定长的数组arroy
class Array(object):
    #初始化
    def __init__(self,size = 32):
        #
        self._size = size
        #长度为size,value全为None的列表
        self._items = [None] * size

    #通过[]获取value
    def __getitem__(self,index):
        return self.items[index]

    #下标赋值
    def __setitem__(self,index,value):
        self._items[index] = value
    #返回长度
    def __len__(self):
        return self._size
    #清除数组
    def cleor(self,value = None):
        for i in range(len(self.items)):
            self._items[i] = value
    #遍历数组
    def __iter__(self):
        for item in self._items:
            yield item




################################################################
#实现一个堆排序
################################################################

class MaxHeap(object):
    #初始化
    def __init__(self,maxsize = None):
        #定义一个最大长度
        self.maxsize = maxsize
        #定义个数
        self._count = 0
        #新建一个数组
        self._elements = Array(maxsize)
    #长度
    def __len__(self):
        #直接返回元素的个数
        return self._count
    #添加方法
    def add(self,value):
        #首先判断换是否超出了最大长度
        if self.count >= self.maxsize:
            raise Exception('full')
        #把值赋给节点
        self._elements[self._count] = value
        #长度加一
        self._count += 1
        #调用silfup方法
        self.silfup(self._count - 1)
    #判断位置方法
    def _silfup(self, ndx):
        #判断换长度
        if ndx > 0 :
            #计算上一个节点的下标
            parent = ((ndx-1) / 2)
            #判断子节点大于父节点
            if self._elements[ndx] > self._elements[parent]:
                #交换值
                self._elements[ndx],self._elements[parent] = self._elements[parent],self._elements[ndx]
                #递归在进行比较
                self._silfup(parent)

    #删除根节点
    def extract(self):
        #先判断是否还有值
        if self._count <= 0:

            raise Exception('empty')
        #取出根节点
        value = self._elements[0]
        #长度减一
        self._count -= 1
        #把最后一个节点上的值,赋值给根节点
        self._elements[0] = self._elements[self._count]
        #调用_siftdown 函数
        self._siftdown(0)
        #返回根节点的值
        return value

    #通过siftdown的方法满足最大堆的特点
    def _siftdown(self,ndx):
        #计算左孩子的下标
        left = 2 * ndx + 1
        #3计算右孩子的下标
        right = 2 * ndx + 2
        langest = ndx

        #首先左节点下标要小于当前的数组的长度,其次左孩子大于根节点,再其次左孩子大于右孩子
        if (left < self._count and
                self._elements[left] >= self._elements[langest] and
                self._elements[left] >= self._elements[right]):
            #把值左孩子的下标,赋值给langest
            langest = left
        #右孩子下标小于数组的长度,其次右孩子大于左孩子
        elif right < self._count and self._elements[right] >= self._elements[langest]:
            #把右孩子的下标赋给langest
            langest = right
        #当左孩子,或者是右孩子的不等于根下标
        if langest != ndx:
            #根节点和左孩子或者右孩子交换位置
            self._elements[ndx],self._elements[langest] = self._elements[langest],self._elements[ndx]
            #递归调用siftdown方法,,从当前节点开始重新判断
            self._siftdown(langest)

猜你喜欢

转载自blog.csdn.net/weixin_44865158/article/details/100799674