数据结构之堆:堆的介绍与python实现——12

本文深入解析堆数据结构的定义与特性,探讨其在完全二叉树上的实现方式,以及如何通过Python代码实现堆的插入、排序与删除操作。文章详细介绍了堆的上浮与下沉过程,展示了如何维护堆的顺序,最后通过代码实例验证了堆的正确性和效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

堆的简单实现与代码实现

堆的定义

在定义堆(heap)之前,先回顾一下完全二叉树的定义:

  • 完全二叉树:除了最后一层的结点有可能没有达到最大值外,其它层的结点值都达到最大值,此外最后一层的叶子结点会尽可能连续集中在左边
    在这里插入图片描述
  • 堆的基本定义:堆是一种是基于树的专用数据结构,一般是将一颗完全二叉树的结点按照层序遍历的顺序存于数组中来实现的

堆具有以下几个特性

  • 在堆中,最高(或最低)优先级的元素始终都存储在堆的根目录(第一个储存元素的位置)
  • 堆中的父结点优先级总是大于等于(或小于等于)其子结点,但是其子结点并没有大小顺序之分,因此堆不能称作一种顺序数据结构,但是可以被当做是一种部分排序的储存结构
  • 堆的层次之间存在一个特殊关系,利用这个关系,可以代替索引的功能,找到对应的元素

堆的层次关系:

  • 如果一个结点的位置为k ,则它的父结点的位置为[k/2],而它的两个子结点的位置则分别为2k和2k+1。
  • 这样,在不使用指针的情况下.也可以通过计算数组的索引|在树中上下移动:从a[k]向上一层,就令k等于k/2,向下一层就令k等于2k或2k+1。
    在这里插入图片描述
    这里0索引不使用,因为索引从1开始会让操作更方便

堆中插入元素append()使用的排序方法之一上浮swim()过程
在这里插入图片描述
堆中删除最大元素的排序方法之一下沉sink()过程
在这里插入图片描述
下面用代码实现堆,层次往下时元素的值从大到小排列

堆的操作方法
  1. less()比较插入堆中的结点与当前节点的大小,辅助排序
  2. swap()交换结点的值,一般与less合用,达到排序效果
  3. append()向堆中尾部插入一个元素,其内部的swim()利用了堆的层次关系对元素进行上浮操作,实现父子结点间的大小排序
  4. delete_max()删除最大元素,并返回其最大值,其内部的sink()利用了堆的层次关系对元素进行下沉操作,实现父子结点间的大小排序
堆的Python代码实现
import operator


class Heap:
    def __init__(self):
        self.items = [None]
        self.N = 0  # The size of this heap

    def less(self, i, j):
        return operator.lt(self.items[i], self.items[j])

    def swap(self, i, j):
        self.items[i], self.items[j] = self.items[j], self.items[i]

    def append(self, item):
        """Append an element to its tail and do not use the index 0"""
        self.items.append(item)
        self.N += 1

        def swim(k):
            """Adjust the element's position, keeping the heap sequential"""
            while k > 1:
                if self.less(int(k / 2), k):
                    self.swap(int(k / 2), k)
                k = int(k / 2)

        swim(self.N)

    def delete_max(self):
        """Delete the max value(the item where index=1) in this heap and return it"""
        if self.N < 1:
            return
        # Swap items[1] with items[-1]
        _max = self.items[1]
        self.swap(1, self.N)
        # Delete items[-1]
        del self.items[self.N]
        # The length of this heap subtract 1
        self.N -= 1
        # print(f"Length: {self.N}, Length-real: {len(self.items)-1}")

        # Sink() to adjust the sequence of this heap
        def sink(k):
            """Compare the current element with the max of its child nodes"""
            while 2 * k <= self.N:
                # Take the max child's index
                index_of_max_child = 2 * k if 2 * k + 1 > self.N else \
                    (2 * k + 1 if self.less(2 * k, 2 * k + 1) else 2 * k)
                # When we found the position in where it should be, break the loop
                if self.less(index_of_max_child, k):
                    break
                # Else, swap the current node's value with its max child node's value
                self.swap(k, index_of_max_child)
                # Swap the current index with index_of_max_child, continue to do the while loop
                k = index_of_max_child
        sink(1)
        # Return the max value
        return _max
代码测试
if __name__ == '__main__':
    heap = Heap()

    heap.append('A')
    heap.append('B')
    heap.append('C')
    heap.append('D')
    heap.append('E')
    heap.append('F')
    heap.append('G')

    print(heap.N)
    # Iteratively delete the element in this heap
    res = heap.delete_max()
    while res:
        print(res, end=' ')
        res = heap.delete_max()

测试结果
7
G F E D C B A 

是从小到大插入的元素,但是是依次取出最大元素,所以结果是从大到小排列(注意根据插入顺序的不同,可能中间会有元素不是按照大小顺序排放,但是整体是从大到小排列的)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值