pqueue.c

Go to the documentation of this file.
00001 
00007 /*
00008 Originally written by Justin-Heyes Jones
00009 Modified by Shlomi Fish, 2000
00010 Modified by Florian Festi, 2007
00011 
00012 This file is in the public domain (it's uncopyrighted).
00013 
00014 Check out Justin-Heyes Jones' A* page from which this code has
00015 originated:
00016     http://www.geocities.com/jheyesjones/astar.html
00017 */
00018 
00019 #include "common.h"
00020 #include "pqueue.h"
00021 
00022 /* given an index to any element in a binary tree stored in a linear array with the root at 1 and
00023  * a "sentinel" value at 0 these macros are useful in making the code clearer */
00024 
00025 /* the parent is always given by index/2 */
00026 #define PQ_PARENT_INDEX(i) ((i)>>1)
00027 #define PQ_FIRST_ENTRY (1)
00028 
00029 /* left and right children are index * 2 and (index * 2) +1 respectively */
00030 #define PQ_LEFT_CHILD_INDEX(i) ((i)<<1)
00031 #define PQ_RIGHT_CHILD_INDEX(i) (((i)<<1)+1)
00032 #define PGetRating(elem) ((elem).rating)
00033 
00034 
00038 void PQueueInitialise (priorityQueue_t *pq, uint32_t maxElements)
00039 {
00040     pq->maxSize = maxElements;
00041     pq->currentSize = 0;
00042 
00043     pq->elements = (priorityQueueElement_t*) malloc(sizeof(priorityQueueElement_t) * (maxElements + 1));
00044 
00045     if (pq->elements == NULL)
00046         Sys_Error("PQueueInitialise: Memory alloc failed!");
00047 }
00048 
00049 void PQueuePush (priorityQueue_t *pq, pos4_t item, priorityQueueRating_t r)
00050 {
00051     uint32_t i, j;
00052     uint32_t currentSize = pq->currentSize;
00053 
00054     if (currentSize == pq->maxSize) {
00055         int new_size;
00056         new_size = pq->maxSize * 2;
00057         pq->elements = (priorityQueueElement_t *)realloc(pq->elements, sizeof(*pq->elements) * (new_size + 1));
00058         pq->maxSize = new_size;
00059     }
00060 
00061     /* set i to the first unused element and increment CurrentSize */
00062     i = (++currentSize);
00063 
00064     /* while the parent of the space we're putting the new node into is worse than
00065      * our new node, swap the space with the worse node. We keep doing that until we
00066      * get to a worse node or until we get to the top
00067      * note that we also can sort so that the minimum elements bubble up so we need to loops
00068      * with the comparison operator flipped... */
00069 
00070     while (i > PQ_FIRST_ENTRY && pq->elements[PQ_PARENT_INDEX(i)].rating > r) {
00071         pq->elements[i] = pq->elements[PQ_PARENT_INDEX(i)];
00072         i = PQ_PARENT_INDEX(i);
00073     }
00074 
00075     /* then add the element at the space we created. */
00076     for (j = 0; j < 4; j++)
00077         pq->elements[i].item[j] = item[j];
00078 
00079     pq->elements[i].rating = r;
00080 
00081     pq->currentSize = currentSize;
00082 }
00083 
00087 void PQueueFree (priorityQueue_t *pq)
00088 {
00089     free(pq->elements);
00090 }
00091 
00095 void PQueuePop (priorityQueue_t *pq, pos4_t item)
00096 {
00097     uint32_t i, j;
00098     uint32_t child;
00099     priorityQueueElement_t * elements = pq->elements;
00100     uint32_t currentSize = pq->currentSize;
00101     priorityQueueElement_t pMaxElement;
00102     priorityQueueElement_t pLastElement;
00103 
00104     if (PQueueIsEmpty(pq))
00105         return;
00106 
00107     pMaxElement = elements[PQ_FIRST_ENTRY];
00108 
00109     /* get pointer to last element in tree */
00110     pLastElement = elements[currentSize--];
00111 
00112     for (j = 0; j < 4; j++)
00113         item[j] = pMaxElement.item[j];
00114 
00115     for (i = PQ_FIRST_ENTRY; (child = PQ_LEFT_CHILD_INDEX(i)) <= currentSize; i = child) {
00116         /* set child to the smaller of the two children... */
00117 
00118         if ((child != currentSize) && (elements[child + 1].rating < elements[child].rating))
00119             child ++;
00120 
00121         if (pLastElement.rating > elements[ child ].rating)
00122             elements[i] = elements[child];
00123         else
00124             break;
00125     }
00126 
00127     elements[i] = pLastElement;
00128     pq->currentSize = currentSize;
00129 }

Generated by  doxygen 1.6.2