/**************************************************************************** ** ** Copyright (C) 2015 Corentin Chary ** ** 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 QT_BEGIN_HEADER QT_BEGIN_NAMESPACE QT_MODULE(Core) template class QList; #ifndef QT_NO_STL #include #include #else /* Fallback class used when stl is not available */ template > 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 Q_CORE_EXPORT QPriorityQueue { public: inline QPriorityQueue(LessThan l = qLess < T >()) : lessThan(l), d(lessThan) { } inline QPriorityQueue(const QPriorityQueue &q) : lessThan(q.lessThan), d(q.d) { } inline ~QPriorityQueue() { } QPriorityQueue &operator=(const QPriorityQueue &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 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(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 &operator+=(const T &t) { enqueue(t); return *this; } inline QPriorityQueue &operator<< (const T &t) { enqueue(t); return *this; } inline QPriorityQueue &operator>> (T &t) { t = d.top(); d.pop(); return *this; } #ifndef QT_NO_STL static inline QPriorityQueuefromStdPriorityQueue( const std::priority_queue &q) { QPriorityQueue tmp; tmp.d = q; return tmp; } inline std::priority_queue toStdPriorityQueue() const { return d; } #endif private: LessThan lessThan; #ifndef QT_NO_STL std::priority_queue , LessThan> d; #else QPriorityQueuePrivate d; #endif }; #ifndef QT_NO_STL template Q_INLINE_TEMPLATE void QPriorityQueue::clear() { d = std::priority_queue , LessThan>(lessThan); //d = std::priority_queue(lessThan); } #else template Q_INLINE_TEMPLATE void QPriorityQueue::clear() { d.clear(); } #endif template Q_OUTOFLINE_TEMPLATE void QPriorityQueue::append(const QList &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 Q_OUTOFLINE_TEMPLATE void QPriorityQueuePrivate::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 Q_OUTOFLINE_TEMPLATE void QPriorityQueuePrivate::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