255 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			255 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /****************************************************************************
 | |
| **
 | |
| ** Copyright (C) 2015 Corentin Chary <corentin.chary@gmail.cm>
 | |
| **
 | |
| ** This file could be part of the QtCore module of the Qt Toolkit.
 | |
| **
 | |
| ** $QT_BEGIN_LICENSE:LGPL$
 | |
| ** No Commercial Usage
 | |
| ** This file contains pre-release code and may not be distributed.
 | |
| ** You may use this file in accordance with the terms and conditions
 | |
| ** contained in the Technology Preview License Agreement accompanying
 | |
| ** this package.
 | |
| **
 | |
| ** GNU Lesser General Public License Usage
 | |
| ** Alternatively, this file may be used under the terms of the GNU Lesser
 | |
| ** General Public License version 2.1 as published by the Free Software
 | |
| ** Foundation and appearing in the file LICENSE.LGPL included in the
 | |
| ** packaging of this file.  Please review the following information to
 | |
| ** ensure the GNU Lesser General Public License version 2.1 requirements
 | |
| ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 | |
| **
 | |
| ** In addition, as a special exception, Nokia gives you certain additional
 | |
| ** rights.  These rights are described in the Nokia Qt LGPL Exception
 | |
| ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 | |
| **
 | |
| ** If you have questions regarding the use of this file, please contact
 | |
| ** Nokia at qt-info@nokia.com.
 | |
| **
 | |
| **
 | |
| **
 | |
| **
 | |
| **
 | |
| **
 | |
| **
 | |
| **
 | |
| ** $QT_END_LICENSE$
 | |
| **
 | |
| ****************************************************************************/
 | |
| 
 | |
| #ifndef QPRIORITY_QUEUE_H
 | |
| #define QPRIORITY_QUEUE_H
 | |
| 
 | |
| #include <QtCore/qalgorithms.h>
 | |
| 
 | |
| QT_BEGIN_HEADER
 | |
| 
 | |
| QT_BEGIN_NAMESPACE
 | |
| 
 | |
| QT_MODULE(Core)
 | |
| 
 | |
| template <class T> class QList;
 | |
| 
 | |
| #ifndef QT_NO_STL
 | |
| #include <queue>
 | |
| #include <vector>
 | |
| #else
 | |
| /* Fallback class used when stl is not available */
 | |
| template <class T, typename LessThan = qLess < T > >
 | |
| class QPriorityQueuePrivate {
 | |
| public:
 | |
|     inline QPriorityQueuePrivate(LessThan l) : lessThan(l), d() {}
 | |
|     inline ~QPriorityQueuePrivate() {}
 | |
| 
 | |
|     inline void clear() { return d.clear(); }
 | |
|     inline int size() const { return d.size(); }
 | |
|     inline bool empty() const { return d.empty(); }
 | |
| 
 | |
|     inline T &top() { return d.front(); }
 | |
| 
 | |
|     void pop();
 | |
|     void push(const T &value);
 | |
| private:
 | |
|     inline int parent(int i) {
 | |
|     return (i - 1) / 2;
 | |
|     }
 | |
|     inline int leftChild(int i) {
 | |
|     return 2 * i + 1;
 | |
|     }
 | |
|     inline int rightChild(int i) {
 | |
|     return 2 * i + 2;
 | |
|     }
 | |
| 
 | |
|     LessThan lessThan;
 | |
|     QList < T > d;
 | |
| };
 | |
| #endif
 | |
| 
 | |
| template <class T, typename LessThan = qLess < T > >
 | |
| class Q_CORE_EXPORT QPriorityQueue
 | |
| {
 | |
| public:
 | |
|     inline QPriorityQueue(LessThan l = qLess < T >())
 | |
|       : lessThan(l), d(lessThan) { }
 | |
|     inline QPriorityQueue(const QPriorityQueue<T> &q)
 | |
|       : lessThan(q.lessThan), d(q.d) { }
 | |
|     inline ~QPriorityQueue() { }
 | |
| 
 | |
|     QPriorityQueue<T> &operator=(const QPriorityQueue<T> &q) {
 | |
|       d = q.d; return *this;
 | |
|     }
 | |
| 
 | |
|     inline int size() const { return d.size(); }
 | |
|     inline bool isEmpty() const { return empty(); }
 | |
| 
 | |
|     // like qlist
 | |
|     void clear();
 | |
|     void append(const T &t) { return enqueue(t); }
 | |
|     void append(const QList<T> &t);
 | |
|     T takeFirst() { return dequeue(); }
 | |
|     inline int length() const { return size(); } // Same as count()
 | |
|     inline T& first() { return head(); }
 | |
|     inline const T& first() const { return head(); }
 | |
|     inline void removeFirst() { pop(); }
 | |
|     inline bool startsWith(const T &t) const
 | |
|     { return !isEmpty() && first() == t; }
 | |
| 
 | |
|     // like qqueue
 | |
|     inline void enqueue(const T &t) { push(t); }
 | |
|     inline T dequeue() { T t = d.top();	d.pop(); return t; }
 | |
|     inline T &head() { return const_cast<T&>(top()); }
 | |
|     inline const T &head() const { return top(); }
 | |
| 
 | |
|     // stl compatibility
 | |
|     typedef int size_type;
 | |
|     typedef T value_type;
 | |
| 
 | |
|     inline bool empty() const { return d.empty(); }
 | |
|     inline const value_type& top() { Q_ASSERT(!isEmpty()); return d.top(); }
 | |
|     inline void push(const value_type& x) { return d.push(x); }
 | |
|     inline void pop() { Q_ASSERT(!isEmpty()); d.pop(); }
 | |
| 
 | |
|     // comfort
 | |
|     inline QPriorityQueue<T> &operator+=(const T &t) {
 | |
|       enqueue(t); return *this;
 | |
|     }
 | |
|     inline QPriorityQueue<T> &operator<< (const T &t) {
 | |
|       enqueue(t); return *this;
 | |
|     }
 | |
|     inline QPriorityQueue<T> &operator>> (T &t) {
 | |
|       t = d.top(); d.pop(); return *this;
 | |
|     }
 | |
| 
 | |
| #ifndef QT_NO_STL
 | |
|     static inline QPriorityQueue<T>fromStdPriorityQueue(
 | |
|         const std::priority_queue<T> &q) {
 | |
|       QPriorityQueue<T> tmp; tmp.d = q; return tmp;
 | |
|     }
 | |
|     inline std::priority_queue<T> toStdPriorityQueue() const {
 | |
|       return d;
 | |
|     }
 | |
| #endif
 | |
| 
 | |
| private:
 | |
|     LessThan lessThan;
 | |
| #ifndef QT_NO_STL
 | |
|     std::priority_queue <T, std::vector < T >, LessThan> d;
 | |
| #else
 | |
|     QPriorityQueuePrivate <T> d;
 | |
| #endif
 | |
| };
 | |
| 
 | |
| #ifndef QT_NO_STL
 | |
| 
 | |
| template <typename T, typename LessThan>
 | |
| Q_INLINE_TEMPLATE void QPriorityQueue<T, LessThan>::clear()
 | |
| {
 | |
|     d = std::priority_queue <T, std::vector < T >, LessThan>(lessThan);
 | |
|     //d = std::priority_queue<T>(lessThan);
 | |
| }
 | |
| 
 | |
| #else
 | |
| 
 | |
| template <typename T, typename LessThan>
 | |
| Q_INLINE_TEMPLATE void QPriorityQueue<T, LessThan>::clear()
 | |
| {
 | |
|     d.clear();
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| template <typename T, typename LessThan>
 | |
| Q_OUTOFLINE_TEMPLATE void QPriorityQueue<T, LessThan>::append(const QList<T> &t)
 | |
| {
 | |
|     foreach (T & e, t)
 | |
|     push(e);
 | |
| }
 | |
| 
 | |
| // Re-implement std::priority_queue if STL not available, probably
 | |
| // less efficient.
 | |
| #ifdef QT_NO_STL
 | |
| /*!
 | |
|  *  Pop an element from the queue and reorder it using an
 | |
|  *  inlined binary heap.
 | |
|  *
 | |
|  *  \internal
 | |
|  */
 | |
| template <typename T, typename LessThan>
 | |
| Q_OUTOFLINE_TEMPLATE void QPriorityQueuePrivate<T, LessThan>::pop()
 | |
| {
 | |
|     int i = 0;
 | |
|     ssize_t size = d.size();;
 | |
| 
 | |
|     if(!size)
 | |
|     return;
 | |
|     if(size == 1)
 | |
|     return d.clear();
 | |
| 
 | |
|     d[0] = d.takeLast();
 | |
| 
 | |
|     while(i < size - 1) {
 | |
|     int left = leftChild(i);
 | |
|     int right = rightChild(i);
 | |
|     bool validLeft = left < size;
 | |
|     bool validRight = right < size;
 | |
| 
 | |
|     if(validLeft && lessThan(d.at(i), d.at(left)))
 | |
|         if(validRight && !lessThan(d.at(right), d.at(left))) {
 | |
|         d.swap(i, right);
 | |
|         i = right;
 | |
|         } else {
 | |
|         d.swap(i, left);
 | |
|         i = left;
 | |
|         }
 | |
|     else if(validRight && lessThan(d.at(i), d.at(right))) {
 | |
|         d.swap(i, right);
 | |
|         i = right;
 | |
|     }
 | |
|     else
 | |
|         break;
 | |
|     }
 | |
| }
 | |
| 
 | |
| /*!
 | |
|  *  Push an element with a given priority to the right place.
 | |
|  *
 | |
|  *  \internal
 | |
|  */
 | |
| template <typename T, typename LessThan>
 | |
| Q_OUTOFLINE_TEMPLATE void QPriorityQueuePrivate<T, LessThan>::push(const T &value)
 | |
| {
 | |
|     int i = d.size();
 | |
|     d.append(value);
 | |
|     while(i != 0 && !lessThan(d.at(i), d.at(parent(i)))) {
 | |
|     d.swap(i, parent(i));
 | |
|     i = parent(i);
 | |
|     }
 | |
| }
 | |
| #endif
 | |
| 
 | |
| QT_END_NAMESPACE
 | |
| 
 | |
| QT_END_HEADER
 | |
| 
 | |
| #endif // QPRIORITY_QUEUE_H
 | 
