Mercurial > data_structures
changeset 2:b49d814f20a4
Added pqueue - priority queue
author | Eris Caffee <discordia@eldalin.com> |
---|---|
date | Fri, 21 Sep 2012 02:03:01 -0500 |
parents | 392ce56806f9 |
children | f32df8c249f0 |
files | CMakeLists.txt README src/dequeue.h src/pqueue.c src/pqueue.h src/pqueue_test src/pqueue_test.c src/queue.h src/ring_buffer.h src/stack.h |
diffstat | 10 files changed, 239 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- a/CMakeLists.txt Thu Sep 20 23:11:40 2012 -0500 1.2 +++ b/CMakeLists.txt Fri Sep 21 02:03:01 2012 -0500 1.3 @@ -62,3 +62,8 @@ 1.4 ${dequeue_SRCS} 1.5 ) 1.6 1.7 +set (pqueue_SRCS src/pqueue.h src/pqueue.c src/pqueue_test.c) 1.8 +add_executable (pqueue_test 1.9 + ${pqueue_SRCS} 1.10 + ) 1.11 +
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/README Fri Sep 21 02:03:01 2012 -0500 2.3 @@ -0,0 +1,1 @@ 2.4 +This is just a collection of basic data structures implemented in C. I did these as a refresher of things I've not had to do in a few years. (why make a dequeue by hand when then STL has a nice one ready to be used?) Thus, the emphasis is on clarity and demonstrating the fundamental technique. Performance and features are not the goal here.
3.1 --- a/src/dequeue.h Thu Sep 20 23:11:40 2012 -0500 3.2 +++ b/src/dequeue.h Fri Sep 21 02:03:01 2012 -0500 3.3 @@ -1,6 +1,8 @@ 3.4 #ifndef DEQUEUE_H_ 3.5 #define DEQUEUE_H_ 3.6 3.7 +#include <stddef.h> 3.8 + 3.9 struct dequeue 3.10 { 3.11 void ** data;
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/pqueue.c Fri Sep 21 02:03:01 2012 -0500 4.3 @@ -0,0 +1,127 @@ 4.4 +#include <stdlib.h> 4.5 + 4.6 +#include "pqueue.h" 4.7 + 4.8 +//////////////////////////////////////////////////////////////////////////////// 4.9 +// comp should return true if *a comp *b. 4.10 +// So, for a min priority queue, comp will be defined to return true if *a < *b, 4.11 +// whereas for a max priority queue comp will be defined to return true if *a > *b, 4.12 + 4.13 +struct pqueue * 4.14 +pqueue_new(size_t max, bool (*comp)(void const * const a, void const * const b)) 4.15 + { 4.16 + if ( (0 == max) || (NULL == comp) ) 4.17 + return NULL; 4.18 + 4.19 + struct pqueue * pq = malloc(sizeof(struct pqueue)); 4.20 + if (NULL == pq) 4.21 + return NULL; 4.22 + 4.23 + pq->max = max; 4.24 + pq->size = 0; 4.25 + pq->comp = comp; 4.26 + 4.27 + // Allocate space for max+1 since we are going to waste the first element in order to use a one based array. 4.28 + pq->data = malloc((1 + pq->max) * sizeof(void *)); 4.29 + if (NULL == pq->data) 4.30 + { 4.31 + free(pq); 4.32 + return NULL; 4.33 + } 4.34 + 4.35 + return pq; 4.36 + } 4.37 + 4.38 + 4.39 +//////////////////////////////////////////////////////////////////////////////// 4.40 +void 4.41 +pqueue_delete(struct pqueue * pq) 4.42 + { 4.43 + if (NULL != pq) 4.44 + { 4.45 + free(pq->data); 4.46 + free(pq); 4.47 + } 4.48 + } 4.49 + 4.50 +//////////////////////////////////////////////////////////////////////////////// 4.51 +void * 4.52 +pqueue_push(struct pqueue * pq, void * elem) 4.53 + { 4.54 + if ( (NULL == pq) || (NULL == elem) ) 4.55 + return NULL; 4.56 + 4.57 + if (pq->size == pq->max) 4.58 + return NULL; 4.59 + 4.60 + pq->size++; 4.61 + pq->data[pq->size] = elem; 4.62 + 4.63 + // sift up 4.64 + void * temp; 4.65 + size_t i, parent; 4.66 + for (i = pq->size, parent = i/2; 4.67 + (i > 1) && (! pq->comp(pq->data[parent], pq->data[i])); 4.68 + i = parent, parent = i/2) 4.69 + { 4.70 + temp = pq->data[i]; 4.71 + pq->data[i] = pq->data[parent]; 4.72 + pq->data[parent] = temp; 4.73 + } 4.74 + 4.75 + return elem; 4.76 + } 4.77 + 4.78 + 4.79 +//////////////////////////////////////////////////////////////////////////////// 4.80 +void * 4.81 +pqueue_pop(struct pqueue * pq) 4.82 + { 4.83 + if ( (NULL == pq) || (0 == pq->size) ) 4.84 + return NULL; 4.85 + 4.86 + void * val = pq->data[1]; 4.87 + 4.88 + pq->data[1] = pq->data[pq->size]; 4.89 + pq->size--; 4.90 + 4.91 + // sift down 4.92 + void * temp; 4.93 + size_t i, child; 4.94 + for (i = 1; (child = 2*i) <= pq->size; i = child) 4.95 + { 4.96 + if ( (child+1 <= pq->size) && (pq->comp(pq->data[child+1], pq->data[child])) ) 4.97 + child++; 4.98 + if (pq->comp(pq->data[child], pq->data[i])) 4.99 + { 4.100 + temp = pq->data[i]; 4.101 + pq->data[i] = pq->data[child]; 4.102 + pq->data[child] = temp; 4.103 + } 4.104 + else 4.105 + break; 4.106 + } 4.107 + 4.108 + return val; 4.109 + } 4.110 + 4.111 + 4.112 +//////////////////////////////////////////////////////////////////////////////// 4.113 +void * 4.114 +pqueue_peek(struct pqueue * pq) 4.115 + { 4.116 + if ( (NULL == pq) || (0 == pq->size) ) 4.117 + return NULL; 4.118 + 4.119 + return pq->data[1]; 4.120 + } 4.121 + 4.122 +//////////////////////////////////////////////////////////////////////////////// 4.123 +size_t 4.124 +pqueue_size(struct pqueue * pq) 4.125 + { 4.126 + if (NULL == pq) 4.127 + return 0; 4.128 + 4.129 + return pq->size; 4.130 + }
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/pqueue.h Fri Sep 21 02:03:01 2012 -0500 5.3 @@ -0,0 +1,25 @@ 5.4 +#ifndef PQUEUE_ 5.5 +#define PQUEUE_ 5.6 + 5.7 +#include <stddef.h> 5.8 +#include <stdbool.h> 5.9 + 5.10 +struct pqueue 5.11 + { 5.12 + void ** data; 5.13 + size_t max; 5.14 + size_t size; 5.15 + bool (*comp)(void const * const a, void const * const b); 5.16 + }; 5.17 + 5.18 +struct pqueue * pqueue_new(size_t max, 5.19 + bool (*comp)(void const * const a, void const * const b)); 5.20 +void pqueue_delete(struct pqueue * pq); 5.21 + 5.22 +void * pqueue_push(struct pqueue * pq, void * elem); 5.23 +void * pqueue_pop(struct pqueue * pq); 5.24 +void * pqueue_peek(struct pqueue * pq); 5.25 + 5.26 +size_t pqueue_size(struct pqueue * pq); 5.27 + 5.28 +#endif // ndef PQUEUE_
6.1 Binary file src/pqueue_test has changed
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/src/pqueue_test.c Fri Sep 21 02:03:01 2012 -0500 7.3 @@ -0,0 +1,73 @@ 7.4 +#include <stdio.h> 7.5 +#include <stdlib.h> 7.6 +#include <stdbool.h> 7.7 +#include <time.h> 7.8 + 7.9 +#include "pqueue.h" 7.10 + 7.11 +#define MAX 10 7.12 + 7.13 +bool int_lt(void const * const a, void const * const b) 7.14 + { 7.15 + return *((int *) a) < *((int *) b); 7.16 + } 7.17 + 7.18 +bool int_gt(void const * const a, void const * const b) 7.19 + { 7.20 + return *((int *) a) > *((int *) b); 7.21 + } 7.22 + 7.23 +int main(int argc, char**argv) 7.24 + { 7.25 + struct pqueue * pq = pqueue_new(MAX, int_gt); 7.26 + if (NULL == pq) 7.27 + { 7.28 + perror("pqueue_new"); 7.29 + exit(EXIT_FAILURE); 7.30 + } 7.31 + 7.32 + srand(time(NULL)); 7.33 + 7.34 + // Fill the queue 7.35 + for (int i = 0; i < MAX; i++) 7.36 + { 7.37 + int * ip = malloc(sizeof(int)); 7.38 + *ip = rand(); 7.39 + if (NULL == ip) 7.40 + { 7.41 + perror("malloc"); 7.42 + exit(EXIT_FAILURE); 7.43 + } 7.44 + 7.45 + if (NULL == pqueue_push(pq, ip)) 7.46 + { 7.47 + perror("pqueue_push"); 7.48 + exit(EXIT_FAILURE); 7.49 + } 7.50 + } 7.51 + 7.52 + printf("size is %zd\n", pqueue_size(pq)); 7.53 + 7.54 + int * ip; 7.55 + printf("peeking..."); 7.56 + ip = pqueue_peek(pq); 7.57 + if (NULL == ip) 7.58 + { 7.59 + perror("pqueue_peek"); 7.60 + exit(EXIT_FAILURE); 7.61 + } 7.62 + printf("%d\n", *ip); 7.63 + 7.64 + printf("size is %zd\n", pqueue_size(pq)); 7.65 + 7.66 + // Empty the queue 7.67 + while (ip = pqueue_pop(pq)) 7.68 + { 7.69 + printf("%d\n", *ip); 7.70 + free(ip); 7.71 + } 7.72 + 7.73 + printf("size is %zd\n", pqueue_size(pq)); 7.74 + 7.75 + pqueue_delete(pq); 7.76 + }
8.1 --- a/src/queue.h Thu Sep 20 23:11:40 2012 -0500 8.2 +++ b/src/queue.h Fri Sep 21 02:03:01 2012 -0500 8.3 @@ -1,6 +1,8 @@ 8.4 #ifndef QUEUE_ 8.5 #define QUEUE_ 8.6 8.7 +#include <stddef.h> 8.8 + 8.9 struct queue 8.10 { 8.11 void ** data;