堆二叉树

堆(heap)又被为优先队列(priority queue)。尽管名为优先队列,但堆并不是队列。回忆一下,在队列中,我们可以进行的限定操作是dequeue和enqueue。dequeue是按照进入队列的先后顺序来取出元素。而在堆中,我们不是按照元素进入队列的先后顺序取出元素的,而是按照元素的优先级取出元素。


堆的一个经典的实现是完全二叉树(complete binary tree)。这样实现的堆成为二叉堆(binary heap)

完全二叉树是增加了限定条件的二叉树。假设一个二叉树的深度为n。为了满足完全二叉树的要求,该二叉树的前n-1层必须填满,第n层也必须按照从左到右的顺序被填满,比如下图:

为了实现堆的操作,我们额外增加一个要求: 任意节点的优先级不小于它的子节点。如果在上图中,设定小的元素值享有高的优先级,那么上图就符合该要求。

已经在排序算法简介及其C++实现中实际使用了堆。堆的主要操作是插入删除最小元素和排序(元素值本身为优先级键值,小元素享有高优先级)。在插入或者删除排序操作之后,我们必须保持该实现应有的性质: 1. 完全二叉树 2. 每个节点值都小于或等于它的子节点。

 

 

我们插入节点2:

插入

 

 

删除根节点1。如图:

删除根节点

 

 

#pragma once 
#include<iostream>
using namespace std;
template <class Type>
class MaxHeap
{
	public:
		MaxHeap(int sz=DefaultSize)
		{
			MaxHeapSize=sz>DefaultSize? sz:DefaultSize;
            heap=new Type[MaxHeapSize];
			memset(heap,0,sizeof(Type)*MaxHeapSize);
			CurHeapSize=0;
		}
		MaxHeap(int *a,int n )
		{
			MaxHeapSize=n>DefaultSize? n:DefaultSize;
            heap=new Type[MaxHeapSize];
			memset(heap,0,sizeof(Type)*MaxHeapSize);
			CurHeapSize=n;
			for(int i=0;i<n;++i)
			{
				heap[i]=a[i];
			}
            CreateHeapTree(a,n); 	
		}
		void CreateHeapTree(int *a,int n)
		{
			
		/*	int pos=n/2-1;
		while(pos>=0)
		{
		SiftDown(pos,n);
		pos--;
		}
			*/
			int pos=0;
			while(pos<=n/2-1)
			{
				SiftUp(pos,n); 
				pos++;
			}
		}
		void Show()const
		{
			for(int i=0; i<CurHeapSize; ++i)
			{
				cout<<heap[i]<<" ";
			}
			cout<<endl;
		}
		void RemoveMax()
		{
			RemoveMax(CurHeapSize-1);
		}
		
		bool Insert(const Type &x)
		{ 	
			heap[CurHeapSize ]=x;
			CurHeapSize++;
			CreateHeapTree(heap ,CurHeapSize );
			return true;
		}
		void Sort()
		{
			int 	n=CurHeapSize;
			int i=1;
			while(i<n)
			{
				if(heap[i]<heap[i+1])
				{
					swap(heap[i],heap[i+1]);
					i--;
				}
				else
					i++;
			}	
		}
	protected:
		Type RemoveMax(int n)
		{
			heap[0]=heap[n];
			heap[n]=0;
			n--;
            CreateHeapTree(heap ,n);
			CurHeapSize--;
			
			return 0;
		}
		void SiftDown(int pos,int n ) 
		{
			int i=pos,j=2*i+1;
			while(j<=n)
			{ 
				if(j+1<=n && heap[j]<heap[j+1])
				{
					j++;
				}
				
				if(heap[i] < heap[j])
				{
					Type tmp = heap[i];
					heap[i] = heap[j];
					heap[j] = tmp;
				}
				i = j;
				j = 2*i+1;
			}
		}
		void SiftUp(int pos,int n)
		{
			int i=pos,j=2*i+1;
			while(j>0)
			{
				if(j+1<=n && heap[j]<heap[j+1])
				{
					j++;
				}
				if(heap[i]<heap[j])
				{
					//heap[i]=heap[i]^heap[j];
				//	heap[j]=heap[i]^heap[j];
				//	heap[i]=heap[i]^heap[j];
					swap(heap[i],heap[j]);
				}
				j=i;
				i=(i-1)/2; 	 
			}
			
		}
	private:
		enum{DefaultSize=10};
		Type *heap;
		int MaxHeapSize;
		int CurHeapSize;
};


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章