Graphviz  2.29.20120523.0446
lib/neatogen/fPQ.h
Go to the documentation of this file.
00001 /* $Id$Revision: */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /*************************************************************************
00005  * Copyright (c) 2011 AT&T Intellectual Property 
00006  * All rights reserved. This program and the accompanying materials
00007  * are made available under the terms of the Eclipse Public License v1.0
00008  * which accompanies this distribution, and is available at
00009  * http://www.eclipse.org/legal/epl-v10.html
00010  *
00011  * Contributors: See CVS logs. Details at http://www.graphviz.org/
00012  *************************************************************************/
00013 
00014 #include <memory.h>
00015 #include <stdio.h>
00016 
00017 /* Priority queue:
00018  * To work, the following have to be defined before this file is
00019  * included:
00020  *   - PQTYPE   : type of object stored in the queue
00021  *   - PQVTYPE  : type of priority value
00022  *   - N_VAL(pq,n) : macro for (negative) priority value of object n in pq
00023  *   - N_IDX(pq,n) : macro for integer index > 0 of n in pq
00024  *   - guard, type PQTYPE, with N_VAL(guard) == 0
00025  *
00026  * Priorities are stored as negative numbers, with the item with the least
00027  * negative priority at the head (just after the guard).
00028  */
00029 
00030 #ifdef PQ_TYPES
00031 typedef struct {
00032     PQTYPE*  pq;
00033     int     PQcnt;
00034     int     PQsize;
00035 } PQ;
00036 #endif
00037 
00038 #ifdef PQ_CODE
00039 static void
00040 PQgen(PQ* pq, int sz, PQTYPE guard)
00041 {
00042     pq->pq = N_NEW(sz+1,PQTYPE);
00043     pq->pq[0] = guard;
00044     pq->PQsize = sz;
00045     pq->PQcnt = 0;
00046 }
00047 
00048 static void
00049 PQfree(PQ* pq, int freeAll)
00050 {
00051     free (pq->pq);
00052     if (freeAll) free (pq);
00053 }
00054 
00055 static void
00056 PQinit(PQ* pq)
00057 {
00058     pq->PQcnt = 0;
00059 }
00060 
00061 #ifdef PQCHECK
00062 static int
00063 PQcheck (PQ* pq)
00064 {
00065     int i;
00066  
00067     for (i = 1; i <= pq->PQcnt; i++) {
00068         if (N_IDX(pq,pq->pq[i]) != i) {
00069             return 1;
00070         }
00071     }
00072     return 0;
00073 }
00074 #endif
00075 
00076 static void
00077 PQupheap(PQ* ppq, int k)
00078 {
00079     PQTYPE* pq = ppq->pq;
00080     PQTYPE x = pq[k];
00081     PQVTYPE v = N_VAL(ppq,x);
00082     int  next = k/2;
00083     PQTYPE  n;
00084     
00085     while (N_VAL(ppq,n = pq[next]) < v) {
00086         pq[k] = n;
00087         N_IDX(ppq,n) = k;
00088         k = next;
00089         next /= 2;
00090     }
00091     pq[k] = x;
00092     N_IDX(ppq,x) = k;
00093 }
00094 
00095 static int
00096 PQinsert(PQ* pq, PQTYPE np)
00097 {
00098     if (pq->PQcnt == pq->PQsize) {
00099         agerr (AGERR, "Heap overflow\n");
00100         return (1);
00101     }
00102     pq->PQcnt++;
00103     pq->pq[pq->PQcnt] = np;
00104     PQupheap (pq, pq->PQcnt);
00105 #ifdef PQCHECK
00106     PQcheck(pq);
00107 #endif
00108     return 0;
00109 }
00110 
00111 static void
00112 PQdownheap (PQ* ppq, int k)
00113 {
00114     PQTYPE*  pq = ppq->pq;
00115     PQTYPE x = pq[k];
00116     PQVTYPE v = N_VAL(ppq,x);
00117     int   lim = ppq->PQcnt/2;
00118     PQTYPE n;
00119     int    j;
00120 
00121     while (k <= lim) {
00122         j = k+k;
00123         n = pq[j];
00124         if (j < ppq->PQcnt) {
00125             if (N_VAL(ppq,n) < N_VAL(ppq,pq[j+1])) {
00126                 j++;
00127                 n = pq[j];
00128             }
00129         }
00130         if (v >= N_VAL(ppq,n)) break;
00131         pq[k] = n;
00132         N_IDX(ppq,n) = k;
00133         k = j;
00134     }
00135     pq[k] = x;
00136     N_IDX(ppq,x) = k;
00137 }
00138 
00139 static PQTYPE
00140 PQremove (PQ* pq)
00141 {
00142     PQTYPE n;
00143 
00144     if (pq->PQcnt) {
00145         n = pq->pq[1];
00146         pq->pq[1] = pq->pq[pq->PQcnt];
00147         pq->PQcnt--;
00148         if (pq->PQcnt) PQdownheap (pq, 1);
00149 #ifdef PQCHECK
00150         PQcheck(pq);
00151 #endif
00152         return n;
00153     }
00154     else return pq->pq[0];
00155 }
00156 
00157 static void
00158 PQupdate (PQ* pq, PQTYPE n, PQVTYPE d)
00159 {
00160     N_VAL(pq,n) = d;
00161     PQupheap (pq, N_IDX(pq,n));
00162 #ifdef PQCHECK
00163     PQcheck(pq);
00164 #endif
00165 }
00166 
00167 #ifdef DEBUG
00168 
00169 static void
00170 PQprint (PQ* pq)
00171 {
00172     int i;
00173     PQTYPE  n;
00174 
00175     fprintf (stderr, "Q: ");
00176     for (i = 1; i <= pq->PQcnt; i++) {
00177         n = pq->pq[i];
00178         fprintf (stderr, "(%d:%f) ", N_IDX(pq,n), N_VAL(pq,n));
00179     }
00180     fprintf (stderr, "\n");
00181 }
00182 #endif
00183 #endif
00184