- 说明
- 基于顺序表实现的堆
一、说明
1、堆是一颗完全二叉树,因此能用一维数组来存储堆,但堆本质上是一种实现了“局部有序”的树结构。
2、最大堆:任何一个结点存储的值都大于或等于任意一个子结点存储的值。根结点存储着最大值。
最小堆:任何一个结点存储的值都小于或等于任意一个子结点存储的值。根结点存储着最小值。
3、本文中存储堆的数组下标从0开始。则下标为i的左孩子结点为lc=2*i+1,右孩子结点为rc=2*i+2,双亲结点为parent=(i-1)/2。
4、插入一个新元素it时,只需将堆的大小加1,把it放在堆的末端,然后对it进行sift_up(上移)操作。所需时间Θ(log n)。
5、删除第i项元素时,用堆中最后一个元素来取代Heap[i],然后根据被删除元素和取代它的元素的优先级,来确定对取代它的元素是做sift_up(上移)还是sift_down(下移)操作。所需时间Θ(log n)。
6、删除堆顶时,用堆中最后一个元素来取代堆顶元素,将堆的大小减1,然后对it进行sift_down(下移)操作。所需时间Θ(log n)。
7、堆的建立有两种方法:①对于一个空堆,用insert操作来建堆,插入n个元素,所需的执行时间是Θ(n log n);②直接在数组中调整,单结点的二叉树是堆,在完全二叉树中所有以叶子结点(序号i>=n/2)为根的子树是堆,这样,只需要依次将以序号为n/2-1,n/2-2,...,0的结点为根的子树调整为堆即可,所需的执行时间为Θ(n)。
8、下述堆的实现有两个模板参数,第一个E是堆中的数据类型,第二个Comp是比较优先级的。若要实现某种堆则调用相对应的Comp类。
二、基于顺序表实现的堆
1、Comp_max.h(调用该类实现最大堆)
#include<iostream>
using namespace std;
#ifndef _Comp_max
#define _Comp_max
namespace wangzhe
{
template<typename E>
class Comp_max
{
public:
static bool prior(E a, E b)//注意要是静态函数
{
return a>=b;
}
};
}
#endif
2、Comp_min.h(调用该类实现最小堆)
#include<iostream>
using namespace std;
#ifndef _Comp_min
#define _Comp_min
namespace wangzhe
{
template<typename E>
class Comp_min
{
public:
static bool prior(E a, E b)//注意要是静态函数
{
return a<=b;
}
};
}
#endif
3、heap.h
#include<iostream>
using namespace std;
#include"Comp_max.h"
#ifndef _heap
#define _heap
namespace wangzhe
{
template<typename E,typename Comp>
class heap
{
private:
E* Heap; //堆
int maxsize;//最大结点数
int n;//当前结点数
void sift_down(int pos)//向下调整
{
while(!isLeaf(pos))
{
int j=lc(pos),r=rc(pos);
if(r<n&&(Comp::prior(Heap[r],Heap[j]))) j=r;
if(Comp::prior(Heap[pos],Heap[j])) return;
swap(Heap[pos],Heap[j]);
pos=j;
}
}
void sift_up(int pos)//向上调整
{
while(pos)
{
int j=parent(pos);
if(Comp::prior(Heap[j],Heap[pos])) return;
swap(Heap[pos],Heap[j]);
pos=j;
}
}
public:
heap(E* h,int num,int max);//构造函数
int size() const;//当前堆的大小
bool isEmpty();//判断当前堆是否为空
bool isLeaf(int pos) const;//判断是否是叶结点
int lc(int pos) const;//左孩子
int rc(int pos) const;//右孩子
int parent(int pos) const;//双亲
void buildHeap();//建堆
E top();//返回堆顶
void insert(const E& it);//添加一个结点
E removefirst();//删除堆顶
E remove(int pos);//删除第pos个结点
};
}
#endif
4、heap.cpp
#include<iostream>
#include<algorithm>
using namespace std;
#include"heap.h"
namespace wangzhe
{
template<typename E,typename Comp>
heap<E,Comp>::heap(E* h,int num,int max)
{
Heap=h,n=num,maxsize=max;
buildHeap();
}
template<typename E,typename Comp>
int heap<E,Comp>::size() const
{
return n;
}
template<typename E,typename Comp>
bool heap<E,Comp>::isEmpty()
{
return n==0;
}
template<typename E,typename Comp>
bool heap<E,Comp>::isLeaf(int pos) const
{
return (pos>=n/2)&&(pos<n);
}
template<typename E,typename Comp>
int heap<E,Comp>::lc(int pos) const
{
return 2*pos+1;
}
template<typename E,typename Comp>
int heap<E,Comp>::rc(int pos) const
{
return 2*pos+2;
}
template<typename E,typename Comp>
int heap<E,Comp>::parent(int pos) const
{
return (pos-1)/2;
}
template<typename E,typename Comp>
void heap<E,Comp>::buildHeap()
{
for(int i=n/2-1;i>=0;i--)
sift_down(i);
}
template<typename E,typename Comp>
E heap<E,Comp>::top()
{
if(n<=0)
{
cout<<"Heap is empty\n";
exit(-1);
}
return Heap[0];
}
template<typename E,typename Comp>
void heap<E,Comp>::insert(const E& it)
{
if(n>=maxsize)
{
cout<<"Heap is full\n";
return;
}
Heap[n++]=it;
sift_up(n-1);
}
template<typename E,typename Comp>
E heap<E,Comp>::removefirst()
{
if(n<=0)
{
//cout<<"Heap is empty\n";
exit(-1);
}
swap(Heap[0],Heap[--n]);
if(n!=0) sift_down(0);
return Heap[n];//返回被删掉的元素,原先是Heap[0]
}
template<typename E,typename Comp>
E heap<E,Comp>::remove(int pos)
{
if(pos<0||pos>=n)
{
cout<<"Bad position\n";
exit(-1);
}
if(pos==n-1) n--;
else
{
int x=Heap[pos],y=Heap[--n];
swap(Heap[pos],Heap[n]);
if(Comp::prior(x,y)) sift_down(pos);
else sift_up(pos);
}
return Heap[n];
}
}
5、main.cpp
#include <iostream>
using namespace std;
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
#include"Comp_max.h"
#include"heap.h"
#include"heap.cpp"
using namespace wangzhe;
int main(int argc, char** argv)
{
int n,a[10010];
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
heap< int,Comp_max<int> > hp(a,n,10010);
while(!hp.isEmpty())
cout<<hp.removefirst()<<endl;
cout<<endl;
hp.insert(100);
hp.insert(1999);
cout<<hp.top()<<endl;
cout<<"size:"<<hp.size()<<endl;
hp.remove(0);
cout<<hp.top()<<endl;
}
运行结果