2 * This file is part of libFirm.
3 * Copyright (C) 2012 University of Karlsruhe.
8 * @author Christian Wuerdig, Matthias Braun
9 * @brief Priority Queue implementation based on the heap datastructure
20 * Implementation note: It might seem strange that we start indexing at 0
21 * but use 2*i and 2*i+1 to find the left and right sucessor of an index.
22 * The trick is that for index 0 the left successor is 0 again, and the
23 * right successor is 1 in this scheme. For the right successor 1 everything
24 * works like usual. We simply took care in the algorithms that they still
25 * work with the left child of 0 being 0 again. This was possible without
26 * any extra ifs or arithmetic.
27 * Thus we can save the wastage of 1 array position you can see in other
28 * implementations or the ugly (i+1)*2 - 1 and (i+1)*2 for calculating the
29 * left and right child. (At the expense that stuff easily breaks when you make
30 * changes and don't think that the left child of 0 is 0 :-/)
34 typedef struct pqueue_el_t {
44 * Enforces the heap characteristics if the queue
45 * starting from element at position @p pos.
47 static void pqueue_heapify(pqueue_t *q, size_t pos)
49 size_t len = ARR_LEN(q->elems);
51 while (pos * 2 < len) {
53 size_t exchange = pos;
55 if (q->elems[exchange].priority < q->elems[pos * 2].priority) {
59 if ((pos * 2 + 1) < len
60 && q->elems[exchange].priority < q->elems[pos * 2 + 1].priority) {
61 exchange = pos * 2 + 1;
68 q->elems[pos] = q->elems[exchange];
69 q->elems[exchange] = tmp;
76 * Sifts up a newly inserted element at position @p pos.
78 static void pqueue_sift_up(pqueue_t *q, size_t pos)
80 while (q->elems[pos].priority > q->elems[pos / 2].priority) {
84 q->elems[pos] = q->elems[pos / 2];
85 q->elems[pos / 2] = tmp;
91 pqueue_t *new_pqueue(void)
93 pqueue_t *res = XMALLOC(pqueue_t);
94 res->elems = NEW_ARR_F(pqueue_el_t, 0);
98 void del_pqueue(pqueue_t *q)
104 void pqueue_put(pqueue_t *q, void *data, int priority)
109 el.priority = priority;
111 ARR_APP1(pqueue_el_t, q->elems, el);
113 pqueue_sift_up(q, ARR_LEN(q->elems) - 1);
116 void *pqueue_pop_front(pqueue_t *q)
118 switch (ARR_LEN(q->elems)) {
120 panic("Attempt to retrieve element from empty priority queue.");
122 ARR_SHRINKLEN(q->elems, 0);
123 return q->elems[0].data;
125 void *data = q->elems[0].data;
126 size_t len = ARR_LEN(q->elems) - 1;
128 q->elems[0] = q->elems[len];
129 ARR_SHRINKLEN(q->elems, len);
130 pqueue_heapify(q, 0);
137 size_t pqueue_length(const pqueue_t *q)
139 return ARR_LEN(q->elems);
142 int pqueue_empty(const pqueue_t *q)
144 return ARR_LEN(q->elems) == 0;