美文网首页
使用python实现一个大顶堆

使用python实现一个大顶堆

作者: 热血大桃子 | 来源:发表于2020-04-10 15:48 被阅读0次

堆定义

  • 堆是一个树形结构,其底层实现是一棵完全二叉树。而完全二叉树是一层一层按照进入的顺序排成的。按照这个特性,我们可以用数组来按照完全二叉树实现堆;

堆的一些性质

一个大顶堆示例

上面的示例就是一个完全二叉树,也是一个大顶堆。而大顶堆有一个性质:每一个节点的值都小于它父节点的值。(特别注意,每一个节点的值的大小与它所处的深度没有必然的联系。)

我们可以很容易的根据任意一个节点的索引(除去根节点)找到它的父节点的索引以及其左右子节点的索引,如果当前节点的索引为index,那么:

  • 当前节点的父节点 = (index-1) / 2 (这里我们将结果取整);
  • 当前节点的左子节点 = index * 2 + 1;
  • 当前节点的右子节点 = index * 2 + 2。

代码实现一个堆

根据上述的堆的一些性质,我们可以自己实现一个堆。

# 实现一个最大堆
class MaxHeap(object):
    """
    实现一个大顶堆
    """

    def __init__(self):
        self.array = [] # 用一个数组存放堆中元素

    def heapify(self, array):
        """
        对传入的数组进行堆化
        """
        for a in array:
            self.push(a)
        return self.array

    def get_size(self):
        """
        返回堆的大小
        """
        return len(self.array)

    def _parent(self, index):
        """
        返回某个节点的父节点
        """
        if index == 0:
            raise Exception('Index 0 has no parent')
        return int((index - 1) / 2)

    def _left_child(self, index):
        """
        返回左孩子节点的索引
        """
        return index * 2 + 1

    def _right_child(self, index):
        """
        返回右边孩子节点的索引
        """
        return index * 2 + 2

    def _shift_up(self, k):
        """
        节点上移动,将当前节点与其父亲节点比较大小,如果比父亲节点大,
        则交换其位置,重复只执行上述过程,直到当前节点比父亲节点小。
        """
        while k > 0 and self.array[self._parent(k)] < self.array[k]:
            # 交换节点与父节点的值
            self.array[self._parent(k)], self.array[k] = self.array[k], self.array[self._parent(k)]
            k = self._parent(k)

    def _shift_down(self, k):
        """
        节点下移动, 当前节点与它左右孩子中最大的节点交换位置
        """
        while self._left_child(k) < self.get_size():
            choose_index = self._left_child(k)  # 左孩子的索引
            # 先比较左右孩子的大小,选择较大的那个孩子再与父亲节点进行比较
            if choose_index + 1 < self.get_size() and self.array[choose_index + 1] > self.array[choose_index]:
                choose_index = self._right_child(k)
            if self.array[choose_index] <= self.array[k]:  # 如果最大的孩子比父亲节点小,退出循环
                break
            # 否则父亲节点和最大的子节点交换位置
            self.array[choose_index], self.array[k] = self.array[k], self.array[choose_index]
            k = choose_index  # 进行下次循环

    def push(self, value):
        """
        添加一个元素后,需要对堆重新进行堆化,具体过程就是对堆尾元素执行上移操作;
        """
        self.array.append(value)
        self._shift_up(self.get_size() - 1)  # 相当于对堆进行重新堆化

    def pop(self):
        """
        返回堆顶元素,将堆顶元素和堆最后一个元素交换,
        然后返回最后一个元素,最后对堆顶元素进行下沉操作(重新堆化)
        """
        ret = self.find_max()
        self.array[0], self.array[self.get_size() - 1] = self.array[self.get_size() - 1], self.array[0]
        self.array.pop(-1)  # 删除最后一个元素
        self._shift_down(0)
        return ret

    def find_max(self):
        """
        查看堆中的最大值
        """
        if self.array:
            return self.array[0]
        else:
            raise Exception('Empty heap has no value')

# 测试我们实现的大顶堆
test = [12, 11, 10, 9, 6, 7, 8, 13]
max_heap = MaxHeap()
print(max_heap.heapify(test)) # 对一个数组执行堆化
print(max_heap.pop()) # 弹出堆顶元素
print(max_heap.array) 
max_heap.push(14) # 推入一个元素
print(max_heap.array)

相关文章

  • 大顶堆生成、新增、删除、排序javascript实现

    大顶堆小顶堆的概念和使用本文不赘述,使用js实现一个大顶堆的创建,新增,删除以及利用大顶堆排序

  • 使用python实现一个大顶堆

    堆定义 堆是一个树形结构,其底层实现是一棵完全二叉树。而完全二叉树是一层一层按照进入的顺序排成的。按照这个特性,我...

  • 堆排序的实现

    使用大顶锥实现升序排序,二叉堆的详细操作见以前的文章 步骤如下: 先构建大顶堆 然后循环删除堆顶元素(交互首尾元素...

  • 堆排序的实现

    用大顶堆实现堆排序

  • PriorityQueue 使用方法

    求最大k个元素的问题:使用小顶堆 求最小k个元素的问题:使用大顶堆 参考:1 采用PriorityQueue实现大...

  • 堆的创建、删除、插入以及堆排序

    简介 堆在生产中有着广泛的使用,在求top K、堆排序方面都有使用,使用数组即可实现大顶堆或者小顶堆,下标为i的元...

  • 数据流的中位数

    使用双pq,一个大顶堆装小于middle的数,一个小顶堆装大于middle的数。大顶堆与小顶堆之间元素个数差不能大...

  • 大顶堆的实现.md

    大顶堆的实现.md 大顶堆介绍   大顶堆的基础结构就是完全二叉树, 是一种基础的数据结构, 其特点是根节点是最大...

  • 手把手教你写个大顶堆

    今天我们来实现一个大顶堆,所谓大顶堆,即根节点的值大于等于其孩子节点的值。废话少絮,直接开始。 堆是一个完全二叉树...

  • 堆在java中的应用--PriorityQueue

    堆的特点 堆是一种完全二叉树的模拟,堆一般是基于数组的实现,堆分大顶堆和小顶堆,大顶堆就是堆顶是最大的数据,然后子...

网友评论

      本文标题:使用python实现一个大顶堆

      本文链接:https://www.haomeiwen.com/subject/invrmhtx.html