diff engine/core/util/structures/priorityqueue.h @ 0:4a0efb7baf70

* Datasets becomes the new trunk and retires after that :-)
author mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222
date Sun, 29 Jun 2008 18:44:17 +0000
parents
children 90005975cdbb
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/engine/core/util/structures/priorityqueue.h	Sun Jun 29 18:44:17 2008 +0000
@@ -0,0 +1,326 @@
+/***************************************************************************
+ *   Copyright (C) 2005-2008 by the FIFE team                              *
+ *   http://www.fifengine.de                                               *
+ *   This file is part of FIFE.                                            *
+ *                                                                         *
+ *   FIFE is free software; you can redistribute it and/or modify          *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA              *
+ ***************************************************************************/
+
+#ifndef FIFE_SOLVER_INDEXEDPQ_H
+#define FIFE_SOLVER_INDEXEDPQ_H
+
+#include <cassert>
+#include <list>
+
+namespace FIFE {
+
+	/** A pq which stores index-value pairs for elements.
+	 *
+	 * This acts as a normal PQ but stores some extra information about the
+	 * elements that it's storing, namely a special unique index. 
+	 */
+	template<typename index_type, typename priority_type>
+	class PriorityQueue {
+	public:
+		/** Used for element ordering.
+		 *
+		 */
+		enum Ordering {
+			Ascending, //!< lowest priority first.
+			Descending //!< highest priority first.
+		};
+		
+		typedef std::pair<index_type, priority_type> value_type;
+		
+		/** Constructor
+		 *
+		 */
+		PriorityQueue(void) : m_ordering(Ascending) {
+		}
+
+		/** Constructor
+		 *
+		 * @param ordering The ordering the priority queue should use.
+		 */
+		PriorityQueue(const Ordering ordering) : m_ordering(ordering) {
+		}
+
+		/** Pushes a new element onto the queue.
+		 * 
+		 * The element is pushed onto the queue and then moved up the queue until it's 
+		 * in the correct position by priority.
+		 *
+		 * @param element Of type value_type which contains both the index and the priority of the element.
+		 */
+		void pushElement(const value_type& element);
+		
+		/** Pops the element with the highest priority from the queue.
+		 *
+		 * Removes and deletes the highest priority element.
+		 */
+		void popElement(void);
+
+		/** Changes the priority of an element.
+		 *
+		 * Locates the element with the given index and changes it's priority to the given
+		 * priority, it then re-orders the priority queue to take account of this new information.
+		 *
+		 * @param index The index of the element to change the priority of.
+		 * @param newPriority The new priority of the element.
+		 * @return True if the element could be found, false otherwise.
+		 */
+		bool changeElementPriority(const index_type& index, const priority_type& newPriority);
+
+		/** Removes all elements from the priority queue.
+		 *
+		 */
+		void clear(void);
+		
+		/** Retrieves the element with the highest priority.
+		 *
+		 * This function will generate an assertion error if the pq is 
+		 * empty.
+		 *
+		 * @return A const reference to the highest priority element.
+		 */
+		const value_type getPriorityElement(void) const {
+				
+			assert(!empty());
+
+			return m_elements.front();
+
+		}
+
+		/** Determines whether the queue is currently empty.
+		 *
+		 * @return true if it is empty, false otherwise.
+		 */
+		bool empty(void) const {
+			return m_elements.empty();
+		}
+
+		/** Returns the current size of the queue.
+		 *
+		 */
+		size_t size(void) const {
+			return m_elements.size();
+		}
+	private:
+		typedef std::list<value_type> ElementList;
+		typedef typename ElementList::iterator ElementListIt;
+		typedef typename ElementList::const_iterator ElementListConstIt;
+
+		//A list of valuetype pairs that represents the pq. 
+		ElementList m_elements;
+
+		//The order to use when sorting the pq.
+		Ordering    m_ordering;
+
+		/** Orders a PQ element up the list.
+		 *
+		 * @param i An iterator representing the element in the list to be sorted up.
+		 */
+		void orderUp(ElementListIt i);
+		/** Orders a PQ element up the list.
+		 *
+		 * @param entry A const reference to a value_type which represents the element to be added to the
+		 * pq. 
+		 */
+		void orderUp(const value_type& entry);
+
+		/** Orders a PQ element down the list.
+		 *
+		 * @param An iterator representing the element in the PQ to order down.
+		 */
+		void orderDown(ElementListIt i);
+
+		/** Retrieves the iterator to the element with the given index.
+		 * 
+		 * @param index A const reference to the index to find.
+		 */
+		ElementListIt getElementIterator(const index_type& index) { 
+
+			for(ElementListIt i = m_elements.begin(); i != m_elements.end(); ++i) {
+				if(i->first == index) {
+					return i;
+				}
+			}
+
+			return m_elements.end();
+
+		}
+	
+		/** The comparison function, used to compare two elements.
+		 *
+		 * @param a The l-operand of the comparison operation.
+		 * @param b The r-operand of the comparison operation.
+		 * @return An integer representing the result of the comparison operation. 1 being a is greather than b,
+		 *		   -1 being a is less than b and 0 meaning that they're equal.
+		 */
+		int compare(const value_type& a, const value_type& b);
+	};
+}
+
+template<typename index_type, typename priority_type>
+void FIFE::PriorityQueue<index_type, priority_type>::pushElement(const value_type& element) {
+	if(empty()) {
+		m_elements.push_front(element);
+	}
+	else {
+		orderUp(element);
+	}
+}
+
+template<typename index_type, typename priority_type>
+void FIFE::PriorityQueue<index_type, priority_type>::popElement(void) {
+	
+	if(!empty()) {
+		m_elements.pop_front();
+	}
+
+}
+
+template<typename index_type, typename priority_type>
+bool FIFE::PriorityQueue<index_type, priority_type>::changeElementPriority(const index_type& index, const priority_type& newPriority) {
+	
+	ElementListIt i = getElementIterator(index);
+
+	if(i == m_elements.end()) {
+		return false;
+	}
+
+	int compare_res = compare(value_type(index, newPriority), (*i));
+
+	i->second = newPriority;
+
+	if(compare_res > 0 &&  i != m_elements.begin()) {
+		orderDown(i);
+	} else if(compare_res < 0) {
+		orderUp(i);
+	}
+
+	return true;
+
+}
+
+template<typename index_type, typename priority_type>
+void FIFE::PriorityQueue<index_type, priority_type>::clear(void) {
+
+	m_elements.clear();
+
+}
+
+template<typename index_type, typename priority_type>
+void FIFE::PriorityQueue<index_type, priority_type>::orderUp(ElementListIt i) {
+
+	assert(i != m_elements.end() && L"Invalid iterator passed to function");
+
+	value_type vt = (*i);
+
+	i = m_elements.erase(i);
+
+	while(i != m_elements.end()) {
+
+		if(compare(vt, (*i)) > 0) {
+			
+			m_elements.insert(i, vt);
+
+			return;
+		}
+
+		++i;
+	}
+
+	m_elements.push_back(vt);
+
+}
+
+template<class index_type, class priority_type>
+void FIFE::PriorityQueue<index_type, priority_type>::orderUp(const value_type& val)
+{
+	for(ElementListIt i = m_elements.begin(); i != m_elements.end(); ++i)
+	{
+		assert(val.first != i->first);
+
+		if(compare(val, (*i)) > 0)
+		{
+			assert(val.first != i->first);
+
+			m_elements.insert(i, val);
+
+			return;
+		}
+	}
+
+	m_elements.push_back(val);
+}
+
+template<typename index_type, typename priority_type>
+void FIFE::PriorityQueue<index_type, priority_type>::orderDown(ElementListIt i) {
+
+	assert(i != m_elements.end());
+
+	value_type vt = (*i);
+
+	i = m_elements.erase(i);
+
+	if(i == m_elements.end()) {
+		--i;
+	}
+
+	ElementListIt j = i;
+
+	++j;
+
+	while(i != m_elements.begin()) {
+		if(compare(vt, (*i)) < 0) {
+			
+			m_elements.insert(j, vt);
+			
+			return;
+		}
+
+		--i;
+		--j;
+	}
+
+	m_elements.push_front(vt);
+}
+
+template<typename index_type, typename priority_type>
+int FIFE::PriorityQueue<index_type, priority_type>::compare(const value_type& a, const value_type& b) { 
+	
+	if(m_ordering == Descending) {
+
+		if(a.second > b.second) {
+			return 1;
+		} else if(b.second > a.second) {
+			return -1;
+		}
+
+	} else {
+
+		if(a.second < b.second) {
+			return 1;
+		} else if(b.second < a.second) {
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+#endif