堆二叉樹

堆(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;
};


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