123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- /*************************************************************************
- * Copyright (c) 2011 AT&T Intellectual Property
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * https://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors: Details at https://graphviz.org
- *************************************************************************/
- #include <stdio.h>
- #include <util/alloc.h>
- /* Priority queue:
- * To work, the following have to be defined before this file is
- * included:
- * - PQTYPE : type of object stored in the queue
- * - PQVTYPE : type of priority value
- * - N_VAL(pq,n) : macro for (negative) priority value of object n in pq
- * - N_IDX(pq,n) : macro for integer index > 0 of n in pq
- * - guard, type PQTYPE, with N_VAL(guard) == 0
- *
- * Priorities are stored as negative numbers, with the item with the least
- * negative priority at the head (just after the guard).
- */
- #ifdef PQ_TYPES
- typedef struct {
- PQTYPE* pq;
- int PQcnt;
- int PQsize;
- } PQ;
- #endif
- #ifdef PQ_CODE
- static void
- PQgen(PQ* pq, int sz, PQTYPE guard)
- {
- pq->pq = gv_calloc(sz + 1, sizeof(PQTYPE));
- pq->pq[0] = guard;
- pq->PQsize = sz;
- pq->PQcnt = 0;
- }
- static void
- PQfree(PQ* pq, int freeAll)
- {
- free (pq->pq);
- if (freeAll) free (pq);
- }
- static void
- PQinit(PQ* pq)
- {
- pq->PQcnt = 0;
- }
- #ifdef PQCHECK
- static int
- PQcheck (PQ* pq)
- {
- int i;
-
- for (i = 1; i <= pq->PQcnt; i++) {
- if (N_IDX(pq,pq->pq[i]) != i) {
- return 1;
- }
- }
- return 0;
- }
- #endif
- static void
- PQupheap(PQ* ppq, int k)
- {
- PQTYPE* pq = ppq->pq;
- PQTYPE x = pq[k];
- PQVTYPE v = N_VAL(ppq,x);
- int next = k/2;
- PQTYPE n;
-
- while (N_VAL(ppq,n = pq[next]) < v) {
- pq[k] = n;
- N_IDX(ppq,n) = k;
- k = next;
- next /= 2;
- }
- pq[k] = x;
- N_IDX(ppq,x) = k;
- }
- static int
- PQinsert(PQ* pq, PQTYPE np)
- {
- if (pq->PQcnt == pq->PQsize) {
- agerrorf("Heap overflow\n");
- return (1);
- }
- pq->PQcnt++;
- pq->pq[pq->PQcnt] = np;
- PQupheap (pq, pq->PQcnt);
- #ifdef PQCHECK
- PQcheck(pq);
- #endif
- return 0;
- }
- static void
- PQdownheap (PQ* ppq, int k)
- {
- PQTYPE* pq = ppq->pq;
- PQTYPE x = pq[k];
- PQVTYPE v = N_VAL(ppq,x);
- int lim = ppq->PQcnt/2;
- PQTYPE n;
- int j;
- while (k <= lim) {
- j = k+k;
- n = pq[j];
- if (j < ppq->PQcnt) {
- if (N_VAL(ppq,n) < N_VAL(ppq,pq[j+1])) {
- j++;
- n = pq[j];
- }
- }
- if (v >= N_VAL(ppq,n)) break;
- pq[k] = n;
- N_IDX(ppq,n) = k;
- k = j;
- }
- pq[k] = x;
- N_IDX(ppq,x) = k;
- }
- static PQTYPE
- PQremove (PQ* pq)
- {
- PQTYPE n;
- if (pq->PQcnt) {
- n = pq->pq[1];
- pq->pq[1] = pq->pq[pq->PQcnt];
- pq->PQcnt--;
- if (pq->PQcnt) PQdownheap (pq, 1);
- #ifdef PQCHECK
- PQcheck(pq);
- #endif
- return n;
- }
- else return pq->pq[0];
- }
- static void
- PQupdate (PQ* pq, PQTYPE n, PQVTYPE d)
- {
- N_VAL(pq,n) = d;
- PQupheap (pq, N_IDX(pq,n));
- #ifdef PQCHECK
- PQcheck(pq);
- #endif
- }
- #if defined(DEBUG) && DEBUG > 1
- static void
- PQprint (PQ* pq)
- {
- int i;
- PQTYPE n;
- fprintf (stderr, "Q: ");
- for (i = 1; i <= pq->PQcnt; i++) {
- n = pq->pq[i];
- fprintf (stderr, "(%d:%f) ", N_IDX(pq,n), N_VAL(pq,n));
- }
- fprintf (stderr, "\n");
- }
- #endif
- #endif
|