[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++有钱途吗? 这 ...
随机推荐
- Wake-Sleep(W-S)算法【转载】
原文: https://www.zhihu.com/question/29648549 https://blog.csdn.net/zouxy09/article/details/8775518 en ...
- C语言实验报告(五) 两个正整数的最大公约数
编程实现求两个正整数的最大公约数,要求计算最大公约数用函数fun(int a,int b)实现. #include<stdio.h>void main(){ int n,a,b; in ...
- go基础语法-指针
1.基础定义 golang的指针没有cpp等语言的指针复杂,具体表现在其不可用于运算.只有值传递 语法:var variableName *int = memoryAddr var a = 2 var ...
- vuejs中的生命周期
vue中生命周期分为初始化,跟新状态,销毁三个阶段 1.初始化阶段:beforeCreated,created,beforeMount,mounted 2.跟新状态:beforeUpdate,upda ...
- 创龙DSP6748开发板LED闪烁-第一篇
1. 首先看下DSP6748的GPIO寄存器的文档,先看下框图,有这个框图,一目了然,输入和输出很清楚 2. 看下寄存器部分,对应上面的图,问题在于,DSP6748有多少个GPIO?最多144个,下一 ...
- pg 与 oracle 比较
所谓动态引擎,就是说比如有很多张表的Join,原始的做法是一开始就生成好这个执行计划,随后执行,但实际上很多表Join的时候,你一开始生成的那个执行计划很有可能是不对的. 那么动态执行计划就是指它可以 ...
- centos7下安装mysql8.0.12及设置权限
一.mysql版本介绍 mysql的官网为:https://www.mysql.com/ 在官网上可以看到多个版本,主要版本如下, 1.MySQL Community Server 社区版本,开源免费 ...
- 「日常训练」Divisibility by Eight(Codeforces Round 306 Div.2 C)
题意与分析 极简单的数论+思维题. 代码 #include <bits/stdc++.h> #define MP make_pair #define PB emplace_back #de ...
- hdu1527取石子游戏(威佐夫博弈)
取石子游戏 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submi ...
- Python字符串所有操作函数
name = "my \tname is {name} and i am {year} old" print(name.capitalize())#首字母大写 print(name ...