优先级队列的实现

优先级队列是基于最大堆或者最小堆的,有很多的应用,比如任务调度,事件模拟之类的,下面我们来实现最大优先级队列(基于最大堆)和最小优先级队列(基于最小堆)。


最大优先级队列代码如下。在实际使用中,一般可以只保存一个用于比较的key和一个指向实际数据的指针在优先级队列中,下面的代码忽略了实际的数据,只考虑Key。

#ifndef _LARGESTPRIORITYQUEUE_
#define _LARGESTPRIORITYQUEUE_

#include 
#include 
using namespace std;

template 
class LargestPriorityQueue
{
public:
	LargestPriorityQueue(): _size(0)
	{
		_values = new T[MaxCount];
	}
	~LargestPriorityQueue() { delete [] _values; }
	LargestPriorityQueue(const LargestPriorityQueue& rhs): _size(0),_values(NULL) { operator=(rhs); }
	const LargestPriorityQueue& operator= ( const LargestPriorityQueue& rhs)
	{
		if( this != &rhs )
		{
			delete [] _values;
			_values = new T[MaxCount];
			_size = rhs._size;

			for(int i=0;i<_size;++i)
				_values[i] = rhs._values[i];
		}

		return *this;
	}

	bool IsEmpty() const { return _size == 0; }
	bool Size() const { return _size; }
	bool IsFull() const { return _size == MaxCount; }

	void Insert(const T& value)
	{
		if(IsFull())
			 throw logic_error("Queue is full");

		_values[_size++] = value;

		int index = _size - 1;
		int parent = (index - 1) / 2;
		while( index > 0 && _values[parent] < _values[index] )
		{
			Swap(parent,index);
			index = parent;
			parent = (index - 1) / 2;
		}
	}

	T GetLargest()
	{
		if(IsEmpty())
			throw logic_error("No element in queue");

		return _values[0];
	}

	T RemoveLargest()
	{
		if(IsEmpty())
			throw logic_error("No element in queue");

		T value = _values[0];

		Swap(0,_size-1);
		--_size;
		MaxHeapify(0,_size-1);
		return value;
	}

	void IncreaseKey(int index, const T& newValue)
	{
		if( index < 0 || index >= _size )
			throw logic_error("Invalid element index");

		if(_values[index] > newValue )
			throw logic_error("New value is less than the old value");

		_values[index] = newValue;

		int parent = (index - 1) / 2;
		while( index > 0 && _values[parent] < _values[index] )
		{
			Swap(parent,index);
			index = parent;
			parent = (index - 1) / 2;
		}
	}

	void Print() const
	{
		cout << "Size=" << _size << endl;
		for(int i=0;i<_size;++i)
		{
			cout << _values[i] << ",";
		}
		cout << endl;
	}

private:
	T* _values;
	int _size;

	void MaxHeapify(int low, int high)
	{
		if(low < high)
		{
			int large = low*2+1;
			while( large <= high )
			{
				if( large < high && _values[large] < _values[large + 1])
					++large;

				if( _values[low] < _values[large] )
				{
					Swap(low,large);
					low = large;
					large = 2*low+1;
				}
				else
				{
					break;
				}
			}
		}
	}

	void Swap(int source, int target)
	{
		if( source != target )
		{
			T temp = _values[target];
			_values[target] = _values[source];
			_values[source] = temp;
		}
	}

};
#endif



最大优先级队列测试代码:

void LargestPriorityQueueTest1()
{
	LargestPriorityQueue lpq;
	lpq.Print();

	lpq.Insert(10);
	lpq.Insert(7);
	lpq.Insert(15);
	lpq.Print();

	lpq.Insert(2);
	lpq.Print();
	lpq.IncreaseKey(3,13);
	lpq.Print();

	lpq.IncreaseKey(3,18);
	lpq.Print();
	cout << lpq.GetLargest() << endl;
	cout << lpq.RemoveLargest() << endl;
	lpq.Print();
}

相对应的,最小优先级队列的代码如下:

#ifndef _SMALLESTPRIORITYQUEUE_
#define _SMALLESTPRIORITYQUEUE_

#include 
#include 
using namespace std;

template 
class SmallestPriorityQueue
{
public:
	SmallestPriorityQueue(): _size(0) { _values = new T[MaxCount]; }
	~SmallestPriorityQueue() { delete [] _values; }
	SmallestPriorityQueue( const SmallestPriorityQueue& rhs) : _size(0),_values(NULL) { operator=(rhs); }
	const SmallestPriorityQueue& operator= ( const SmallestPriorityQueue& rhs)
	{
		if( this != &rhs )
		{
			delete [] _values;
			_values = new T[MaxCount];
			_size = rhs._size;

			for(int i=0;i<_size;++i)
				_values[i] = rhs._values[i];
		}

		return *this;
	}

	bool IsEmpty() const { return _size == 0; }
	bool IsFull() const { return _size == MaxCount; }
	int Size() const { return _size; }

	void Insert(const T& value)
	{
		if(IsFull())
			throw logic_error("Queue is full");

		_values[_size++] = value;
		int index = _size-1;
		int parent = (index-1) /2;

		while( index>0 && _values[index] < _values[parent] )
		{
			Swap(index,parent);
			index = parent;
			parent = (index-1) /2;
		}
	}

	T GetSmallest()
	{
		if(IsEmpty())
			throw logic_error("No element in the queue");

		return _values[0];
	}

	T RemoveSmallest()
	{
		if(IsEmpty())
			throw logic_error("No element in the queue");

		T value = _values[0];
		Swap(0,_size-1);
		--_size;
		MinHeapify(0,_size-1);
		return value;
	}

	void DecreaseKey(int index, const T& newValue)
	{
		if( index < 0 || index >= _size )
			throw logic_error("Invalid index value");

		if( _values[index] < newValue )
			throw logic_error("New value is greater than the old value");

		_values[index] = newValue;
		int parent = (index - 1) / 2;

		while( index>0 && _values[index] < _values[parent] )
		{
			Swap(index,parent);
			index = parent;
			parent = (index-1) /2;
		}
	}

	void Print() const
	{
		cout << "Size=" << _size << endl;
		for(int i=0;i<_size;++i)
		{
			cout << _values[i] << ",";
		}
		cout << endl;
	}
private :

	void MinHeapify(int low, int high)
	{
		if(low < high)
		{
			int small = low*2+1;
			while( small <= high )
			{
				if( small < high && _values[small] > _values[small + 1])
					++small;

				if( _values[low] > _values[small] )
				{
					Swap(low,small);
					low = small;
					small = 2*low+1;
				}
				else
				{
					break;
				}
			}
		}
	}

	void Swap(int source, int target)
	{
		if( source != target )
		{
			T temp = _values[target];
			_values[target] = _values[source];
			_values[source] = temp;
		}
	}

	T* _values;
	int _size;
};

#endif



测试代码如下:

void SmallestPriorityQueueTest1()
{
	SmallestPriorityQueue spq;
	spq.Print();

	spq.Insert(12);
	spq.Insert(9);
	spq.Insert(10);
	spq.Print();

	spq.Insert(4);
	spq.Print();

	spq.DecreaseKey(3,2);
	spq.Print();

	spq.Insert(7);
	spq.Print();

	cout << spq.GetSmallest() << endl;
	cout << spq.RemoveSmallest() << endl;
	spq.Print();

	while( spq.Size() > 0)
	{
		cout << spq.RemoveSmallest() << endl;
	}
	spq.Print();
}



你可能感兴趣的:(C++,面试题目)