定义:一棵大根树(小根树)是这样一棵树,其中每一个节点的值都大小(小于)或等于其子节点(如果有子节点的话)的值。

一个大根堆(小根堆)既是大根树(小根树)也是完全二叉树。

大根堆

小根堆

本篇主要实现大根堆的初始化,插入以及删除操作。

在实现这些之前,先来简单介绍一下大根堆类的主要数据成员:

私有成员变量:

heap:一维数组,用于存储堆中的元素;

heapSize:整型变量,用于记录堆中元素个数;

arrayLength:整形变量,用于记录堆最大容量,即最多可以容纳多少个元素;

公有成员函数:

initialize(T* ,int):初始化最大堆,第一个形参为初始化的数组,第二个形参为元素个数;

remove(int);删除最大堆中特定元素;

push(const T&);添加新元素;

私有成员函数:

changeArrayLength(T*, int):当实际容量等于额定容量时,扩充额定容量;

adjust(T&,int, int):用于调整堆结构的函数,插入删除和初始化都会用到;

堆虽然也是二叉树,但本例中没有使用构建树的方式(即用节点指针)来构建最大堆,而是用数组的方式存储元素,这样我们假设数组[1:heapSize]用来存储堆元素,而对堆中元素进行调整的过程就是改变元素在数组中位置的过程。

另外需要明确的是,1是根节点的下标,heapSize/2是最后一个节点的父节点下标。

对于某一个节点下标n来说,如果2*n<=heapSize,则2*n是该节点左孩子的下标;

如果2*n+1<=heapSize,则2*n+1是该节点右孩子的下标。

首先来看一下初始化操作的实现,传入的参数为一维数组和元素个数。

步骤1:用参数的数组初始化堆中数组heap,用第二个参数初始化堆中元素个数heapSize;

步骤2:从最后一个节点的父节点开始(heapSize/2),一个个循环,每次循环结束节点索引减一。即第一次是heapSize/2,第二次则是heapSize/2-1,第三次是heapSize/2-2,一直循环到1。暂且叫步骤2为外层循环,该循环是逐个向上。每循环完一次都确保以该下标的节点为根节点的子树是一个最大堆。

步骤3:在步骤2中的每一次循环中(内层循环),逐层向下索引,同时比较当前结点和其子节点的大小,将大节点作为子树的根节点,将原先的根节点下移到子树的位置。直到索引到达heapSize。与步骤2不同,步骤3是逐层向下索引,即某一次索引为n,则下一次是2*n。

template<class T>
void maxHeap<T>::initialize(T* theHeap, int theSize)
{delete[] heap; //删除堆中原先的元素heap = theHeap; //指针赋值,将参数中数组的元素赋值给堆heapSize = theSize; //元素个数赋值//执行循环,从最后一个节点的父节点开始,逐个向上,外层循环for(int root = heapSize/2; root >= 1; --root)   {T theElement = heap[root]; //保存外层循环的当前结点,每次都可以理解为给这个值找位置。//内层循环开始,给theElement找位置,将大的上移,大节点原先的位置变成空位置。int currentNode = root; //始终是空位置的下标,也是child下标的父节点位置int child = 2*root;  //当前结点左孩子下标while(child <= heapSize){if(child < heapSize && heap[child+1] > heap[child])++child;    //令child指向值较大的孩子//如果theElement比两个孩子都大,那么就证明找到位置if(theElement > heap[child])break;//如果没有找到,将大的节点放在空位置上,大节点原先的位置变为空位置heap[currentNode] = heap[child];current = child;//更新孩子下标,继续向下寻找位置child *= 2;   }}//找到位置,将theElement放在空位置上heap[currentNode] = theElement;
}

接下来是插入操作,参数是要插入的值theElement,原理同初始化一样,也是为theElement找位置,只是开始的位置不是heapSize/2,而是(++heapSize)/2。此时空位置是heapSize。

步骤1:检查数组容量,如果数组满了,则需要扩充数组大小。

步骤2:堆元素个数加一。

步骤3:比较theElement和当前节点大小,如果theElement大,则把当前结点移动到空位置上,把该节点原先的位置设为空位置。继续向上寻找。

template<class T>
void maxHeap<T>::push(const T& theElement)
{//检测堆是否已满,若满则需要扩充if(heapSize == arrayLength - 1){changeArrayLength(heap, 2*heapSize);heapSize *= 2;}int currentNode = ++heapSize; //堆元素个数加一,空位置为末尾下标//从下到上一层一层比较,把小节点下移,空位置上移。//直到空位置的父节点比theElement大,子节点比theElement小while(currentNode != 1 && heap[currentNode/2] < theElement){heap[currentNode] = heap[currentNode/2];currentNode /= 2;}heap[currentNode] = theElement;
}

最后是删除操作,参数是要删除的下标索引。删除后,以该位置为根节点的子树已经不是最大堆,只需要对这一小部分进行调整。

原理依旧相同,把要删除的那个下标设为空位置。逐层向下寻找位置,把大节点上移,空位值下移。

步骤1:取出末尾下标的元素theElement,并将堆元素个数减一。

步骤2:在以删除节点为根节点的子树中为theElement找位置。

template<class T>
T maxHeap<T>::remove(int index)
{//判断下标是否合法if(index < 1 || index > heapSize)throw heapError("Error: the index is illegal"); T theElement = heap[heapSize--]; //取出最后一个元素,同时元素个数减一int currentNode = index;   //始终指向空位置,也是child的父节点int child = 2 * index; while(child <= heapSize){//令child是较大孩子的下标if(child < heapSize && heap[child+1] > heap[child])child++;//如果theElement大,则说明找到位置存放theElement了if(theElement > heap[child])return;//若没找到,继续向下寻找heap[currentNode] = heap[child];currentNode = child;child *= 2;}heap[currentNode] = theElement;return theElement;
}

另外因为初始化和删除操作中while循环中的部分相同,可以单独抽出来作为一个私有成员函数。

数据结构-----最大堆的实现相关推荐

  1. java数据结构--最大堆

    概念: 最大堆是堆的两种形式之一. 根节点(亦称为堆顶)的关键字是堆里所有结点关键字中最大者,称为大根堆,又称最大堆(大顶堆). 实现方法(java): 可以自己写一个类,包含左节点和右节点,但是在这 ...

  2. 数据结构——最大堆和最小堆(C语言)

    定义: 最大堆和最小堆都是一棵完全二叉树. 最大堆:是指根节点的关键字值是堆中的最大关键字值,且每个节点若有儿子节点,其关键字值都不小于其儿子节点的关键字值. 最小堆:是指根节点的关键字值是堆中的最小 ...

  3. 数据结构 堆中的路径(最小堆)

    题目: 将一系列给定数字插入一个初始为空的小顶堆H[ ].随后对任意给定的下标i,打印从H[i]到根结点的路径. 输入格式: 每组测试第1行包含2个正整数N和M(≤1000),分别是插入元素的个数.以 ...

  4. 字节跳动三轮技术面_后端研发提前批

    点击上方"code小生",选择"星标" 我们一起「在看」 作者:炼狱的吹笛人 链接:https://www.jianshu.com/p/a44f2e25d98d ...

  5. 字节跳动Java面试难吗,应该如何应对?应付秋招你只需要这样做

    前言: 先自我介绍一下,本人是18届校招学生,普通211的文科类专业.我是抖音和头条的深度用户,所以对于我来讲,字节跳动是我心中top1的公司,而最后也如愿以偿的拿到了字节跳动的 每次面试都会淘汰人, ...

  6. 数据结构-堆(最大堆)

    最大堆 实质是一棵完全二叉树 每个根结点元素的值都比左右儿子的大 每次都是取出堆顶元素(可以说是优先队列) 代码 参考自浙大数据结构 #include <iostream> #includ ...

  7. php里面优先级最高的是,数据结构-PHP 优先级队列(最大堆)的实现

    ​这篇文章主要介绍如何使用最大堆这种数据结构实现优先队列. 1.优先队列介绍 对于 普通队列,数据元素是 First In First Out,而对于 优先队列 是出队顺序和入队顺序无关,和优先级相关 ...

  8. C++数据结构与算法(九) 树,优先级队列,最大堆的实现

    树: 用来表示具有结构层次的数据,应用: 软件工程技术:模块化技术 根: 子树: 在树中,每个元素都代表一个节点. 树的级: 根是一级,根的孩子是二级,一次往下,有三级,四级... 树的高度(深度): ...

  9. 最大堆和最小堆(数据结构)

    堆和栈的区别: 一.空间分配区别: 栈(操作系统):由操作系统自动分配释放,存放函数的参考值,局部变量的值等.其操作方式类似于数据结构中的栈 堆(操作系统):一般由程序员分配释放,若程序员不释放,程序 ...

最新文章

  1. SL专题2:加入并熟悉Second Life世界
  2. linux系统 opt扩容,Linux系统扩容根目录磁盘空间的操作方法
  3. 服务发现与健康监测框架Consul-DNS转发的应用
  4. php角色权限安全,php – 安全的chmod权限?
  5. 最早单机的计算机操作系统,川农《计算机操作系统(本科)》19年12月在线作业【满分答案】...
  6. 在libevent中使用线程池
  7. 微助教课件怎么下载_【微助教课件下载】[微助教]自测一下,您的课堂有好的开始和结束么?...
  8. Mycat安全权限配置user_配置mycat用户只读数据---MyCat分布式数据库集群架构工作笔记0031
  9. 越混越差的十个原因,看看你有没有?
  10. datatables 一列显示两个字段的数据_5个超实用的Excel数据透视表技巧,学会少加班...
  11. 计算机系统 cpu课程,计算机操作系统
  12. php期末考试题机考_phP基础知识期末考试题.doc
  13. 纯js实现数据导出excel表格
  14. 软件测试理论思维导图
  15. EnhancedFor
  16. Exchange Server 2016下载链接
  17. GamePlay架构
  18. 《中国程序化广告技术生态图》2015年三月号更新发布
  19. Python中的迭代是什么意思?
  20. 集成讯飞离线语音合成SDK报:“ 未经授权的语音应用.(错误码:11210)“ 问题解决

热门文章

  1. 找出1000以内的完数,所谓完数是指该数的各因子之和等于该数,如:6 = 1+2+3。
  2. 程序员面试100题之十六:二叉树中两个节点的最近公共父节点
  3. 如何在Anaconda中实现多版本python Spyder共存
  4. squirrelsql安装
  5. 黑白棋子的移动(东方化改题+???)
  6. js如何判断一个对象是不是Array
  7. Windows 下OpenSSL 安装详解 +图解
  8. Oracle中使用Table()函数解决For循环中不写成 in (l_idlist)形式的问题
  9. C# 网络编程之通过ip地址获取地理位置(补充)
  10. SwiftUI之深入解析属性包装器如何处理结构体