eg_edgraph.h

Go to the documentation of this file.
00001 /* EGlib "Efficient General Library" provides some basic structures and
00002  * algorithms commons in many optimization algorithms.
00003  *
00004  * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
00005  * 
00006  * This library is free software; you can redistribute it and/or modify it
00007  * under the terms of the GNU Lesser General Public License as published by the
00008  * Free Software Foundation; either version 2.1 of the License, or (at your
00009  * option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful, but 
00012  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
00013  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
00014  * License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public License
00017  * along with this library; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
00019  * */
00020 /* ========================================================================= */
00021 /** @defgroup EGeDgraph EGeDgraph
00022  * Here we define a basic directed graph structure, it holds the number of
00023  * nodes and edges in the graph, as well as the in and out degree of all
00024  * nodes, and allow to access the head and tail of any edge. The spirit of this
00025  * implementation is to use embeded sub-structures rather than pointers to
00026  * sub-structures, much in the spirit of the Linux Kernel List implementation.
00027  * Wether this will help in running time is hard to say, but at least now we
00028  * have two implementations (EGdGraph_t) one with embeded structures and one
00029  * with pointer to sub-structures.
00030  *
00031  * @version 0.0.1
00032  * @par History:
00033  * - 2005-05-23
00034  *            - First Implementation.
00035  *
00036  * */
00037 /** @file 
00038  * @ingroup EGeDgraph */
00039 /** @addtogroup EGeDgraph */
00040 /** @{ */
00041 /** @example eg_edgraph.ex.c
00042  * This is a more detailed example on how to use this module */
00043 /* ========================================================================= */
00044 
00045 #ifndef _EG_E_DGRAPH_H
00046 #define _EG_E_DGRAPH_H
00047 #include <stdio.h>
00048 #include <limits.h>
00049 #include <stddef.h>
00050 #include "eg_elist.h"
00051 
00052 /* ========================================================================= */
00053 /** @brief structure that hold all node related structures needed to define a
00054  * graph, and add/delete/modify it's structure */
00055 typedef struct EGeDgraphNode_t
00056 {
00057   EGeList_t in_edge;  /**< List head for a list of incomming edges */
00058   EGeList_t out_edge; /**< List head for a list of outgoing edges */
00059   EGeList_t node_cn;  /**< List member of the list of all nodes in the graph, 
00060                            note that if this node is not (YET) in a graph, 
00061                            the contents are undefined */
00062   unsigned in_size;   /**< Number of incomming edges */
00063   unsigned out_size;  /**< Number of outgoing edges */
00064 }
00065 EGeDgraphNode_t;
00066 
00067 /* ========================================================================= */
00068 /** @brief structure that hold all edge related structures needed to define a
00069  * directed graph, and add/delete/modify it's structure */
00070 typedef struct EGeDgraphEdge_t
00071 {
00072   EGeList_t head_cn;    /**< List member of the incomming edge list in the 
00073                              head node for this edge. */
00074   EGeList_t tail_cn;    /**< List member of the outgoing edge list in the 
00075                              tail node for this edge. */
00076   EGeDgraphNode_t *head;/**< pointer to the head node for this edge */
00077   EGeDgraphNode_t *tail;/**< pointer to the tail node for this edge */
00078 }
00079 EGeDgraphEdge_t;
00080 
00081 /* ========================================================================= */
00082 /** @brief structure that holds all graph related structures needed to define
00083  * a directed graph, and to allow modifications over it. */
00084 typedef struct EGeDgraph_t
00085 {
00086   EGeList_t nodes;  /**< List head for all nodes in the graph */
00087   unsigned n_nodes; /**< number of nodes in the graph */
00088   unsigned n_edges; /**< number of edges in the graph */
00089 }
00090 EGeDgraph_t;
00091 
00092 /* ========================================================================= */
00093 /** @brief Initialize a graph structure as an empty graph with no members.
00094  * @param G pointer to the graph to be initialized */
00095 #define EGeDgraphInit(G) ({\
00096   EGeDgraph_t*const __EGeDg_in_G = (G);\
00097   EGeListInit(&(__EGeDg_in_G->nodes));\
00098   __EGeDg_in_G->n_edges = __EGeDg_in_G->n_nodes = 0;})
00099 
00100 /* ========================================================================= */
00101 /** @brief Reset the given graph pointer as an empty graph.
00102  * @param graph_pt pointer to the graph to reset */
00103 #define EGeDgraphReset(graph_pt) EGeDgraphInit(graph_pt)
00104 
00105 /* ========================================================================= */
00106 /** @brief Clear the structure so that we can free it (without memory leaks).
00107  * Note that this macro does nothing, because it is always safe to free this
00108  * structure */
00109 #define EGeDgraphClear(G) ;
00110 
00111 /* ========================================================================= */
00112 /** @brief Initialize an edge as an empty edge, non attached to any graph.
00113  * @param e pointer to edge be initialized */
00114 #define EGeDgraphEdgeInit(e) ({\
00115   EGeDgraphEdge_t*const __EGeDg_in_e = (e);\
00116   __EGeDg_in_e->head_cn = (EGeList_t){0,0};\
00117   __EGeDg_in_e->tail_cn = (EGeList_t){0,0};\
00118   __EGeDg_in_e->head = __EGeDg_in_e->tail = 0;})
00119 
00120 /* ========================================================================= */
00121 /** @brief Reset the given edge pointer as an edge not linked to a graph.
00122  * @param edge_pt pointer to the edge to reset */
00123 #define EGeDgraphEdgeReset(edge_pt) EGeDgraphEdgeInit(edge_pt)
00124 
00125 /* ========================================================================= */
00126 /** @brief Clear the structure so that we can free it (without memory leaks).
00127  * Note that this macro does nothing, because it is always safe to free this
00128  * structure */
00129 #define EGeDgraphEdgeClear(G) ;
00130 
00131 /* ========================================================================= */
00132 /** @brief Initialize a node as an empty non-attached node.
00133  * @param v pointer to node to be initialized */
00134 #define EGeDgraphNodeInit(v) ({\
00135   EGeDgraphNode_t*const __EGeDg_in_v = (v);\
00136   EGeListInit(&(__EGeDg_in_v->in_edge));\
00137   EGeListInit(&(__EGeDg_in_v->out_edge));\
00138   __EGeDg_in_v->node_cn = (EGeList_t){0,0};\
00139   __EGeDg_in_v->in_size = __EGeDg_in_v->out_size = 0;})
00140 
00141 /* ========================================================================= */
00142 /** @brief Reset the given node pointer as a node not linked to a graph.
00143  * @param node_pt pointer to the node to reset */
00144 #define EGeDgraphNodeReset(node_pt) EGeDgraphNodeInit(node_pt)
00145 
00146 /* ========================================================================= */
00147 /** @brief Clear the structure so that we can free it (without memory leaks).
00148  * Note that this macro does nothing, because it is always safe to free this
00149  * structure */
00150 #define EGeDgraphNodeClear(G)
00151 
00152 /* ========================================================================= */
00153 /** @brief Add a node to the graph.
00154  * @param G pointer to the graph to where we will add a node, it should be an
00155  * initialized graph structure (see EGeDgraphInit).
00156  * @param v pointer to the node to be added to the graph. Note that we don't
00157  * check wether the node has valid information inside (you should call
00158  * EGeDgraphNodeInit(v) for all nodes before adding them.
00159  * @return the number of nodes in the graph (including the recently added
00160  * node).
00161  * */
00162 #define EGeDgraphAddNode(G,v) ({\
00163   EGeDgraph_t*const __EGeDg_add_n_G = (G);\
00164   EGeDgraphNode_t*const __EGeDg_add_n_v = (v);\
00165   EGeListAddAfter(&(__EGeDg_add_n_v->node_cn),&(__EGeDg_add_n_G->nodes));\
00166   __EGeDg_add_n_G->n_nodes++;})
00167 
00168 /* ========================================================================= */
00169 /** @brief Remove a node from a graph.
00170  * @param v pointer to the node to be removed from the graph.
00171  * @param G pointer to the graph from where we will remove the node.
00172  * @return pointer to the removed node.
00173  * @note Note that the actual definition of removing a node from a graph is
00174  * not completelly well defined, since there might be some edges attached to
00175  * this node, and is not clear what to do in such a case. In this
00176  * implementation we chose to return an error if the degree of this node is
00177  * non-zero. */
00178 #define EGeDgraphDelNode(G,v) ({\
00179   EGeDgraph_t*const __EGeDg_del_n_G = (G);\
00180   EGeDgraphNode_t*const __EGeDg_del_n = (v);\
00181   if(__EGeDg_del_n->in_size) EXIT(1,"trying to remove node "#v" with "\
00182     "incoming edges from graph "#G);\
00183   if(__EGeDg_del_n->out_size) EXIT(1,"trying to remove node "#v" with "\
00184     "outgoing edges from graph "#G);\
00185   EGeListDel(&(__EGeDg_del_n->node_cn));\
00186   __EGeDg_del_n_G->n_nodes--;\
00187   __EGeDg_del_n;})
00188 
00189 /* ========================================================================= */
00190 /** @brief Add an edge to a graph.
00191  * @param G pointer to the graph.
00192  * @param head_pt pointer to the head node.
00193  * @param tail_pt pointer to the tail node.
00194  * @param e pointer to the edge.
00195  * */
00196 #define EGeDgraphAddEdge(G,head_pt,tail_pt,e) ({\
00197   EGeDgraph_t*const __EGeDg_add_e_G = (G);\
00198   EGeDgraphNode_t*const __EGeDg_add_e_head = (head_pt);\
00199   EGeDgraphNode_t*const __EGeDg_add_e_tail = (tail_pt);\
00200   EGeDgraphEdge_t*const __EGeDg_add_e = (e);\
00201   EGeListAddAfter(&(__EGeDg_add_e->head_cn),&(__EGeDg_add_e_head->in_edge));\
00202   EGeListAddAfter(&(__EGeDg_add_e->tail_cn),&(__EGeDg_add_e_tail->out_edge));\
00203   __EGeDg_add_e->head = __EGeDg_add_e_head;\
00204   __EGeDg_add_e->tail = __EGeDg_add_e_tail;\
00205   __EGeDg_add_e_head->in_size++;\
00206   __EGeDg_add_e_tail->out_size++;\
00207   __EGeDg_add_e_G->n_edges++;})
00208 
00209 /* ========================================================================= */
00210 /** @brief Delete an edge from a graph.
00211  * @param G pointer to the graph.
00212  * @param e pointer to the edge.
00213  * @return pointer to the deleted edge.
00214  * @note Take notice that this function won't change the values stored in the
00215  * given edge 'e', so if you access the internal information it may or may not
00216  * be still valid, (depending on what else has happen with the graph in the
00217  * meantime).
00218  * */
00219 #define EGeDgraphDelEdge(G,e) ({\
00220   EGeDgraph_t*const __EGeDg_del_e_G = (G);\
00221   EGeDgraphEdge_t*const __EGeDg_del_e = (e);\
00222   EGeListDel(&(__EGeDg_del_e->head_cn));\
00223   EGeListDel(&(__EGeDg_del_e->tail_cn));\
00224   __EGeDg_del_e->head->in_size--;\
00225   __EGeDg_del_e->tail->out_size--;\
00226   __EGeDg_del_e_G->n_edges--;\
00227   __EGeDg_del_e;})
00228 
00229 /* ========================================================================= */
00230 /** @brief Change the tail of an edge.
00231  * @param e pointer to the edge whose tail will be changed.
00232  * @param G pointer to the graph.
00233  * @param tail_pt pointer to the new edge's tail.
00234  * @return pointer to the new tail of the given edge.
00235  * @par Description:
00236  * Note that this function assumes that  that
00237  * both (e) and (tail_pt) bellong to an initialized graph. */
00238 #define EGeDgraphChangeTail(G,e,tail_pt) ({\
00239   EGeDgraphNode_t*const __EGeDg_chg_hd_tail = (tail_pt);\
00240   EGeDgraphEdge_t*const __EGeDg_chg_hd_e = (e);\
00241   __EGeDg_chg_hd_e->tail->out_size--;\
00242   EGeListDel(&(__EGeDg_chg_hd_e->tail_cn));\
00243   EGeListAddAfter(&(__EGeDg_chg_hd_e->tail_cn),&(__EGeDg_chg_hd_tail->out_edge));\
00244   __EGeDg_chg_hd_tail->out_size++;\
00245   __EGeDg_chg_hd_e->tail = __EGeDg_chg_hd_tail;})
00246 
00247 /* ========================================================================= */
00248 /** @brief Change the head of an edge.
00249  * @param e pointer to the edge whose head will be changed.
00250  * @param head_pt pointer to the new edge's head.
00251  * @param G pointer to the graph.
00252  * @return pointer to the new head of the given edge.
00253  * @par Description:
00254  * Note that this function assumes that  that
00255  * both (e) and (head_pt) bellong to an initialized graph. */
00256 #define EGeDgraphChangeHead(G,e,head_pt) ({\
00257   EGeDgraphNode_t*const __EGeDg_chg_hd_head = (head_pt);\
00258   EGeDgraphEdge_t*const __EGeDg_chg_hd_e = (e);\
00259   __EGeDg_chg_hd_e->head->in_size--;\
00260   EGeListDel(&(__EGeDg_chg_hd_e->head_cn));\
00261   EGeListAddAfter(&(__EGeDg_chg_hd_e->head_cn),&(__EGeDg_chg_hd_head->in_edge));\
00262   __EGeDg_chg_hd_head->in_size++;\
00263   __EGeDg_chg_hd_e->head = __EGeDg_chg_hd_head;})
00264 
00265 /* ========================================================================= */
00266 /** @} */
00267 /* end of eg_edgraph.h */
00268 #endif

Generated on Mon Jan 30 08:48:53 2006 for EGlib by  doxygen 1.4.5