Skip to content

Commit

Permalink
Add support for priority comparison function.
Browse files Browse the repository at this point in the history
  • Loading branch information
vy committed Jan 23, 2010
1 parent bf9ba4f commit eb6708c
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 40 deletions.
58 changes: 31 additions & 27 deletions src/pqueue.c
Expand Up @@ -30,10 +30,11 @@

pqueue_t *
pq_init(size_t n,
pqueue_get_priority getpri,
pqueue_set_priority setpri,
pqueue_get_position getpos,
pqueue_set_position setpos)
pqueue_compare_priority cmppri,
pqueue_get_priority getpri,
pqueue_set_priority setpri,
pqueue_get_position getpos,
pqueue_set_position setpos)
{
pqueue_t *q;

Expand All @@ -45,14 +46,15 @@ pq_init(size_t n,
free(q);
return NULL;
}

q->size = 1;
q->avail = q->step = (n+1); /* see comment above about n+1 */
q->cmppri = cmppri;
q->setpri = setpri;
q->getpri = getpri;
q->getpos = getpos;
q->setpos = setpos;

return q;
}

Expand Down Expand Up @@ -81,7 +83,7 @@ pq_bubble_up(pqueue_t *q, size_t i)
long moving_pri = q->getpri(moving_node);

for (parent_node = parent(i);
((i > 1) && (q->getpri(q->d[parent_node]) < moving_pri));
((i > 1) && q->cmppri(q->getpri(q->d[parent_node]), moving_pri));
i = parent_node, parent_node = parent(i))
{
q->d[i] = q->d[parent_node];
Expand All @@ -101,8 +103,8 @@ maxchild(pqueue_t *q, size_t i)
if (child_node >= q->size)
return 0;

if ((child_node+1 < q->size) &&
(q->getpri(q->d[child_node+1]) > q->getpri(q->d[child_node])))
if ((child_node+1) < q->size &&
q->cmppri(q->getpri(q->d[child_node]), q->getpri(q->d[child_node+1])))
child_node++; /* use right child instead of left */

return child_node;
Expand All @@ -117,7 +119,7 @@ pq_percolate_down(pqueue_t *q, size_t i)
long moving_pri = q->getpri(moving_node);

while ((child_node = maxchild(q, i)) &&
(moving_pri < q->getpri(q->d[child_node])))
q->cmppri(moving_pri, q->getpri(q->d[child_node])))
{
q->d[i] = q->d[child_node];
q->setpos(q->d[i], i);
Expand Down Expand Up @@ -151,22 +153,22 @@ pq_insert(pqueue_t *q, void *d)
i = q->size++;
q->d[i] = d;
pq_bubble_up(q, i);

return 0;
}


void
pq_change_priority(pqueue_t *q,
long new_priority,
void *d)
long new_priority,
void *d)
{
size_t posn;
long old_priority = q->getpri(d);
long old_priority = q->getpri(d);

q->setpri(d, new_priority);
q->setpri(d, new_priority);
posn = q->getpos(d);
if (new_priority > old_priority)
if (q->cmppri(old_priority, new_priority))
pq_bubble_up(q, posn);
else
pq_percolate_down(q, posn);
Expand All @@ -178,7 +180,7 @@ pq_remove(pqueue_t *q, void *d)
{
size_t posn = q->getpos(d);
q->d[posn] = q->d[--q->size];
if (q->getpri(q->d[posn]) > q->getpri(d))
if (q->cmppri(q->getpri(d), q->getpri(q->d[posn])))
pq_bubble_up(q, posn);
else
pq_percolate_down(q, posn);
Expand Down Expand Up @@ -216,8 +218,8 @@ pq_peek(pqueue_t *q)

void
pq_dump(pqueue_t *q,
FILE *out,
pqueue_print_entry print)
FILE *out,
pqueue_print_entry print)
{
int i;

Expand All @@ -243,18 +245,20 @@ pq_set_pos(void *d, size_t val)
static void
pq_set_pri(void *d, long pri)
{
/* do nothing */
/* do nothing */
}


void
pq_print(pqueue_t *q,
FILE *out,
pqueue_print_entry print)
FILE *out,
pqueue_print_entry print)
{
pqueue_t *dup;

dup = pq_init(q->size, q->getpri, pq_set_pri, q->getpos, pq_set_pos);

dup = pq_init(q->size,
q->cmppri, q->getpri, pq_set_pri,
q->getpos, pq_set_pos);
dup->size = q->size;
dup->avail = q->avail;
dup->step = q->step;
Expand All @@ -268,7 +272,7 @@ pq_print(pqueue_t *q,
else
break;
}

pq_free(dup);
}

Expand All @@ -278,14 +282,14 @@ pq_subtree_is_valid(pqueue_t *q, int pos)
{
if (left(pos) < q->size) {
/* has a left child */
if (q->getpri(q->d[pos]) < q->getpri(q->d[left(pos)]))
if (q->cmppri(q->getpri(q->d[pos]), q->getpri(q->d[left(pos)])))
return 0;
if (!pq_subtree_is_valid(q, left(pos)))
return 0;
}
if (right(pos) < q->size) {
/* has a right child */
if (q->getpri(q->d[pos]) < q->getpri(q->d[right(pos)]))
if (q->cmppri(q->getpri(q->d[pos]), q->getpri(q->d[right(pos)])))
return 0;
if (!pq_subtree_is_valid(q, right(pos)))
return 0;
Expand Down
26 changes: 16 additions & 10 deletions src/pqueue.h
Expand Up @@ -28,6 +28,10 @@
#define PQUEUE_H


/** priority comparison function */
typedef int (*pqueue_compare_priority)(long u, long v);


/** callback functions to get/set the priority of an element */
typedef long (*pqueue_get_priority)(void *a);
typedef void (*pqueue_set_priority)(void *a, long pri);
Expand All @@ -48,6 +52,7 @@ typedef struct pqueue_t
size_t size;
size_t avail;
size_t step;
pqueue_compare_priority cmppri;
pqueue_get_priority getpri;
pqueue_set_priority setpri;
pqueue_get_position getpos;
Expand All @@ -69,10 +74,11 @@ typedef struct pqueue_t
*/
pqueue_t *
pq_init(size_t n,
pqueue_get_priority getpri,
pqueue_set_priority setpri,
pqueue_get_position getpos,
pqueue_set_position setpos);
pqueue_compare_priority cmppri,
pqueue_get_priority getpri,
pqueue_set_priority setpri,
pqueue_get_position getpos,
pqueue_set_position setpos);


/**
Expand Down Expand Up @@ -106,8 +112,8 @@ int pq_insert(pqueue_t *q, void *d);
*/
void
pq_change_priority(pqueue_t *q,
long new_priority,
void *d);
long new_priority,
void *d);


/**
Expand Down Expand Up @@ -147,8 +153,8 @@ void *pq_peek(pqueue_t *q);
*/
void
pq_print(pqueue_t *q,
FILE *out,
pqueue_print_entry print);
FILE *out,
pqueue_print_entry print);


/**
Expand All @@ -161,8 +167,8 @@ pq_print(pqueue_t *q,
*/
void
pq_dump(pqueue_t *q,
FILE *out,
pqueue_print_entry print);
FILE *out,
pqueue_print_entry print);


/**
Expand Down
24 changes: 21 additions & 3 deletions src/sample.c
Expand Up @@ -12,6 +12,13 @@ typedef struct node_t
} node_t;


static int
cmp_pri(long u, long v)
{
return (u < v);
}


static long
get_pri(void *a)
{
Expand Down Expand Up @@ -48,7 +55,7 @@ main(void)
node_t *n;

ns = malloc(10 * sizeof(node_t));
pq = pq_init(10, get_pri, set_pri, get_pos, set_pos);
pq = pq_init(10, cmp_pri, get_pri, set_pri, get_pos, set_pos);
if (!(ns && pq)) return 1;

ns[0].pri = 5; ns[0].val = -5; pq_insert(pq, &ns[0]);
Expand All @@ -58,16 +65,27 @@ main(void)
ns[4].pri = 1; ns[4].val = -1; pq_insert(pq, &ns[4]);

n = pq_peek(pq);
printf("peek: %ld @ %ul\n", n->pri, n->pos);
printf("peek: %ld [%d]\n", n->pri, n->val);

pq_change_priority(pq, 8, &ns[4]);
pq_change_priority(pq, 7, &ns[2]);

while ((n = pq_pop(pq)))
printf("pop: %ld @ %ul\n", n->pri, n->pos);
printf("pop: %ld [%d]\n", n->pri, n->val);

pq_free(pq);
free(ns);

return 0;
}

/*
* $ cc -Wall -g pqueue.c sample.c -o sample
* $ ./sample
* peek: 6 [-6]
* pop: 8 [-1]
* pop: 7 [-2]
* pop: 6 [-6]
* pop: 5 [-5]
* pop: 4 [-4]
*/

0 comments on commit eb6708c

Please sign in to comment.