pqueue.c
上传用户:xiaozhuqw
上传日期:2009-11-15
资源大小:1338k
文件大小:4k
- /* Priority queue functions.
- Copyright (C) 2003 Yasuhiro Ohara
- This file is part of GNU Zebra.
- GNU Zebra is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
- GNU Zebra is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GNU Zebra; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
- #include <zebra.h>
- #include "pqueue.h"
- /* priority queue using heap sort */
- /* pqueue->cmp() controls the order of sorting (i.e, ascending or
- descending). If you want the left node to move upper of the heap
- binary tree, make cmp() to return less than 0. for example, if cmp
- (10, 20) returns -1, the sorting is ascending order. if cmp (10,
- 20) returns 1, the sorting is descending order. if cmp (10, 20)
- returns 0, this library does not do sorting (which will not be what
- you want). To be brief, if the contents of cmp_func (left, right)
- is left - right, dequeue () returns the smallest node. Otherwise
- (if the contents is right - left), dequeue () returns the largest
- node. */
- #define DATA_SIZE (sizeof (void *))
- #define PARENT_OF(x) ((x - 1) / 2)
- #define LEFT_OF(x) (2 * x + 1)
- #define RIGHT_OF(x) (2 * x + 2)
- #define HAVE_CHILD(x,q) (x < (q)->size / 2)
- static void
- trickle_up (int index, struct pqueue *queue)
- {
- void *tmp;
- /* Save current node as tmp node. */
- tmp = queue->array[index];
- /* Continue until the node reaches top or the place where the parent
- node should be upper than the tmp node. */
- while (index > 0 &&
- (*queue->cmp) (tmp, queue->array[PARENT_OF (index)]) < 0)
- {
- /* actually trickle up */
- queue->array[index] = queue->array[PARENT_OF (index)];
- index = PARENT_OF (index);
- }
- /* Restore the tmp node to appropriate place. */
- queue->array[index] = tmp;
- }
- static void
- trickle_down (int index, struct pqueue *queue)
- {
- void *tmp;
- int which;
- /* Save current node as tmp node. */
- tmp = queue->array[index];
- /* Continue until the node have at least one (left) child. */
- while (HAVE_CHILD (index, queue))
- {
- /* If right child exists, and if the right child is more proper
- to be moved upper. */
- if (RIGHT_OF (index) < queue->size &&
- (*queue->cmp) (queue->array[LEFT_OF (index)],
- queue->array[RIGHT_OF (index)]) > 0)
- which = RIGHT_OF (index);
- else
- which = LEFT_OF (index);
- /* If the tmp node should be upper than the child, break. */
- if ((*queue->cmp) (queue->array[which], tmp) > 0)
- break;
- /* Actually trickle down the tmp node. */
- queue->array[index] = queue->array[which];
- index = which;
- }
- /* Restore the tmp node to appropriate place. */
- queue->array[index] = tmp;
- }
- struct pqueue *
- pqueue_create ()
- {
- struct pqueue *queue;
- queue = (struct pqueue *) malloc (sizeof (struct pqueue));
- memset (queue, 0, sizeof (struct pqueue));
- queue->array = (void **)
- malloc (DATA_SIZE * PQUEUE_INIT_ARRAYSIZE);
- memset (queue->array, 0, DATA_SIZE * PQUEUE_INIT_ARRAYSIZE);
- queue->array_size = PQUEUE_INIT_ARRAYSIZE;
- return queue;
- }
- void
- pqueue_delete (struct pqueue *queue)
- {
- free (queue->array);
- free (queue);
- }
- static int
- pqueue_expand (struct pqueue *queue)
- {
- void **newarray;
- newarray = (void **) malloc (queue->array_size * DATA_SIZE * 2);
- if (newarray == NULL)
- return 0;
- memset (newarray, 0, queue->array_size * DATA_SIZE * 2);
- memcpy (newarray, queue->array, queue->array_size * DATA_SIZE);
- free (queue->array);
- queue->array = newarray;
- queue->array_size *= 2;
- return 1;
- }
- void
- pqueue_enqueue (void *data, struct pqueue *queue)
- {
- if (queue->size + 2 >= queue->array_size && ! pqueue_expand (queue))
- return;
- queue->array[queue->size] = data;
- trickle_up (queue->size, queue);
- queue->size ++;
- }
- void *
- pqueue_dequeue (struct pqueue *queue)
- {
- void *data = queue->array[0];
- queue->array[0] = queue->array[--queue->size];
- trickle_down (0, queue);
- return data;
- }