[BinaryTree] 最大堆的类实现
堆的定义:
最大树(最小树):每个结点的值都大于(小于)或等于其子结点(如果有的话)值的树。
最大堆(最小堆):最大(最小)的完全二叉树。
最大堆的抽象数据结构:
class MaxHeap
{
private:
T* heapArray; //存放堆数据的数组
int CurrentSize;//当前堆中元素数目
int MaxSize; //堆中能容纳的最大元素数目
public:
MaxHeap(T* array,int num,int max);
virtual ~MaxHeap()
{
delete []heapArray;
}
void BuildHeap();
void Swap(int pos_x,int pos_y); //交换位置x与y的元素
bool IsLeaf(int pos) const; //如果是叶子结点,返回true
int LeftChild(int pos) const; //返回左孩子位置
int RightChild(int pos) const; //返回右孩子位置
int Parent(int pos) const; //返回父结点位置
bool Remove(int pos,T& node); //删除给定下标元素
void SiftDown(int left); //筛选法函数,参数left表示开始处理的数组下标
void SiftUp(int position); //从position向上开始调整,使序列成为堆
bool Insert(const T& newNode); //向堆中插入新元素newNode
T& RemoveMax(); //从堆顶删除最大值
void print(); //输出函数
};
下面是一些简单函数的实现:
template<class T>
MaxHeap<T>::MaxHeap(T* array,int num,int max)
{
heapArray = array;
CurrentSize = num;
MaxSize = max;
}
template<class T>
void MaxHeap<T>::Swap(int pos_x,int pos_y)
{
T temp = heapArray[pos_x];
heapArray[pos_x] = heapArray[pos_y];
heapArray[pos_y] = temp;
}
template<class T>
bool MaxHeap<T>::IsLeaf(int pos) const
{
return (pos>=CurrentSize/)&&(pos<CurrentSize);
}
template<class T>
int MaxHeap<T>::LeftChild(int pos) const
{
return pos*+;
}
template<class T>
int MaxHeap<T>::RightChild(int pos) const
{
return pos*+;
}
template<class T>
int MaxHeap<T>::Parent(int pos) const
{
if(pos == )
return -;
return (pos-)/;
}
下面来看几个重要的操作的实现:
·堆的插入操作
(1)新元素添加到末尾(保持完全二叉树的性质);
(2)为了保持堆的性质,沿着其祖先的路径,自下而上依次比较和交换该结点与父结点的位置,直到重新满足堆的性质位置;
(3)在插入过程中,总是自下而上逐渐上升,最后停留在某个满足堆的性质的位置,故此过程又称为 “筛选”。
template<class T>
bool MaxHeap<T>::Insert(const T& newNode)
{
if(CurrentSize == MaxSize)
return false;
heapArray[CurrentSize] = newNode;
SiftUp(CurrentSize);
CurrentSize++;
return true;
}
·建堆过程
(1)首先将所有关键码放到一维数组中,这时形成的完全二叉树并不具备堆的特性,但是仅包含叶子结点的子树已经是堆 (即在有n个结点的完全二叉树中,当i > [n/2]-1时,以关键码Ki为根的子树已经是堆。
(2)这时从含有内部结点数最少的子树(这种子树在完全二叉树的倒数第二层,此时i = [n/2]-1开始,从右至左依次调整。
(3)对这一层调整完成之后,继续对上一层进行同样的工作,直到整个过程到达树根时,整棵完全二叉树就成为一个堆了
template<class T>
void MaxHeap<T>::BuildHeap()
{
for(int i = CurrentSize/-; i >= ; i--)
{
SiftDown(i);
}
}
·堆的删除操作
(1)把最末端结点填入删除产生的空位(保持完全二叉树的性质)
(2)为了保持堆的性质,比较当前结点和其父节点的大小来决定向上还是向下“筛选”,直到重新满足堆的性质位置
template<class T>
bool MaxHeap<T>::Remove(int pos,T& node)
{
if(pos < || pos >= CurrentSize)
return false;
node = heapArray[pos];
heapArray[pos] = heapArray[--CurrentSize];
if(heapArray[Parent(pos)] < heapArray[pos])
{
SiftUp(pos);
}
else SiftDown(pos);
return true;
}
下面是删除堆顶元素的代码:
template<class T>
T& MaxHeap<T>::RemoveMax()
{
if(CurrentSize == )
{
cout<<"Can't delete"<<endl;
exit();
}
else
{
Swap(,--CurrentSize);
if(CurrentSize>)
{
SiftDown();
}
return heapArray[CurrentSize];
}
}
下面是该类的核心代码:
向下筛选:
template<class T>
void MaxHeap<T>::SiftDown(int left)
{
int i = left; //标识父结点
int j = LeftChild(i); //标识关键码较小的子结点
T temp = heapArray[i]; //保存父结点
while(j < CurrentSize) //筛选
{
if((j < CurrentSize-)&&(heapArray[j] < heapArray[j+]))
{//若有右结点,且大于左结点
j++; //则j指向右结点
}
if(temp < heapArray[j])
{//若父结点小于子结点的值则交换位置
heapArray[i] = heapArray[j];
i = j;
j = LeftChild(j);
}
else break;//找到恰当的位置,跳出循环
}
heapArray[i] = temp;
}
向上筛选:
template<class T>
void MaxHeap<T>::SiftUp(int position)
{ //从position开始向上调整
int tempos = position;
T temp = heapArray[tempos];
while((tempos > )&&(temp > heapArray[Parent(tempos)]))
{
heapArray[tempos] = heapArray[Parent(tempos)];
tempos = Parent(tempos);
}
heapArray[tempos] = temp;
}
测试函数:
int main()
{
int a[] = {,,,,,,,,,};
MaxHeap<int> S(a,,);
cout<<"构建最大堆:"<<endl;
S.BuildHeap();
S.print();
cout<<"插入元素10:"<<endl;
int newNode = ;
S.Insert(newNode);
S.print();
cout<<"删除堆顶元素:"<<endl;
S.RemoveMax();
S.print();
cout<<"删除pos = 1的元素:"<<endl;
int x;
S.Remove(,x);
cout<<"x = "<<x<<endl;
S.print();
return ;
}
测试结果:

[BinaryTree] 最大堆的类实现的更多相关文章
- Java类的继承与多态特性-入门笔记
相信对于继承和多态的概念性我就不在怎么解释啦!不管你是.Net还是Java面向对象编程都是比不缺少一堂课~~Net如此Java亦也有同样的思想成分包含其中. 继承,多态,封装是Java面向对象的3大特 ...
- MVC+EF 理解和实现仓储模式和工作单元模式
MVC+EF 理解和实现仓储模式和工作单元模式 原文:Understanding Repository and Unit of Work Pattern and Implementing Generi ...
- 携程Android App插件化和动态加载实践
携程Android App的插件化和动态加载框架已上线半年,经历了初期的探索和持续的打磨优化,新框架和工程配置经受住了生产实践的考验.本文将详细介绍Android平台插件式开发和动态加载技术的原理和实 ...
- 省身 (zhuan)
http://blog.csdn.net/marksinoberg/article/details/52419152 ***************************************** ...
- [百度空间] [转]DLL地狱及其解决方案
DLL地狱及其解决方案 原作者:Ivan S Zapreev 译者:陆其明概要 本文将要介绍DLL的向后兼容性问题,也就是著名的“DLL Hell”问题.首先我会列出自己的研究结果,其中包括其它一些研 ...
- c#winform使用WebBrowser 大全[超长文转载]
1.主要用途:使用户可以在窗体中导航网页. 2.注意:WebBrowser 控件会占用大量资源.使用完该控件后一定要调用 Dispose 方法,以便确保及时释放所有资源.必须在附加事件的同一线程上调用 ...
- (翻译)什么是Java的永久代(PermGen)内存泄漏
http://www.codelast.com/?p=7248 转载请注明出处:http://www.codelast.com/ 本文是我对这篇文章的翻译:What is a PermGen leak ...
- My.Ioc 代码示例——使用条件绑定和元数据(可选)构建插件树
本文旨在通过创建一棵插件树来演示条件绑定和元数据的用法. 说“插件树”也许不大妥当,因为在一般观念中,谈到插件树,我们很容易会想到 Winform/Wpf 中的菜单.举例来说,如果要在 Winform ...
- [欢度国庆]为什么我们今天还要学习和使用C++?(转载)
在各种新的开发语言层出不穷的今天,在Java和C#大行其道今天,我们为什么还要学习和使用C++?现在学习C++将来有用吗?学习C++要花费那么多时间和精力,这一切都值得吗?现在学习C++有钱途吗? 这 ...
随机推荐
- VS中添加lib与dll
参考与拓展阅读:https://blog.csdn.net/u012043391/article/details/54972127 lib: 1.附加包含目录---添加工程的头文件目录: ...
- FPGA基础知识,应用,ASIC、ASSP区别(四)
一.ASIC与ASSP区别? 专用应用集成电路( ASIC) 是一种由电子组件组成的集成电路,例如 :晶体管.电容器.电阻器等,这些组件被植入到晶元上 :晶元由硅或其他半导体材料组成,并可按照特定用途 ...
- gp与 pg 查询进程
select now()-query_start as cost_time,* from pg_stat_activity where current_query not in ( '<IDLE ...
- python--基本类型之集合
set(集合): 定义和创建: 定义:集合是一个无序的,不重复的数据集合,它主要作用1:去重,把一个列表变成集合,就自动去重了2:关系测试,测试两组数据之间的交集,差集,并集等关系 集合:把不同的数据 ...
- 南京Uber优步司机奖励政策(12月14日到12月20日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- LeetCode:43. Multiply Strings (Medium)
1. 原题链接 https://leetcode.com/problems/multiply-strings/description/ 2. 题目要求 给定两个String类型的正整数num1.num ...
- Android AOSP 单独编译某一模块
由于AOSP 项目太大,我只修改了一个模块,比如设置. 那么只需要单独编译设置这个模块就可以了. 首先执行Source: source build/envsetup.sh 执行之后,就会有一些额外的命 ...
- 海思NB-IOT的RA功能
就带ReleaseAssistance标志的特殊发送指令,发送数据的时候会向网络侧请求立即释放RRC进入Idle态. 降低20秒50mA连接态的能量消耗.
- linux下免安装版本mysql5.5 配置
进入/usr/local #cd /usr/local 下载 #wget http://dev.mysql.com/get/Downloads/MySQL-5.5/mysql-5.5.39-linux ...
- python 水仙花
#简单def narcissus(): for n in range(100, 1000, 1): a, b, c = n//100, (n//10)%10, (n%100)%10 if a ** 3 ...