[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++有钱途吗? 这 ...
随机推荐
- vim 智能提示插件 YouCompleteMe安装
按照网上的教程安装该软件,没有一篇是成功的(也有可能是没找对).自己从网上东拼西凑的,终于让自己的vim智能识别了. 1. 升级 vim: (ubuntu) sudo add-apt-reposito ...
- LeetCode: 58. Length of Last Word(Easy)
1. 原题链接 https://leetcode.com/problems/length-of-last-word/description/ 2. 题目要求 给定一个String类型的字符串,字符串中 ...
- Linux怎样创建FTP服务器--修改用户默认目录-完美解决 - 费元星
在创建FTP服务器之有先命令: ps -ef |grep vsftpd 查一下系统有没有安装vsftpd这个服务器,如果出现如下图所示的界面说明没有安装. 然后再执行:yum install vs ...
- 错误码:2003 不能连接到 MySQL 服务器在 (10061)
今天在ubuntu上安装了mysql服务器,在windows上用客户端软件连接mysql服务器时,出现错误: 错误码: 不能连接到 MySQL 服务器在 () 折腾来折腾去没搞好,防火墙也关了,330 ...
- hello-jni Android.mk文件简析
#删除旧变量 LOCAL_PATH := $(call my-dir) #返回当前目录 include $(CLEAR_VARS) #删除旧变量 #设置新变量 LOCAL_MODULE := hell ...
- JVM之G1收集器
Garbage-First,面向服务端的垃圾收集器. 并行与并发:充分利用多核环境减少停顿时间, 分代收集:不需要配合其它收集器 空间整合:整体上看属于标记整理算法,局部(region之间)数据复制算 ...
- 【label】标签组件说明
label标签组件 用来改进表单组件的可用性,使用for属性找到对应的id,或者将控件放在该标签下,当点击时,就会触发对应的控件.目前可以绑定的控件有:<button/>, <che ...
- HDU - 6441(费马大定理)
链接:HDU - 6441 题意:已知 n,a,求 b,c 使 a^n + b^n = c^n 成立. 题解:费马大定理 1.a^n + b^n = c^n,当 n > 2 时无解: 2. 当 ...
- CSP201609-1:最大波动
引言:CSP(http://www.cspro.org/lead/application/ccf/login.jsp)是由中国计算机学会(CCF)发起的"计算机职业资格认证"考试, ...
- Map Reduce Application(Join)
We are going to explain how join works in MR , we will focus on reduce side join and map side join. ...