2 * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
6 * This file may be distributed and/or modified under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation and appearing in the file LICENSE.GPL included in the
9 * packaging of this file.
11 * Licensees holding valid libFirm Professional Edition licenses may use
12 * this file in accordance with the libFirm Commercial License.
13 * Agreement provided with the Software.
15 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * @author Christian Wuerdig, Matthias Braun
23 * @brief Priority Queue implementation based on the heap datastructure
34 * Implementation note: It might seem strange that we start indexing at 0
35 * but use 2*i and 2*i+1 to find the left and right sucessor of an index.
36 * The trick is that for index 0 the left successor is 0 again, and the
37 * right successor is 1 in this scheme. For the right successor 1 everything
38 * works like usual. We simply took care in the algorithms that they still
39 * work with the left child of 0 being 0 again. This was possible without
40 * any extra ifs or arithmetic.
41 * Thus we can save the wastage of 1 array position you can see in other
42 * implementations or the ugly (i+1)*2 - 1 and (i+1)*2 for calculating the
43 * left and right child. (At the expense that stuff easily breaks when you make
44 * changes and don't think that the left child of 0 is 0 :-/)
48 typedef struct _pqueue_el_t {
58 * Enforces the heap characteristics if the queue
59 * starting from element at position @p pos.
61 static void pqueue_heapify(pqueue_t *q, unsigned pos)
63 unsigned len = ARR_LEN(q->elems);
65 while (pos * 2 < len) {
67 unsigned exchange = pos;
69 if (q->elems[exchange].priority < q->elems[pos * 2].priority) {
73 if ((pos * 2 + 1) < len
74 && q->elems[exchange].priority < q->elems[pos * 2 + 1].priority) {
75 exchange = pos * 2 + 1;
82 q->elems[pos] = q->elems[exchange];
83 q->elems[exchange] = tmp;
90 * Sifts up a newly inserted element at position @p pos.
92 static void pqueue_sift_up(pqueue_t *q, unsigned pos)
94 while (q->elems[pos].priority > q->elems[pos / 2].priority) {
98 q->elems[pos] = q->elems[pos / 2];
99 q->elems[pos / 2] = tmp;
105 pqueue_t *new_pqueue(void)
107 pqueue_t *res = XMALLOC(pqueue_t);
108 res->elems = NEW_ARR_F(pqueue_el_t, 0);
112 void del_pqueue(pqueue_t *q)
118 void pqueue_put(pqueue_t *q, void *data, int priority)
123 el.priority = priority;
125 ARR_APP1(pqueue_el_t, q->elems, el);
127 pqueue_sift_up(q, ARR_LEN(q->elems) - 1);
130 void *pqueue_pop_front(pqueue_t *q)
132 switch (ARR_LEN(q->elems)) {
134 assert(0 && "Attempt to retrieve element from empty priority queue.");
138 ARR_SHRINKLEN(q->elems, 0);
139 return q->elems[0].data;
142 void *data = q->elems[0].data;
143 int len = ARR_LEN(q->elems) - 1;
145 q->elems[0] = q->elems[len];
146 ARR_SHRINKLEN(q->elems, len);
147 pqueue_heapify(q, 0);
154 int pqueue_length(const pqueue_t *q)
156 return ARR_LEN(q->elems);
159 int pqueue_empty(const pqueue_t *q)
161 return ARR_LEN(q->elems) == 0;