堆的物理实现(大根堆+小根堆)

  • 说明
  • 基于顺序表实现的堆

一、说明

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
using namespace std;
#ifndef _Comp_max
#define _Comp_max
namespace wangzhe
{
	template
	class Comp_max
	{
		public:
			static bool prior(E a, E b)//注意要是静态函数 
			{
				return a>=b;
			}
	};
}
#endif 

2、Comp_min.h(调用该类实现最小堆)

#include
using namespace std;
#ifndef _Comp_min
#define _Comp_min
namespace wangzhe
{
	template
	class Comp_min
	{
		public:
			static bool prior(E a, E b)//注意要是静态函数 
			{
				return a<=b;
			}
	};
}
#endif 

3、heap.h

#include
using namespace std;
#include"Comp_max.h"
#ifndef _heap
#define _heap
namespace wangzhe
{
	template
	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

4、heap.cpp

#include
#include 
using namespace std;
#include"heap.h"
namespace wangzhe
{
	
	template
	heap::heap(E* h,int num,int max)
	{
		Heap=h,n=num,maxsize=max;
		buildHeap(); 
	}
	
	template
	int heap::size() const
	{
		return n;
	}
	
	template
	bool heap::isEmpty() 
	{
		return n==0;
	}
	
	template
	bool heap::isLeaf(int pos) const
	{
		return (pos>=n/2)&&(pos
	int heap::lc(int pos) const
	{
		return 2*pos+1;
	}
	
	template
	int heap::rc(int pos) const
	{
		return 2*pos+2;
	}
	
	template
	int heap::parent(int pos) const
	{
		return (pos-1)/2;
	}
	
	template
	void heap::buildHeap()
	{
	    for(int i=n/2-1;i>=0;i--)
			sift_down(i);	
	} 
	
	template
	E heap::top()
	{
		if(n<=0)
		{
			cout<<"Heap is empty\n";
			exit(-1);
		}
		return Heap[0];
	} 
	
	template
	void heap::insert(const E& it)
	{
		if(n>=maxsize)
		{
			cout<<"Heap is full\n";
			return;
		}
		Heap[n++]=it;
		sift_up(n-1);
 	}
 	
 	template
 	E heap::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
	E heap::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 
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>a[i];
	
	heap< int,Comp_max > hp(a,n,10010);
	while(!hp.isEmpty())
	cout<

 

运行结果

堆的物理实现(大根堆+小根堆)_第1张图片

你可能感兴趣的:(∨∨坑逼数据结构课)