lib

priorityqueue.h
1/* This file is part of the KOffice libraries
2 Copyright (C) 2001 Werner Trobin <trobin@kde.org>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License version 2 as published by the Free Software Foundation.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB. If not, write to
15 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 * Boston, MA 02110-1301, USA.
17*/
18
19#ifndef priority_queue_h
20#define priority_queue_h
21
22#include <vector>
23#include <tqstring.h>
24#include <tqasciidict.h>
25#include <kdebug.h>
26
27// Better put all those internal classes in some namespace to avoid clashes
28// as the names are quite generic
29namespace KOffice {
30
57 template<class T> class PriorityQueue {
58
59 public:
60 PriorityQueue() {}
61 PriorityQueue( const PriorityQueue<T>& rhs ) : m_vector( rhs.m_vector ) {}
62 PriorityQueue( const TQAsciiDict<T>& items );
63 ~PriorityQueue() {}
64
65 PriorityQueue<T> &operator=( const PriorityQueue<T>& rhs ) { m_vector = rhs.m_vector; return *this; }
66 bool operator==( const PriorityQueue<T>& rhs ) { return m_vector == rhs.m_vector; }
67
68 unsigned int count() const { return m_vector.size(); }
69 bool isEmpty() const { return m_vector.empty(); }
70
71 void insert( T* item );
72
78 void keyDecreased( T* item );
79
80 T* extractMinimum();
81
85 void dump() const;
86
87 private:
88 // Note: We have to use a 1-based index here, and we get/return 0-based ones
89 int parent( int i ) { return ( ( i + 1 ) >> 1 ) - 1; }
90 int left( int i ) { return ( ( i + 1 ) << 1 ) - 1; }
91 int right( int i ) { return ( i + 1 ) << 1; }
92
93 void heapify( int i );
94 // item is !=0 for sure
95 void bubbleUp( T* item, int i );
96 // Builds the heap in the vector in O(n)
97 void buildHeap();
98
99 std::vector<T*> m_vector;
100 };
101
102 template<class T>
103 PriorityQueue<T>::PriorityQueue( const TQAsciiDict<T>& items ) : m_vector( items.count() )
104 {
105 // First put all items into the vector
106 TQAsciiDictIterator<T> it( items );
107 for ( int i = 0; it.current(); ++it, ++i ) {
108 it.current()->setIndex( i );
109 m_vector[ i ] = it.current();
110 }
111 // Then build a heap in that vector
112 buildHeap();
113 }
114
115 template<class T>
116 void PriorityQueue<T>::insert( T* item )
117 {
118 if ( !item )
119 return;
120 int i = static_cast<int>( m_vector.size() );
121 m_vector.push_back( 0 ); // extend the vector by one item. i == index to the last item
122 bubbleUp( item, i );
123 }
124
125 template<class T>
127 {
128 if ( !item )
129 return;
130 bubbleUp( item, item->index() );
131 }
132
133 template<class T>
134 T* PriorityQueue<T>::extractMinimum()
135 {
136 if ( m_vector.size() < 1 )
137 return 0;
138 T *min = m_vector[ 0 ];
139 m_vector[ 0 ] = m_vector[ m_vector.size() - 1 ];
140 // update the index
141 m_vector[ 0 ]->setIndex( 0 );
142 m_vector.pop_back();
143 heapify( 0 );
144 return min;
145 }
146
147 template<class T>
149 {
150 kdDebug( 30500 ) << "++++++++++ PriorityQueue::dump ++++++++++" << endl;
151 TQString out;
152 int size = static_cast<int>( m_vector.size() );
153 for ( int i = 0; i < size; ++i ) {
154 if ( m_vector[ i ]->index() != i )
155 out += " ERROR: index out of sync. Should be " + TQString::number( i ) + ", is " +
156 TQString::number( m_vector[ i ]->index() ) + ". ";
157 out += TQString::number( m_vector[ i ]->key() );
158 out += ", ";
159 }
160 if ( out.isEmpty() )
161 out = "(empty)";
162 kdDebug( 30500 ) << out << endl;
163 kdDebug( 30500 ) << "++++++++++ PriorityQueue::dump (done) ++++++++++" << endl;
164 }
165
166 template<class T>
167 void PriorityQueue<T>::heapify( int i )
168 {
169 int l = left( i ), r = right( i ), size = static_cast<int>( m_vector.size() );
170 int smallest;
171
172 if ( l < size && m_vector[ l ]->key() < m_vector[ i ]->key() )
173 smallest = l;
174 else
175 smallest = i;
176 if ( r < size && m_vector[ r ]->key() < m_vector[ smallest ]->key() )
177 smallest = r;
178
179 if ( smallest != i ) {
180 T* tmp = m_vector[ i ];
181 m_vector[ i ] = m_vector[ smallest ];
182 // update indices
183 m_vector[ i ]->setIndex( i );
184 tmp->setIndex( smallest );
185 m_vector[ smallest ] = tmp;
186 heapify( smallest );
187 }
188 }
189
190 template<class T>
191 void PriorityQueue<T>::bubbleUp( T* item, int i )
192 {
193 int p = parent( i );
194 while ( i > 0 && m_vector[ p ]->key() > item->key() ) {
195 // update the index first
196 m_vector[ p ]->setIndex( i );
197 // then move it there
198 m_vector[ i ] = m_vector[ p ];
199 i = p;
200 p = parent( i );
201 }
202 item->setIndex( i );
203 m_vector[ i ] = item;
204 }
205
206 template<class T>
207 void PriorityQueue<T>::buildHeap()
208 {
209 // from size() / 2 down to 1
210 for ( int i = ( m_vector.size() >> 1 ) - 1; i >= 0; --i )
211 heapify( i );
212 }
213
214} // namespace KOffice
215
216#endif // priority_queue_h
void keyDecreased(T *item)
Call this method after decreasing the key of the ith item.
void dump() const
For debugging.
Namespace for general KOFFICE functions.