HW04
Source codes for forth assignment
graph.c
Go to the documentation of this file.
1 /**
2  * Functions for creating and accessing graph.
3  *
4  * This file contains definitions of graph and node types and functions
5  * designed to work with these types.
6  *
7  * @file graph.c
8  * @author Lubomir Sedlar
9  */
10 #include "graph.h"
11 #include "graph-private.h"
12 
13 #include <assert.h>
14 #include <stdlib.h>
15 #include <string.h>
16 
17 /** Structure representing graph. */
18 struct graph {
19  size_t size;
20  size_t used;
21  Node **nodes;
22  bool sorted;
23 };
24 
25 unsigned int node_get_id(Node *n)
26 {
27  assert(n);
28  return n->id;
29 }
30 
31 unsigned short node_get_n_outgoing(Node *n)
32 {
33  assert(n);
34  return n->edges_num;
35 }
36 
37 struct edge * node_get_edges(Node *n)
38 {
39  assert(n);
40  return n->edges;
41 }
42 
43 unsigned int node_get_distance(Node *n)
44 {
45  assert(n);
46  return n->dist;
47 }
48 
50 {
51  assert(n);
52  return n->previous;
53 }
54 
55 /** Default size of nodes array */
56 static const int NODES_DEFAULT_SIZE = 128;
57 /** Default size of edges array in each node */
58 static const int EDGES_DEFAULT_SIZE = 8;
59 
61 {
62  Graph *g = malloc(sizeof *g);
63  if (!g) return NULL;
64  g->size = NODES_DEFAULT_SIZE;
65  g->used = 0;
66  g->nodes = calloc(g->size, sizeof *g->nodes);
67  if (!g->nodes) {
68  g->size = 0;
69  free(g);
70  return NULL;
71  }
72  return g;
73 }
74 
75 bool graph_insert_node(Graph *g, unsigned int id)
76 {
77  if (!g) return false;
78  if (g->used >= g->size) {
79  Node **tmp = realloc(g->nodes, g->size * 2 * sizeof *g->nodes);
80  if(!tmp) return false;
81  g->size *= 2;
82  g->nodes = tmp;
83  }
84 
85  g->nodes[g->used] = malloc(sizeof **g->nodes);
86  if (!g->nodes[g->used]) return false;
87 
88  Node *n = g->nodes[g->used];
89  n->id = id;
90  n->edges_num = 0;
91  n->edges_size = EDGES_DEFAULT_SIZE;
92  n->edges = calloc(n->edges_size, sizeof(struct edge));
93 
94  if (!n->edges) {
95  free(n);
96  return false;
97  }
98  g->used++;
99  g->sorted = false;
100  return true;
101 }
102 
103 bool graph_insert_edge(Graph *g, unsigned int source, unsigned int dest,
104  int mindelay)
105 {
106  if (!g) return false;
107  Node *from = graph_get_node(g, source);
108  Node *to = graph_get_node(g, dest);
109  if (!from || !to) return false;
110 
111  if (from->edges_num >= from->edges_size) {
112  struct edge *tmp = realloc(from->edges,
113  from->edges_size * 2 * sizeof *tmp);
114  if (!tmp) return false;
115  from->edges = tmp;
116  from->edges_size *= 2;
117  }
118 
119  struct edge *edge = &from->edges[from->edges_num++];
120  edge->destination = to;
121  edge->mindelay = mindelay;
122  return true;
123 }
124 
125 static int node_compare(const void *a, const void *b)
126 {
127  const Node *n1 = *(Node **) a;
128  const Node *n2 = *(Node **) b;
129  return n1->id - n2->id;
130 }
131 
132 Node * graph_get_node(Graph *g, unsigned int id)
133 {
134  if (!g) return false;
135  /* Sort the array if necessary. */
136  if (!g->sorted) {
137  qsort(g->nodes, g->used, sizeof *g->nodes, node_compare);
138  g->sorted = true;
139  }
140  size_t low = 0; /* Lowest index that can hold the value. */
141  size_t high = g->used; /* Lowest index that is known to have too high
142  value. These indices specify a halfopen
143  interval of form [low,high). */
144  while (high > low) { /* Stop when there are no indices that can
145  have wanted value. */
146  size_t mid = (low + high) / 2; /* Pick middle value. */
147  /* Hit! return found node. */
148  if (id == g->nodes[mid]->id) {
149  return g->nodes[mid];
150  /* Middle is still to big, therefore it is new high limit. */
151  } else if (id < g->nodes[mid]->id) {
152  high = mid;
153  /* Middle is too small, so low limit is mid + 1. */
154  } else {
155  low = mid + 1;
156  }
157  }
158  return NULL; /* Not found. */
159 }
160 
161 /**
162  * Free a single node.
163  * This is a private function that should not be called from outside this
164  * module.
165  *
166  * @param node node to be freed
167  */
168 static void node_free(Node *node)
169 {
170  if (node) {
171  free(node->edges);
172  }
173  free(node);
174 }
175 
177 {
178  if (g) {
179  for (size_t i = 0; i < g->used; ++i) {
180  node_free(g->nodes[i]);
181  }
182  free(g->nodes);
183  free(g);
184  }
185 }
186 
187 Node **graph_dup_data(Graph *g, size_t *len)
188 {
189  if (!g || !len) return NULL;
190  *len = g->used;
191  Node **arr = malloc(*len * sizeof *arr);
192  return arr ? memcpy(arr, g->nodes, *len * sizeof *arr) : NULL;
193 }
Node * destination
Pointer to destination node of this edge.
Definition: graph.h:35
unsigned int node_get_distance(Node *n)
Get distance of this node from starting node.
Definition: graph.c:43
Representation of an edge.
Definition: graph.h:33
Node * graph_get_node(Graph *g, unsigned int id)
Retrieve a node.
Definition: graph.c:132
struct node Node
Node is an opaque type.
Definition: graph.h:19
bool graph_insert_edge(Graph *g, unsigned int source, unsigned int dest, int mindelay)
Insert an edge into the graph.
Definition: graph.c:103
int mindelay
Minimum delay of this edge.
Definition: graph.h:37
void graph_free(Graph *g)
Free memory used by nodes and edges.
Definition: graph.c:176
unsigned short node_get_n_outgoing(Node *n)
Get number of outgoing edges from a node.
Definition: graph.c:31
Graph * graph_new(void)
Create a new graph.
Definition: graph.c:60
Node * node_get_previous(Node *n)
Get node on (already found) shortest path from which queried node was visited.
Definition: graph.c:49
bool graph_insert_node(Graph *g, unsigned int id)
Insert node into the graph.
Definition: graph.c:75
Interface for creating graph.
struct edge * node_get_edges(Node *n)
Get array of outgoing edges.
Definition: graph.c:37
struct graph Graph
Graph is an opaque type.
Definition: graph.h:25
unsigned int node_get_id(Node *n)
Get id of a node.
Definition: graph.c:25