Graphviz 2.29.20120208.0545
lib/circogen/deglist.c
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 
00015 #include <deglist.h>
00016 #include <circular.h>
00017 #include <blockpath.h>
00018 #include <assert.h>
00019 
00020 typedef struct {
00021     Dtlink_t link;
00022     int deg;
00023     Agnode_t *np;               /* linked list of nodes of same degree */
00024 } degitem;
00025 
00026 static degitem *mkItem(Dt_t * d, degitem * obj, Dtdisc_t * disc)
00027 {
00028     degitem *ap = GNEW(degitem);
00029 
00030     ap->np = NULL;
00031     ap->deg = obj->deg;
00032     return ap;
00033 }
00034 
00035 static void freeItem(Dt_t * d, degitem * obj, Dtdisc_t * disc)
00036 {
00037     free(obj);
00038 }
00039 
00040 static int cmpDegree(Dt_t * d, int *key1, int *key2, Dtdisc_t * disc)
00041 {
00042     if (*key1 < *key2)
00043         return -1;
00044     else if (*key1 > *key2)
00045         return 1;
00046     else
00047         return 0;
00048 }
00049 
00050 static Dtdisc_t nodeDisc = {
00051     offsetof(degitem, deg),     /* key */
00052     sizeof(int),                /* size */
00053     offsetof(degitem, link),    /* link */
00054     (Dtmake_f) mkItem,
00055     (Dtfree_f) freeItem,
00056     (Dtcompar_f) cmpDegree,
00057     (Dthash_f) 0,
00058     (Dtmemory_f) 0,
00059     (Dtevent_f) 0
00060 };
00061 
00062 /* mkDeglist:
00063  * Create an empty list of nodes.
00064  */
00065 deglist_t *mkDeglist(void)
00066 {
00067     deglist_t *s = dtopen(&nodeDisc, Dtoset);
00068     return s;
00069 }
00070 
00071 /* freeDeglist:
00072  * Delete the node list.
00073  * Nodes are not deleted.
00074  */
00075 void freeDeglist(deglist_t * s)
00076 {
00077     dtclose(s);
00078 }
00079 
00080 /* insertDeglist:
00081  * Add a node to the node list.
00082  * Nodes are kept sorted by DEGREE, smallest degrees first.
00083  */
00084 void insertDeglist(deglist_t * ns, Agnode_t * n)
00085 {
00086     degitem key;
00087     degitem *kp;
00088 
00089     key.deg = DEGREE(n);
00090     kp = dtinsert(ns, &key);
00091     ND_next(n) = kp->np;
00092     kp->np = n;
00093 }
00094 
00095 /* removeDeglist:
00096  * Remove n from list, if it is in the list.
00097  */
00098 void removeDeglist(deglist_t * list, Agnode_t * n)
00099 {
00100     degitem key;
00101     degitem *ip;
00102     Agnode_t *np;
00103     Agnode_t *prev;
00104 
00105     key.deg = DEGREE(n);
00106     ip = (degitem *) dtsearch(list, &key);
00107     assert(ip);
00108     if (ip->np == n) {
00109         ip->np = ND_next(n);
00110         if (ip->np == NULL)
00111             dtdelete(list, ip);
00112     } else {
00113         prev = ip->np;
00114         np = ND_next(prev);
00115         while (np && (np != n)) {
00116             prev = np;
00117             np = ND_next(np);
00118         }
00119         if (np)
00120             ND_next(prev) = ND_next(np);
00121     }
00122 }
00123 
00124 /* firstDeglist:
00125  * Return the first node in the list (smallest degree)
00126  * Remove from list.
00127  * If the list is empty, return NULL
00128  */
00129 Agnode_t *firstDeglist(deglist_t * list)
00130 {
00131     degitem *ip;
00132     Agnode_t *np;
00133 
00134     ip = (degitem *) dtfirst(list);
00135     if (ip) {
00136         np = ip->np;
00137         ip->np = ND_next(np);
00138         if (ip->np == NULL)
00139             dtdelete(list, ip);
00140         return np;
00141     } else
00142         return 0;
00143 }
00144 
00145 #ifdef DEBUG
00146 void printDeglist(deglist_t * dl)
00147 {
00148     degitem *ip;
00149     node_t *np;
00150     fprintf(stderr, " dl:\n");
00151     for (ip = (degitem *) dtfirst(dl); ip; ip = (degitem *) dtnext(dl, ip)) {
00152         np = ip->np;
00153         if (np)
00154             fprintf(stderr, " (%d)", ip->deg);
00155         for (; np; np = ND_next(np)) {
00156             fprintf(stderr, " %s", np->name);
00157         }
00158         fprintf(stderr, "\n");
00159     }
00160 
00161 }
00162 #endif