原文地址

我有一个不成熟的建议:老老实实花1个小时把这篇文章仔细看完,关于堆的各种操作一目了然了。

关于最大堆

什么是最大堆和最小堆?最大(小)堆是指在树中,存在一个结点而且该结点有儿子结点,该结点的data域值都不小于(大于)其儿子结点的data域值,并且它是一个完全二叉树(不是满二叉树)。注意区分选择树,因为选择树(selection tree)概念和最小堆有些类似,他们都有一个特点是“树中的根结点都表示树中的最小元素结点”。同理最大堆的根结点是树中元素最大的。那么来看具体的看一下它长什么样?(最小堆这里省略)


这里需要注意的是:在多个子树中,并不是说其中一个子树的父结点一定大于另一个子树的儿子结点。最大堆是树结构,而且一定要是完全二叉树。

最大堆ADT

那么我们在做最大堆的抽象数据类型(ADT)时就需要考虑三个操作:
(1)、创建一个最大堆;
(2)、最大堆的插入操作;
(3)、最大堆的删除操作;
最大堆ADT如下:

struct Max_Heap {object: 由多个元素组成的完全二叉树,其每个结点都不小于该结点的子结点关键字值functions:其中heap∈Max_Heap,n,max_size∈int,Element为堆中的元素类型,item∈ ElementMax_Heap createHeap(max_size)       := 创建一个总容量不大于max_size的空堆void max_heap_insert(heap, item ,n) := 插入一个元素到heap中Element max_heap_delete(heap,n)     := if(heap不为空) {return 被删除的元素 }else{return NULL}
}
///其中:=符号组读作“定义为”

最大堆内存表现形式

我们只是简单的定义了最大堆的ADT,为了能够用代码实现它就必须要考虑最大堆的内存表现形式。从最大堆的定义中,我们知道不管是对最大堆做插入还是删除操作,我们必须要保证插入或者删除完成之后,该二叉树仍然是一个完全二叉树。基于此,我们就必须要去操作某一个结点的父结点。
  第一种方式,我们使用链表的方式来实现,那么我们需要添加一个额外的指针来指向该结点的父结点。此时就包括了左子结点指针、右子结点指针和父结点指针,那么空链的数目有可能是很大的,比如叶子结点的左右子结点指针和根结点的父结点指针,所以不选择这种实现方式(关于用链表实现一般二叉树时处理左右子结点指针的问题在线索二叉树中有提及)。
  第二种方式,使用数组实现,在二叉树进行遍历的方法分为:先序遍历、中序遍历、后序遍历和层序遍历。我们可以通过层序遍历的方式将二叉树结点存储在数组中,由于最大堆是完全二叉树不会存在数组的空间浪费。那么来看看层序遍历是怎么做的?对下图的最大堆进行层序遍历:



从这里可以看出最后得到的顺序和上面图中所标的顺序是一样的。
  那么对于数组我们怎么操作父结点和左右子结点呢?对于完全二叉树采用顺序存储表示,那么对于任意一个下标为i(1 ≤ i ≤ n)的结点:
(1)、父结点为:i / 2(i ≠ 1),若i = 1,则i是根节点。
(2)、左子结点:2i(2i ≤ n), 若不满足则无左子结点。
(3)、右子结点:2i + 1(2i + 1 ≤ n),若不满足则无右子结点。


最终我们选择数组作为最大堆的内存表现形式。
基本定义:

#define MAX_ELEMENTS 20
#define HEAP_FULL(n) (MAX_ELEMENTS - 1 == n)
#define HEAP_EMPTY(n) (!n)
typedef struct {int key;
}element;
element heap[MAX_ELEMENTS];

下面来看看最大堆的插入、删除和创建这三个最基本的操作。

最大堆的插入

最大堆的插入操作可以简单看成是“结点上浮”。当我们在向最大堆中插入一个结点我们必须满足完全二叉树的标准,那么被插入结点的位置的是固定的。而且要满足父结点关键字值不小于子结点关键字值,那么我们就需要去移动父结点和子结点的相互位置关系。具体的位置变化,可以看看下面我画的一个简单的图。

void insert_max_heap(element item ,int *n){if(HEAP_FULL(*n)){return;}int i = ++(*n);for(;(i != 1) && (item.key > heap[i/2].key);i = i / 2){/// i ≠ 1是因为数组的第一个元素并没有保存堆结点heap[i] = heap[i/2];/// 这里其实和递归操作类似,就是去找父结点}heap[i] = item;
}


由于堆是一棵完全二叉树,存在n个元素,那么他的高度为:log2(n+1),这就说明代码中的for循环会执行O(log2(n))次。因此插入函数的时间复杂度为:O(log2(n))。

最大堆的删除

最大堆的删除操作,总是从堆的根结点删除元素。同样根元素被删除之后为了能够保证该树还是一个完全二叉树,我们需要来移动完全二叉树的最后一个结点,让其继续符合完全二叉树的定义,从这里可以看作是最大堆最后一个结点的下沉(也就是下文提到的结点1)操作。例如在下面的最大堆中执行删除操作:


现在对上面

最大堆(创建、删除、插入和堆排序)图文详解相关推荐

  1. html中删除指定数组下标,图文详解JavaScript中删除数组某个元素的方法

    在前端开发中经常需要使用JavaScript,那你知道如何用JS删除数值的指定元素吗?这篇文章就给大家分享JS删除数组某个元素的几种方法,感兴趣的朋友可以参考一下,希望可以帮助到你. 方法一:slic ...

  2. Windows 08 R2_创建AD DS域服务(图文详解)

    目录 目录 Active Directory概念 创建第一个AD域控制器 搭建DNS服务器 使用Windows窗口程序创建AD域控制器 AD与LDAP的关系 使用Powershell来创建ADDS域控 ...

  3. ad域需要自建dns服务器吗,创建AD DS域服务(图文详解)

    Active Directory概念 AD(活动目录):是一种组织资源信息的方法,目录的意义在于我们可以通过标题或者说搜索条件来简单而有效率的在大量数据中查找匹配的信息.支撑这种信息检索的技术就是LD ...

  4. win10计算机恢复到一天前,Win10恢复电脑(刷新电脑)的方法步骤图文详解

    注:本教程同样适用于Win8.1系统 有时候,遇到Win10系统出现了比较严重的问题,那么这时有比重装系统更好的办法就是"恢复电脑(刷新电脑)".因为重装系统就会丢失之前系统的个人 ...

  5. 目录树 删除 数据结构_数据结构:B树和B+树的插入、删除图文详解

    B树 1.1B树的定义 B树也称B-树,它是一颗多路平衡查找树.我们描述一颗B树时需要指定它的阶数,阶数表示了一个结点最多有多少个孩子结点,一般用字母m表示阶数.当m取2时,就是我们常见的二叉搜索树. ...

  6. 数据结构:B树和B+树的插入、删除图文详解

    目录 B树 1.1B树的定义 1.2B树的插入操作 1.3B树的删除操作 B+树 2.1 B+树的定义 2.2 B+树的插入操作 2.3 B+树的删除操作 B树 1.1B树的定义 B树也称B-树,它是 ...

  7. storyboard(故事版)新手教程 图文详解 1.创建一个无约束的导航栏加选项卡(tabbar)故事版

    OSX系统10.10.5 Xcode版本7.1 本文图文详解如何初步使用故事版进行开发 1.打开Xcode  点击Create a new Xcode project 选择Single View Ap ...

  8. Java数据结构与算法-SingleLinkedList单向链表插入,删除,查找,修改详解及代码

    SingleLinkedList单向链表插入,删除,查找,修改详解及代码 单向链表学习目标 1. 链表的介绍 2. 单向链表的存储特点以及原理 3. 基本操作:插入,删除等 4. 单向链表应用场景举例 ...

  9. 图文详解 IntelliJ IDEA 15 创建 Maven 构建的 Java Web 项目(使用 Jetty 容器)

    图文详解 IntelliJ IDEA 15 创建 maven 的 Web 项目 搭建 maven 项目结构 1.使用 IntelliJ IDEA 15 新建一个项目.    2.设置 GAV 坐标  ...

  10. mysql压缩包删除_mysql解压缩方式安装和彻底删除的方法图文详解

    一.安装mysql (1)将下载下来的mysql压缩文件解压缩到需要安装mysql的目录中 (2)打开解压后的文件夹,复制default.ini文件并重命名为my.ini,此文件的相关配置为: (3) ...

最新文章

  1. 网络规划设计师考试命题模式持续在变   你变不变
  2. MFC中Mat实现打开关闭本地摄像头
  3. CV之IS:利用pixellib库基于mask_rcnn_coco模型对《庆余年》片段实现实例分割简单代码全实现
  4. WatchOS系统开发大全(3)-创建第一个WatchApp工程
  5. Android获取网络状态
  6. BZOJ 1188: [HNOI2007]分裂游戏(multi-nim)
  7. Burpsuite技巧之MD5加密密码爆破、带验证码爆破
  8. c语言ascw,VBS中的Asc/AscB/AscW和Chr/ChrB/ChrW函数之间的区别
  9. CheckBoxList 全选(jquery版本)
  10. [ECMAScript] 说说你对class的理解
  11. Power BI 数据可视化软件实现共享报表
  12. 【1+X Web前端等级考证 】| 最新Web前端开发中级实操
  13. React 引入阿里矢量图标方法
  14. fgo最新服务器,《FGO》:现在世界上其他地区的服务器近况如何,一起来看看吧!...
  15. 金蝶计算机快捷键,金蝶KIS专业版常用快捷键列表.doc
  16. 【修复收藏功能、更新登录接口】知识付费小程序、博客小程序、完整版开源源码、资源变现小程序
  17. iOS开发者,金九银十,这样写简历才能让大厂面试官看重你!
  18. 全国应用计算机水平考试,全国计算机应用水平考试
  19. ALSA子系统(一)------Frames Periods
  20. 计算机的用户账户,电脑用户名_电脑用户名是什么

热门文章

  1. 自建魔兽世界sf服务器,魔兽世界80自己搭服务器,热度却持续不到一天,全部用命令!...
  2. 计算机里的及格率和有优秀率怎么算,excel表格计算优秀及格率的教程
  3. element el-table表头添加背景图片
  4. POJ 3388 Japanese Puzzle(二分法)
  5. request爬虫爬取电影并利用pyqt5进行本地播放(失败品)
  6. python图形化界面设计gui_Python图形界面GUI程序设计
  7. 建设工程施工合同系列一建工合同的范围(未完待续)
  8. JAVA山地车deca_越野怪兽 JAVA摆渡人 (ANIMA)山地车
  9. linux cat -A 隐藏符号显示
  10. 助力操作系统国产化:Testin云测试服贸会首发鸿蒙系统测试平台