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
1.4.5