重写优先队列(priority_queue)

STL里面的优先队列没有查找功能,但是在写A*算法时必须要对优先队列进行数据查找,那么就只能自己实现了。相比于STL库里的优先队列,增加了查找功能。

参考文章:http://blog.csdn.net/morewindows/article/details/6709644

#ifndef PRIORITY_QUEUE_X_H
#define PRIORITY_QUEUE_X_H
#include <vector>
using namespace std;
/*
*	1, 创建最小堆,二叉堆是完全二叉树。数据的存储结构可以用数组
	2, 堆得数据插入操作:每次插入都是将新数据放在数组最后,通过调用函数HeapAdjustUp实现
	3, 堆的数据删除操作:每次只能删除第0个数据,把最后一个数据值赋给根节点,然后从根节点开始一次自上而下的调整,借助函数HeapAdjustDown。
	4, 对于节点i,它的左孩子是 2*i+1,右孩子是 2*i+2。第一个节点在数组的下标0处
*/
template<class T>
class Priority_Queue
{
public:
	Priority_Queue(int size=20):t_size(0)
	{
		var.resize(size);
	}
	T& top();
	void pop();
	void pop(T & tar);
	void push(T & dat);
	bool find(T & dst);
	bool empty() const;
	void make_queue_sorted(vector<T>&dst);
private:
	void BuildHeap();
	void HeapAdjustUp(int i);
	void HeapAdjustDown(int i);
private:
	unsigned int t_size;
	vector<T> var;
};

template<class T>
void _swap(T &a, T& b)
{
	T temp;
	temp = a;
	a = b;
	b = temp;
}

template<class T>
T& Priority_Queue<T>::top() 
{
	Node tmp(INT_MAX, INT_MAX);

	if(!empty())
		return var[0];
	else
	{
		return tmp;
	}
}

template<class T>
bool Priority_Queue<T>::empty() const
{
	return t_size == 0;
}

template<class T>
bool Priority_Queue<T>::find(T & dst)
{
	unsigned int i;
	for(i=0; i<t_size; i++)
	{
		if(dst == var[i])
			return 1;
	}
	return 0;
}

template<class T>
void Priority_Queue<T>::HeapAdjustDown(int i)
{
	unsigned int j;
	T temp = var[i];
	j = 2*i+1;	//左孩子
	while(j<t_size)
	{
		if(j+1 < t_size && var[j+1] < var[j]) //在左右孩子中找最小的
			j++;

		if(var[j] >= temp)
			break;

		var[i] = var[j];
		i = j;
		j = 2*i + 1;
	}
	var[i] = temp; 
}

template<class T>
void Priority_Queue<T>::pop()
{
	if(t_size>0)
	{
		_swap(var[0], var[t_size-1]);
		t_size--;
		HeapAdjustDown(0);
	}
}

template<class T>
void Priority_Queue<T>::pop(T & tar)
{
	unsigned int i;
	for(i=0; i<t_size; i++)
	{
		if(tar == var[i])
		{
			_swap(var[i], var[t_size-1]);
			t_size--;
			HeapAdjustDown(i);
			break;
		}
	}
}

template<class T>
void Priority_Queue<T>::HeapAdjustUp(int i)
{//对于一个二叉堆,父节点肯定大于它的子节点,所以在插入时只需关注和父节点的关系
	int j=(i-1)/2;//父节点下标
	T temp = var[i];
	while((i-1)>=0 && var[j]>temp)//类似于插入排序,使用(i-1)判断是因为 当i=0时(i-1)/2恒为0
	{
		var[i] = var[j];	//父节点大于子节点,,父节点下移 
		i=j;
		j=(i-1)/2;
	}
	var[i] = temp;
}

template<class T>
void Priority_Queue<T>::push(T & dat)
{
	if(t_size+1 > var.size())
		var.resize(2*t_size + 1);
	var[t_size] = dat;
	t_size++;
	HeapAdjustUp(t_size-1);
}

template<class T>
void Priority_Queue<T>::make_queue_sorted(vector<T>&dst)
{
	unsigned int size, i;
	
	//临时保存数据
	size = t_size;
	vector<T> tmpvec;
	tmpvec.resize(var.size());
	memcpy(tmpvec.data(), var.data(), var.size()*sizeof(T));

	//排序
	for(i=0; i<size; i++)
	{
		_swap(var[0], var[size-1-i]);
		t_size--;
		HeapAdjustDown(0);
	}

	//对参数赋值
	dst.resize(size);
	memcpy(dst.data(), var.data(), size*sizeof(T));

	//复原数组
	t_size = size;
	memcpy(var.data(), tmpvec.data(), var.size()*sizeof(T));
}
#endif




你可能感兴趣的:(优先队列)