一文学会数据结构-堆

一文学会数据结构-堆

什么是堆

在计算机科学中,堆是一个特殊的树状数据结构。堆通常有如下几个特性:

  1. 堆是完全二叉树;
  2. 堆中每个节点的值都大于或等于(小于或等于)其子节点的值,这个取值规则称为堆的“属性”;
  3. 堆顶元素(即根节点)总是为最大值或最小值。

堆的种类

堆分为小根堆和大根堆两种。小根堆要求每个节点的值都不大于其父节点的值,即A[PARENT[i]] <= A[i];大根堆要求每个节点的值都不小于其父节点的值,即A[PARENT[i]] >= A[i]。

优先队列

堆可以用于组成优先队列。优先队列是一种数据结构,其中每个元素有一个“优先级”或“关键值”,优先级高的元素先被处理。当然,堆并不是唯一可以组成优先队列的数据结构,但堆的效率要高得多。

实现堆

堆是通过数组实现的。令i表示二叉树中节点的序号,A[i]表示存储在该节点的元素。

  1. 父节点的位置为 Parent(i) = floor(i/2)
  2. 左子节点的位置为 Left(i) = 2i
  3. 右子节点的位置为 Right(i) = 2i + 1

实现中我们可以使用数组存储堆,这样可以快速寻找到每个节点的父节点和子节点。

堆的操作

下面介绍堆的几个常见操作:

堆化(Heapify)

将i结点以下的堆整体调整成最大堆或最小堆,时间复杂度为O(logN)。

# 以大根堆为例
def heapify(arr, n, i):
    # 初始化最大值位置
    largest = i 
    left = 2 * i + 1
    right = 2 * i + 2

    # 如果左子节点的值大于父节点的值,更新最大值位置
    if left < n and arr[i] < arr[left]:
        largest = left

    # 如果右子节点的值大于最大值位置节点的值,更新最大值位置
    if right < n and arr[largest] < arr[right]:
        largest = right

    # 如果最大值位置不是父节点位置,则交换这两个节点的值,并递归调用heapify
    if largest != i:
        arr[i], arr[largest] = arr[largest], arr[i]
        heapify(arr, n, largest)

建堆

通过对所有元素进行一次heapify操作实现,建堆的时间复杂度为O(n)。

def build_heap(arr, n):
    # 从最后一个非叶子节点开始heapify
    for i in range(int(n / 2) - 1, -1, -1):
        heapify(arr, n, i)

插入(Insertion)

将新元素插入到堆中,保证堆的属性。时间复杂度为O(logN)。

def insert(arr, element):
    arr.append(element)
    i = len(arr) - 1
    p = int((i - 1) / 2)
    while i > 0 and arr[p] < arr[i]:
        arr[p], arr[i] = arr[i], arr[p]
        i = p
        p = int((i - 1) / 2)

删除堆顶元素(Remove)

删除堆顶元素并返回其值,时间复杂度为O(logN)。

def remove(arr):
    n = len(arr)
    # 如果堆为空,则返回None
    if n == 0:
        return None
    # 如果堆中只有一个元素,则直接返回该元素
    if n == 1:
        return arr.pop()
    # 弹出堆顶元素,并将末尾元素移动到堆顶
    top = arr[0]
    arr[0] = arr.pop()
    n = len(arr)
    # 对新的堆顶元素进行一次heapify操作,使得剩余元素保持堆的属性
    heapify(arr, n, 0)
    return top

示例

示例1

给定数组 [3, 2, 1, 6, 5, 4],按升序排列后的结果为 [1, 2, 3, 4, 5, 6]。下面是一个Python实现:

# 堆排序
def heap_sort(arr):
    # 首先将数组构建为最大堆
    build_heap(arr, len(arr))
    # 将最大的元素交换到数组末尾,并缩小堆的范围
    for i in range(len(arr) - 1, 0, -1):
        arr[i], arr[0] = arr[0], arr[i]
        heapify(arr, i, 0)

arr = [3, 2, 1, 6, 5, 4]
heap_sort(arr)
print(arr)

输出: [1, 2, 3, 4, 5, 6]

示例2

使用堆来解决“TOP K 问题”,即在一个无序的整数数组中,找到最大的K个数。下面是一个Python实现:

import heapq

def top_k(arr, k):
    # 取前K个数,建立一个小根堆
    heap = arr[:k]
    heapq.heapify(heap)
    # 对于剩下的元素,如果比堆顶元素大,则弹出堆顶,并将该元素压入堆中
    for element in arr[k:]:
        if element > heap[0]:
            heapq.heappop(heap)
            heapq.heappush(heap, element)
    # 返回堆中的元素,即为前K大的数
    return heap

arr = [4, 3, 6, 5, 9, 8]
print(top_k(arr, 3)) # 输出: [6, 8, 9]

输出 [6, 8, 9],为原数组中最大的三个数。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:一文学会数据结构-堆 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • C语言数据结构中约瑟夫环问题探究

    C语言数据结构中约瑟夫环问题探究 什么是约瑟夫环问题? 约瑟夫环问题(Josephus problem)是一个经典的问题,据说是Flavius Josephus发现并命名的。该问题描述为,编号从1到n的n个人按照顺时针方向围坐成一圈,每人持有一个密码。从第1个人开始,顺时针方向每次完整的数m个人,然后让这m个人出圈并把他们的密码拿走不算。当到达队尾时,又从队…

    数据结构 2023年5月17日
    00
  • C++ 超详细分析数据结构中的时间复杂度

    C++ 超详细分析数据结构中的时间复杂度攻略 什么是时间复杂度? 时间复杂度是用来衡量算法效率的指标,它表示的是算法的执行时间与问题规模之间的关系,通常用大O记法来表示。 如何分析时间复杂度? 1. 常见时间复杂度 以下是常见的时间复杂度及其对应的执行次数: 时间复杂度 对应执行次数 O(1) 常数级别 O(log n) 对数级别 O(n) 线性级别 O(n…

    数据结构 2023年5月17日
    00
  • 一文带你走进js数据类型与数据结构的世界

    一文带你走进JS数据类型与数据结构的世界 一、JS数据类型 1. 原始类型 JS中原始类型包括:Undefined、Null、Boolean、Number、String、Symbol(ES6新增)。 其中Undefined和Null分别代表未定义和空值,Boolean表示布尔值,Number表示数字,String表示字符串,Symbol是ES6新增的一种基础…

    数据结构 2023年5月17日
    00
  • 算法总结–ST表

    声明(叠甲):鄙人水平有限,本文为作者的学习总结,仅供参考。 1. RMQ 介绍 在开始介绍 ST 表前,我们先了解以下它以用的场景 RMQ问题 。RMQ (Range Minimum/Maximum Query)问题是指:对于长度为n的数列A,回答若干询问RMQ(A,i,j)(i,j<=n),返回数列A中下标在i,j里的最小(大)值,也就是说,RMQ…

    算法与数据结构 2023年4月18日
    00
  • Java常见基础数据结构

    Java常见基础数据结构攻略 Java是一种面向对象的编程语言,拥有丰富的数据结构,大多数基础数据结构都包含在Java API中。在本文中,我们将讨论Java中常见的基础数据结构,包括数组、链表、栈、队列、集合和映射。我们将探讨每种数据结构的定义、用法和基本操作,并提供两个示例说明。 数组 数组是Java中最基本的数据结构之一。它是一个有序的集合,可以包含任…

    数据结构 2023年5月17日
    00
  • java数据结构和算法中哈希表知识点详解

    Java数据结构和算法中哈希表知识点详解 什么是哈希表 哈希表是一种以键值对(key-value)形式存储数据的数据结构,通过使用哈希函数将对应的键映射为一个索引,使得数据的添加、删除、查找等操作可以在常数时间内完成。 具体来讲,哈希表主要包含以下几个部分: 哈希函数:将键转换为一个索引,通常使用散列算法实现。 数组:用于存储哈希表的元素(键值对)。 冲突解…

    数据结构 2023年5月17日
    00
  • php数据结构与算法(PHP描述) 查找与二分法查找

    以下是详细讲解“php数据结构与算法(PHP描述) 查找与二分法查找”的完整攻略。 1. 数据结构与算法简介 数据结构是计算机中存储和组织数据的方式。它涉及到数据的表示、处理和存储方式等。 算法则是完成特定任务的步骤集合。算法设计可以优化计算机程序的效率和速度。 PHP是一种非常流行的服务器端脚本语言,数据结构和算法对web开发者来说非常重要。因此,我们需要…

    数据结构 2023年5月17日
    00
  • C语言数据结构之 折半查找实例详解

    C语言数据结构之 折半查找实例详解 什么是折半查找? 折半查找是一种在有序数组中查找某个特定元素的算法。其基本思想是将查找的值与数组的中间元素比较,如果比中间元素小,则在数组的左半部分查找;如果比中间元素大,则在数组的右半部分查找,直到找到该元素或查找范围为空。 折半查找算法的流程 确定要查找的数组arr和其元素个数n,以及要查找的元素value。 设定左边…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部