Annotation of embedaddon/quagga/lib/pqueue.c, revision 1.1.1.2
1.1 misho 1: /* Priority queue functions.
2: Copyright (C) 2003 Yasuhiro Ohara
3:
4: This file is part of GNU Zebra.
5:
6: GNU Zebra is free software; you can redistribute it and/or modify
7: it under the terms of the GNU General Public License as published
8: by the Free Software Foundation; either version 2, or (at your
9: option) any later version.
10:
11: GNU Zebra is distributed in the hope that it will be useful, but
12: WITHOUT ANY WARRANTY; without even the implied warranty of
13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: General Public License for more details.
15:
16: You should have received a copy of the GNU General Public License
17: along with GNU Zebra; see the file COPYING. If not, write to the
18: Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19: Boston, MA 02111-1307, USA. */
20:
21: #include <zebra.h>
22:
23: #include "memory.h"
24: #include "pqueue.h"
25:
26: /* priority queue using heap sort */
27:
28: /* pqueue->cmp() controls the order of sorting (i.e, ascending or
29: descending). If you want the left node to move upper of the heap
30: binary tree, make cmp() to return less than 0. for example, if cmp
31: (10, 20) returns -1, the sorting is ascending order. if cmp (10,
32: 20) returns 1, the sorting is descending order. if cmp (10, 20)
33: returns 0, this library does not do sorting (which will not be what
34: you want). To be brief, if the contents of cmp_func (left, right)
35: is left - right, dequeue () returns the smallest node. Otherwise
36: (if the contents is right - left), dequeue () returns the largest
37: node. */
38:
39: #define DATA_SIZE (sizeof (void *))
40: #define PARENT_OF(x) ((x - 1) / 2)
41: #define LEFT_OF(x) (2 * x + 1)
42: #define RIGHT_OF(x) (2 * x + 2)
43: #define HAVE_CHILD(x,q) (x < (q)->size / 2)
44:
45: void
46: trickle_up (int index, struct pqueue *queue)
47: {
48: void *tmp;
49:
50: /* Save current node as tmp node. */
51: tmp = queue->array[index];
52:
53: /* Continue until the node reaches top or the place where the parent
54: node should be upper than the tmp node. */
55: while (index > 0 &&
56: (*queue->cmp) (tmp, queue->array[PARENT_OF (index)]) < 0)
57: {
58: /* actually trickle up */
59: queue->array[index] = queue->array[PARENT_OF (index)];
60: if (queue->update != NULL)
61: (*queue->update) (queue->array[index], index);
62: index = PARENT_OF (index);
63: }
64:
65: /* Restore the tmp node to appropriate place. */
66: queue->array[index] = tmp;
67: if (queue->update != NULL)
68: (*queue->update) (tmp, index);
69: }
70:
71: void
72: trickle_down (int index, struct pqueue *queue)
73: {
74: void *tmp;
75: int which;
76:
77: /* Save current node as tmp node. */
78: tmp = queue->array[index];
79:
80: /* Continue until the node have at least one (left) child. */
81: while (HAVE_CHILD (index, queue))
82: {
83: /* If right child exists, and if the right child is more proper
84: to be moved upper. */
85: if (RIGHT_OF (index) < queue->size &&
86: (*queue->cmp) (queue->array[LEFT_OF (index)],
87: queue->array[RIGHT_OF (index)]) > 0)
88: which = RIGHT_OF (index);
89: else
90: which = LEFT_OF (index);
91:
92: /* If the tmp node should be upper than the child, break. */
93: if ((*queue->cmp) (queue->array[which], tmp) > 0)
94: break;
95:
96: /* Actually trickle down the tmp node. */
97: queue->array[index] = queue->array[which];
98: if (queue->update != NULL)
99: (*queue->update) (queue->array[index], index);
100: index = which;
101: }
102:
103: /* Restore the tmp node to appropriate place. */
104: queue->array[index] = tmp;
105: if (queue->update != NULL)
106: (*queue->update) (tmp, index);
107: }
108:
109: struct pqueue *
110: pqueue_create (void)
111: {
112: struct pqueue *queue;
113:
114: queue = XCALLOC (MTYPE_PQUEUE, sizeof (struct pqueue));
115:
116: queue->array = XCALLOC (MTYPE_PQUEUE_DATA,
117: DATA_SIZE * PQUEUE_INIT_ARRAYSIZE);
118: queue->array_size = PQUEUE_INIT_ARRAYSIZE;
119:
120: /* By default we want nothing to happen when a node changes. */
121: queue->update = NULL;
122: return queue;
123: }
124:
125: void
126: pqueue_delete (struct pqueue *queue)
127: {
128: XFREE (MTYPE_PQUEUE_DATA, queue->array);
129: XFREE (MTYPE_PQUEUE, queue);
130: }
131:
132: static int
133: pqueue_expand (struct pqueue *queue)
134: {
135: void **newarray;
136:
137: newarray = XCALLOC (MTYPE_PQUEUE_DATA, queue->array_size * DATA_SIZE * 2);
138: if (newarray == NULL)
139: return 0;
140:
141: memcpy (newarray, queue->array, queue->array_size * DATA_SIZE);
142:
143: XFREE (MTYPE_PQUEUE_DATA, queue->array);
144: queue->array = newarray;
145: queue->array_size *= 2;
146:
147: return 1;
148: }
149:
150: void
151: pqueue_enqueue (void *data, struct pqueue *queue)
152: {
153: if (queue->size + 2 >= queue->array_size && ! pqueue_expand (queue))
154: return;
155:
156: queue->array[queue->size] = data;
157: if (queue->update != NULL)
158: (*queue->update) (data, queue->size);
159: trickle_up (queue->size, queue);
160: queue->size ++;
161: }
162:
163: void *
164: pqueue_dequeue (struct pqueue *queue)
165: {
166: void *data = queue->array[0];
167: queue->array[0] = queue->array[--queue->size];
168: trickle_down (0, queue);
169: return data;
170: }
1.1.1.2 ! misho 171:
! 172: void
! 173: pqueue_remove_at (int index, struct pqueue *queue)
! 174: {
! 175: queue->array[index] = queue->array[--queue->size];
! 176:
! 177: if (index > 0
! 178: && (*queue->cmp) (queue->array[index],
! 179: queue->array[PARENT_OF(index)]) < 0)
! 180: {
! 181: trickle_up (index, queue);
! 182: }
! 183: else
! 184: {
! 185: trickle_down (index, queue);
! 186: }
! 187: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>