大小堆的实现与实现优先级队列

堆:可视为一棵完全二叉树结构,最小堆每个父节点都小于孩子结点,最大堆每个父节点都大于孩子结点。

建堆思想:实现向下调整算法AdjustDown():即当一个节点的左子树和右子树都已为最大堆或最小堆(在这里则寻找树倒着走的第一个非叶子结点,依次进行调整),比较其左右孩子结点满足大堆或小堆要求的节点,再与此节点比较,若孩子结点大,满足大堆交换两节点值,或小堆,孩子结点小则交换。大堆与小堆思想基本相同,所以实现用仿函数进行实现。

建堆完成后可在堆中实现在尾部插入和删除头节点等操作,从中又实现一个向上调整算法AdjustUp(),其类似于向下调整算法.

优先级队列:则在大堆与小堆基础上实现队列的优先级等系列操作。

代码实现:

#include <iostream>
#include <cstdlib>
#include <vector>
#include <assert.h>
using namespace std;

template <class T> //仿函数
struct Less
{
	bool operator()(const T& l1,const T& l2)
	{
		return l1<l2;
	}
};

template <class T>
struct Greater
{
	bool operator()(const T& l1,const T& l2)
	{
		return l1>l2;
	}
};

template <class T,class Compare=Greater<T>>
class Heap
{
public:
	Heap()
	{}
	Heap(T* a,size_t n)
		:_a(a,a+n)
	{
		for(int i=(n-2)/2;i>=0;--i) //先找到树的第一个非叶子结点
		{
			_AdjustDown(i);   //向下调整
		}
	}

	void Push(const T& x)
	{
		_a.push_back(x);
		_AdjustUp(_a.size()-1);    //向上调整
	}

	void Pop()
	{
		assert(_a.size());
		swap(_a[0],_a[_a.size()-1]);
		_a.pop_back();
		_AdjustDown(0);    //向下调整
	}

	const T& Top()
	{
		assert(_a.size());
		return _a[0];
	}

	size_t Size()
	{
		return _a.size();
	}

	bool Empty()
	{
		return _a.empty();
	}
protected:
	void _AdjustDown(size_t root)  //向下调整
	{
		Compare compare;
		size_t parent=root;
		size_t child=parent*2+1;
		while(child<_a.size())  //当parent不为叶子结点
		{
			if(child+1<_a.size()&&compare(_a[child+1],_a[child]))//比较左右孩子符合条件的
				++child;
			if(compare(_a[child],_a[parent]))  //比较孩子和父节点
			{
				swap(_a[parent],_a[child]);
				parent=child;
				child=parent*2+1;
			}
			else
				break;
		}
	}

	void _AdjustUp(size_t child)   //向上调整
	{
		Compare compare;
		size_t parent=(child-1)/2;
		while(child>0)
		{
			if(compare(_a[child],_a[parent]))   //比较孩子和父节点
			{
				swap(_a[parent],_a[child]);
				child=parent;
				parent=(child-1)/2;
			}
			else
				break;
		}
	}
protected:
	vector<T> _a;
};

template <class T,class Compare=Greater<T>>
class PriorityQueue     //优先级队列
{
public:
	void Push(const T& x)
	{
		_hp1.Push(x);
	}
	void Pop()
	{
		_hp1.Pop();
	}
	const T& Top()
	{
		return _hp1.Top();
	}
	size_t Size()
	{
		return _hp1.Size();
	}
	bool Empty()
	{
		return _hp1.Empty();
	}
protected:
	Heap<T,Compare> _hp1;   //用堆实现
};

void TestHeap()
{
	//最大堆
	int a1[]={10,11,13,12,16,18,15,17,14,19};
	Heap<int> hp1(a1,sizeof(a1)/sizeof(a1[0]));
	hp1.Push(20);
	hp1.Pop();

	//最小堆
	int a2[]={19,17,18,14,16,13,15,12,10,11};
	Heap<int,Less<int>> hp2(a2,sizeof(a2)/sizeof(a2[0]));
	hp2.Push(9);
	hp2.Pop();
}

void TestPriorityQueue()
{
	PriorityQueue<int> que; 
	que.Push(10);
	que.Push(11);
	que.Push(13);
	que.Push(12);
	que.Push(16);
	que.Push(18);
	que.Push(15);
	que.Push(17);
	if(!que.Empty())
	{
		cout<<que.Size()<<endl;
		cout<<que.Top()<<endl;
	}
	que.Pop();
}

int main()
{
	TestHeap();
	TestPriorityQueue();
	system("pause");
	return 0;
}




你可能感兴趣的:(大小堆的实现与实现优先级队列)