|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */ |
|
3 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #ifndef NS_TPRIORITY_QUEUE_H_ |
|
8 #define NS_TPRIORITY_QUEUE_H_ |
|
9 |
|
10 #include "nsTArray.h" |
|
11 #include "nsDebug.h" |
|
12 |
|
13 /** |
|
14 * A templatized priority queue data structure that uses an nsTArray to serve as |
|
15 * a binary heap. The default comparator causes this to act like a min-heap. |
|
16 * Only the LessThan method of the comparator is used. |
|
17 */ |
|
18 template<class T, class Compare = nsDefaultComparator<T, T> > |
|
19 class nsTPriorityQueue |
|
20 { |
|
21 public: |
|
22 typedef typename nsTArray<T>::size_type size_type; |
|
23 |
|
24 /** |
|
25 * Default constructor also creates a comparator object using the default |
|
26 * constructor for type Compare. |
|
27 */ |
|
28 nsTPriorityQueue() : mCompare(Compare()) { } |
|
29 |
|
30 /** |
|
31 * Constructor to allow a specific instance of a comparator object to be |
|
32 * used. |
|
33 */ |
|
34 nsTPriorityQueue(const Compare& aComp) : mCompare(aComp) { } |
|
35 |
|
36 /** |
|
37 * Copy constructor |
|
38 */ |
|
39 nsTPriorityQueue(const nsTPriorityQueue& aOther) |
|
40 : mElements(aOther.mElements), |
|
41 mCompare(aOther.mCompare) |
|
42 { } |
|
43 |
|
44 /** |
|
45 * @return True if the queue is empty or false otherwise. |
|
46 */ |
|
47 bool IsEmpty() const |
|
48 { |
|
49 return mElements.IsEmpty(); |
|
50 } |
|
51 |
|
52 /** |
|
53 * @return The number of elements in the queue. |
|
54 */ |
|
55 size_type Length() const |
|
56 { |
|
57 return mElements.Length(); |
|
58 } |
|
59 |
|
60 /** |
|
61 * @return The topmost element in the queue without changing the queue. This |
|
62 * is the element 'a' such that there is no other element 'b' in the queue for |
|
63 * which Compare(b, a) returns true. (Since this container does not check |
|
64 * for duplicate entries there may exist 'b' for which Compare(a, b) returns |
|
65 * false.) |
|
66 */ |
|
67 const T& Top() const |
|
68 { |
|
69 NS_ABORT_IF_FALSE(!mElements.IsEmpty(), "Empty queue"); |
|
70 return mElements[0]; |
|
71 } |
|
72 |
|
73 /** |
|
74 * Adds an element to the queue |
|
75 * @param aElement The element to add |
|
76 * @return true on success, false on out of memory. |
|
77 */ |
|
78 bool Push(const T& aElement) |
|
79 { |
|
80 T* elem = mElements.AppendElement(aElement); |
|
81 if (!elem) |
|
82 return false; // Out of memory |
|
83 |
|
84 // Sift up |
|
85 size_type i = mElements.Length() - 1; |
|
86 while (i) { |
|
87 size_type parent = (size_type)((i - 1) / 2); |
|
88 if (mCompare.LessThan(mElements[parent], mElements[i])) { |
|
89 break; |
|
90 } |
|
91 Swap(i, parent); |
|
92 i = parent; |
|
93 } |
|
94 |
|
95 return true; |
|
96 } |
|
97 |
|
98 /** |
|
99 * Removes and returns the top-most element from the queue. |
|
100 * @return The topmost element, that is, the element 'a' such that there is no |
|
101 * other element 'b' in the queue for which Compare(b, a) returns true. |
|
102 * @see Top() |
|
103 */ |
|
104 T Pop() |
|
105 { |
|
106 NS_ABORT_IF_FALSE(!mElements.IsEmpty(), "Empty queue"); |
|
107 T pop = mElements[0]; |
|
108 |
|
109 // Move last to front |
|
110 mElements[0] = mElements[mElements.Length() - 1]; |
|
111 mElements.TruncateLength(mElements.Length() - 1); |
|
112 |
|
113 // Sift down |
|
114 size_type i = 0; |
|
115 while (2*i + 1 < mElements.Length()) { |
|
116 size_type swap = i; |
|
117 size_type l_child = 2*i + 1; |
|
118 if (mCompare.LessThan(mElements[l_child], mElements[i])) { |
|
119 swap = l_child; |
|
120 } |
|
121 size_type r_child = l_child + 1; |
|
122 if (r_child < mElements.Length() && |
|
123 mCompare.LessThan(mElements[r_child], mElements[swap])) { |
|
124 swap = r_child; |
|
125 } |
|
126 if (swap == i) { |
|
127 break; |
|
128 } |
|
129 Swap(i, swap); |
|
130 i = swap; |
|
131 } |
|
132 |
|
133 return pop; |
|
134 } |
|
135 |
|
136 /** |
|
137 * Removes all elements from the queue. |
|
138 */ |
|
139 void Clear() |
|
140 { |
|
141 mElements.Clear(); |
|
142 } |
|
143 |
|
144 /** |
|
145 * Provides readonly access to the queue elements as an array. Generally this |
|
146 * should be avoided but may be needed in some situations such as when the |
|
147 * elements contained in the queue need to be enumerated for cycle-collection. |
|
148 * @return A pointer to the first element of the array. If the array is |
|
149 * empty, then this pointer must not be dereferenced. |
|
150 */ |
|
151 const T* Elements() const |
|
152 { |
|
153 return mElements.Elements(); |
|
154 } |
|
155 |
|
156 protected: |
|
157 /** |
|
158 * Swaps the elements at the specified indices. |
|
159 */ |
|
160 void Swap(size_type aIndexA, size_type aIndexB) |
|
161 { |
|
162 T temp = mElements[aIndexA]; |
|
163 mElements[aIndexA] = mElements[aIndexB]; |
|
164 mElements[aIndexB] = temp; |
|
165 } |
|
166 |
|
167 nsTArray<T> mElements; |
|
168 Compare mCompare; // Comparator object |
|
169 }; |
|
170 |
|
171 #endif // NS_TPRIORITY_QUEUE_H_ |