~ubuntu-branches/ubuntu/precise/igraph/precise

« back to all changes in this revision

Viewing changes to src/adjlist.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathieu Malaterre
  • Date: 2009-11-16 18:12:42 UTC
  • Revision ID: james.westby@ubuntu.com-20091116181242-mzv9p5fz9uj57xd1
Tags: upstream-0.5.3
ImportĀ upstreamĀ versionĀ 0.5.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: C -*-  */
 
2
/* 
 
3
   IGraph library.
 
4
   Copyright (C) 2003, 2004, 2005  Gabor Csardi <csardi@rmki.kfki.hu>
 
5
   MTA RMKI, Konkoly-Thege Miklos st. 29-33, Budapest 1121, Hungary
 
6
   
 
7
   This program is free software; you can redistribute it and/or modify
 
8
   it under the terms of the GNU General Public License as published by
 
9
   the Free Software Foundation; either version 2 of the License, or
 
10
   (at your option) any later version.
 
11
   
 
12
   This program is distributed in the hope that it will be useful,
 
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
   GNU General Public License for more details.
 
16
   
 
17
   You should have received a copy of the GNU General Public License
 
18
   along with this program; if not, write to the Free Software
 
19
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
 
20
   02110-1301 USA
 
21
 
 
22
*/
 
23
 
 
24
#include "igraph.h"
 
25
#include "memory.h"
 
26
#include "config.h"
 
27
 
 
28
#include <string.h>   /* memset */
 
29
 
 
30
/**
 
31
 * \section about_adjlists
 
32
 * <para>Sometimes it is easier to work with a graph which is in
 
33
 * adjacency list format: a list of vectors; each vector contains the
 
34
 * neighbor vertices or adjacent edges of a given vertex. Typically,
 
35
 * this representation is good if we need to iterate over the neigbors
 
36
 * of all vertices many times. E.g. when finding the shortest paths
 
37
 * between every pairs of vertices or calculating closeness centrality
 
38
 * for all the vertices.</para>
 
39
 * 
 
40
 * <para>The <type>igraph_adjlist_t</type> stores the adjacency lists
 
41
 * of a graph. After creation it is independent of the original graph,
 
42
 * it can be modified freely with the usual vector operations, the
 
43
 * graph is not affected. E.g. the adjacency list can be used to
 
44
 * rewire the edges of a graph efficiently. If one used the
 
45
 * straightforward \ref igraph_delete_edges() and \ref
 
46
 * igraph_add_edges() combination for this that needs O(|V|+|E|) time
 
47
 * for every single deletion and insertion operation, it is thus very
 
48
 * slow if many edges are rewired. Extracting the graph into an
 
49
 * adjacency list, do all the rewiring operations on the vectors of
 
50
 * the adjacency list and then creating a new graph needs (depending
 
51
 * on how exactly the rewiring is done) typically O(|V|+|E|) time for
 
52
 * the whole rewiring process.</para>
 
53
 * 
 
54
 * <para>Lazy adjacency lists are a bit different. When creating a
 
55
 * lazy adjacency list, the neighbors of the vertices are not queried,
 
56
 * only some memory is allocated for the vectors. When \ref
 
57
 * igraph_lazy_adjlist_get() is called for vertex v the first time,
 
58
 * the neighbors of v are queried and stored in a vector of the
 
59
 * adjacency list, so they don't need to be queried again. Lazy
 
60
 * adjacency lists are handy if you have an at least linear operation
 
61
 * (because initialization is generally linear in terms of number of
 
62
 * vertices), but you don't know how many vertices you will visit
 
63
 * during the computation.
 
64
 * </para>
 
65
 * 
 
66
 */
 
67
 
 
68
/**
 
69
 * \function igraph_adjlist_init
 
70
 * Initialize an adjacency list of vertices
 
71
 * 
 
72
 * Create a list of vectors containing the neighbors of all vertices
 
73
 * in a graph. The adjacency list is independent of the graph after
 
74
 * creation, e.g. the graph can be destroyed and modified, the
 
75
 * adjacency list contains the state of the graph at the time of its
 
76
 * initialization. 
 
77
 * \param graph The input graph. 
 
78
 * \param al Pointer to an uninitialized <type>igraph_adjlist_t</type> object.
 
79
 * \param mode Constant specifying whether outgoing
 
80
 *   (<code>IGRAPH_OUT</code>), incoming (<code>IGRAPH_IN</code>),
 
81
 *   or both (<code>IGRAPH_ALL</code>) types of neighbors to include
 
82
 *   in the adjacency list. It is ignored for undirected networks.
 
83
 * \return Error code.
 
84
 * 
 
85
 * Time complexity: O(|V|+|E|), linear in the number of vertices and
 
86
 * edges.
 
87
 */
 
88
 
 
89
int igraph_adjlist_init(const igraph_t *graph, igraph_adjlist_t *al, 
 
90
                          igraph_neimode_t mode) {
 
91
  long int i;
 
92
 
 
93
  if (mode != IGRAPH_IN && mode != IGRAPH_OUT && mode != IGRAPH_ALL) {
 
94
    IGRAPH_ERROR("Cannot create adjlist view", IGRAPH_EINVMODE);
 
95
  }
 
96
 
 
97
  if (!igraph_is_directed(graph)) { mode=IGRAPH_ALL; }
 
98
 
 
99
  al->length=igraph_vcount(graph);
 
100
  al->adjs=igraph_Calloc(al->length, igraph_vector_t);
 
101
  if (al->adjs == 0) {
 
102
    IGRAPH_ERROR("Cannot create adjlist view", IGRAPH_ENOMEM);
 
103
  }
 
104
 
 
105
  IGRAPH_FINALLY(igraph_adjlist_destroy, al);
 
106
  for (i=0; i<al->length; i++) {
 
107
    IGRAPH_ALLOW_INTERRUPTION();
 
108
    IGRAPH_CHECK(igraph_vector_init(&al->adjs[i], 0));
 
109
    IGRAPH_CHECK(igraph_neighbors(graph, &al->adjs[i], i, mode));
 
110
  }
 
111
 
 
112
  IGRAPH_FINALLY_CLEAN(1);
 
113
  return 0;
 
114
}
 
115
 
 
116
/**
 
117
 * \function igraph_adjlist_init_complementer
 
118
 * Adjacency lists for the complementer graph
 
119
 * 
 
120
 * This function creates adjacency lists for the complementer 
 
121
 * of the input graph. In the complementer graph all edges are present
 
122
 * which are not present in the original graph. Multiple edges in the
 
123
 * input graph are ignored.
 
124
 * \param graph The input graph.
 
125
 * \param al Pointer to a not yet initialized adjacency list.
 
126
 * \param mode Constant specifying whether outgoing
 
127
 *   (<code>IGRAPH_OUT</code>), incoming (<code>IGRAPH_IN</code>),
 
128
 *   or both (<code>IGRAPH_ALL</code>) types of neighbors (in the
 
129
 *   complementer graph) to include in the adjacency list. It is
 
130
 *   ignored for undirected networks.
 
131
 * \param loops Whether to consider loop edges.
 
132
 * \return Error code.
 
133
 * 
 
134
 * Time complexity: O(|V|^2+|E|), quadratic in the number of vertices.
 
135
 */
 
136
 
 
137
int igraph_adjlist_init_complementer(const igraph_t *graph,
 
138
                                       igraph_adjlist_t *al, 
 
139
                                       igraph_neimode_t mode,
 
140
                                       igraph_bool_t loops) {
 
141
  long int i, j, k, n;
 
142
  igraph_bool_t* seen;
 
143
  igraph_vector_t vec;
 
144
 
 
145
  if (mode != IGRAPH_IN && mode != IGRAPH_OUT && mode != IGRAPH_ALL) {
 
146
    IGRAPH_ERROR("Cannot create complementer adjlist view", IGRAPH_EINVMODE);
 
147
  }
 
148
 
 
149
  if (!igraph_is_directed(graph)) { mode=IGRAPH_ALL; }
 
150
 
 
151
  al->length=igraph_vcount(graph);
 
152
  al->adjs=igraph_Calloc(al->length, igraph_vector_t);
 
153
  if (al->adjs == 0) {
 
154
    IGRAPH_ERROR("Cannot create complementer adjlist view", IGRAPH_ENOMEM);
 
155
  }
 
156
 
 
157
  IGRAPH_FINALLY(igraph_adjlist_destroy, al);
 
158
 
 
159
  n=al->length;
 
160
  seen=igraph_Calloc(n, igraph_bool_t);
 
161
  if (seen==0) {
 
162
    IGRAPH_ERROR("Cannot create complementer adjlist view", IGRAPH_ENOMEM);
 
163
  }
 
164
  IGRAPH_FINALLY(igraph_free, seen);
 
165
 
 
166
  IGRAPH_VECTOR_INIT_FINALLY(&vec, 0);
 
167
 
 
168
  for (i=0; i<al->length; i++) {
 
169
    IGRAPH_ALLOW_INTERRUPTION();
 
170
    igraph_neighbors(graph, &vec, i, mode);
 
171
    memset(seen, 0, sizeof(igraph_bool_t)*al->length);
 
172
    n=al->length;
 
173
    if (!loops) { seen[i] = 1; n--; }
 
174
    for (j=0; j<igraph_vector_size(&vec); j++) {
 
175
      if (! seen [ (long int) VECTOR(vec)[j] ] ) {
 
176
        n--;
 
177
        seen[ (long int) VECTOR(vec)[j] ] = 1;
 
178
      }
 
179
    }
 
180
    IGRAPH_CHECK(igraph_vector_init(&al->adjs[i], n));
 
181
    for (j=0, k=0; k<n; j++) {
 
182
      if (!seen[j]) {
 
183
        VECTOR(al->adjs[i])[k++] = j;
 
184
      }
 
185
    }
 
186
  }
 
187
 
 
188
  igraph_Free(seen);
 
189
  igraph_vector_destroy(&vec);
 
190
  IGRAPH_FINALLY_CLEAN(3);
 
191
  return 0;
 
192
}
 
193
 
 
194
/**
 
195
 * \function igraph_adjlist_destroy
 
196
 * Deallocate memory
 
197
 * 
 
198
 * Free all memory allocated for an adjacency list. 
 
199
 * \param al The adjacency list to destroy.
 
200
 * 
 
201
 * Time complexity: depends on memory management.
 
202
 */
 
203
 
 
204
void igraph_adjlist_destroy(igraph_adjlist_t *al) {
 
205
  long int i;
 
206
  for (i=0; i<al->length; i++) {
 
207
    if (&al->adjs[i]) { igraph_vector_destroy(&al->adjs[i]); }
 
208
  }
 
209
  igraph_Free(al->adjs);
 
210
}
 
211
 
 
212
/**
 
213
 * \function igraph_adjlist_size
 
214
 * Number of vertices in an adjacency list.
 
215
 * 
 
216
 * \param al The adjacency list.
 
217
 * \return The number of elements.
 
218
 * 
 
219
 * Time complexity: O(1).
 
220
 */
 
221
 
 
222
igraph_integer_t igraph_adjlist_size(const igraph_adjlist_t *al) {
 
223
  return al->length;
 
224
}
 
225
 
 
226
/* igraph_vector_t *igraph_adjlist_get(igraph_adjlist_t *al, igraph_integer_t no) { */
 
227
/*   return &al->adjs[(long int)no]; */
 
228
/* } */
 
229
 
 
230
/**
 
231
 * \function igraph_adjlist_sort
 
232
 * Sort each vector in an adjacency list.
 
233
 * 
 
234
 * Sorts every vector of the adjacency list.
 
235
 * \param al The adjacency list.
 
236
 * 
 
237
 * Time complexity: O(n log n), n is the total number of elements in
 
238
 * the adjacency list.
 
239
 */
 
240
 
 
241
void igraph_adjlist_sort(igraph_adjlist_t *al) {
 
242
  long int i;
 
243
  for (i=0; i<al->length; i++)
 
244
    igraph_vector_sort(&al->adjs[i]);
 
245
}
 
246
 
 
247
/**
 
248
 * \function igraph_adjlist_simplify
 
249
 * Simplify
 
250
 * 
 
251
 * Simplify an adjacency list, ie. remove loop and multiple edges.
 
252
 * \param al The adjacency list.
 
253
 * \return Error code.
 
254
 * 
 
255
 * Time complexity: O(|V|+|E|), linear in the number of edges and
 
256
 * vertices.
 
257
 */
 
258
 
 
259
int igraph_adjlist_simplify(igraph_adjlist_t *al) {
 
260
  long int i;
 
261
  long int n=al->length;
 
262
  igraph_vector_t mark;
 
263
  IGRAPH_VECTOR_INIT_FINALLY(&mark, n);
 
264
  for (i=0; i<n; i++) {
 
265
    igraph_vector_t *v=&al->adjs[i];
 
266
    long int j, l=igraph_vector_size(v);
 
267
    VECTOR(mark)[i] = i+1;
 
268
    for (j=0; j<l; /* nothing */) {
 
269
      long int e=VECTOR(*v)[j];
 
270
      if (VECTOR(mark)[e] != i+1) {
 
271
        VECTOR(mark)[e]=i+1;
 
272
        j++;
 
273
      } else {
 
274
        VECTOR(*v)[j] = igraph_vector_tail(v);
 
275
        igraph_vector_pop_back(v);
 
276
        l--;
 
277
      }
 
278
    }
 
279
  }
 
280
  
 
281
  igraph_vector_destroy(&mark);
 
282
  IGRAPH_FINALLY_CLEAN(1);
 
283
  return 0;
 
284
}
 
285
 
 
286
/**
 
287
 * \function igraph_adjedgelist_init
 
288
 * Initialize an adjacency list of edges
 
289
 * 
 
290
 * Create a list of vectors containing the adjacent edges for all
 
291
 * vertices. The adjacency list is independent of the graph after
 
292
 * creation, subsequent changes of the graph object do not update the
 
293
 * adjacency list, and changes to the adjacency list do no update the
 
294
 * graph.
 
295
 * \param graph The input graph.
 
296
 * \param ael Pointer to an uninitialized adjcency list.
 
297
 * \param mode Constant specifying whether incoming edges
 
298
 *   (<code>IGRAPH_IN</code>), outgoing edges (<code>IGRAPH_OUT</code>) or
 
299
 *   both (<code>IGRAPH_ALL</code>) to include in the adjacency lists
 
300
 *   of directed graphs. It is ignored for undirected graphs.
 
301
 * \return Error code.
 
302
 * 
 
303
 * Time complexity: O(|V|+|E|), linear in the number of vertices and
 
304
 * edges.
 
305
 */
 
306
 
 
307
int igraph_adjedgelist_init(const igraph_t *graph, 
 
308
                              igraph_adjedgelist_t *ael, 
 
309
                              igraph_neimode_t mode) {
 
310
  long int i;
 
311
 
 
312
  if (mode != IGRAPH_IN && mode != IGRAPH_OUT && mode != IGRAPH_ALL) {
 
313
    IGRAPH_ERROR("Cannot create adjedgelist view", IGRAPH_EINVMODE);
 
314
  }
 
315
 
 
316
  if (!igraph_is_directed(graph)) { mode=IGRAPH_ALL; }
 
317
 
 
318
  ael->length=igraph_vcount(graph);
 
319
  ael->adjs=igraph_Calloc(ael->length, igraph_vector_t);
 
320
  if (ael->adjs == 0) {
 
321
    IGRAPH_ERROR("Cannot create adjedgelist view", IGRAPH_ENOMEM);
 
322
  }
 
323
 
 
324
  IGRAPH_FINALLY(igraph_adjlist_destroy, ael);  
 
325
  for (i=0; i<ael->length; i++) {
 
326
    IGRAPH_ALLOW_INTERRUPTION();
 
327
    IGRAPH_CHECK(igraph_vector_init(&ael->adjs[i], 0));
 
328
    IGRAPH_CHECK(igraph_adjacent(graph, &ael->adjs[i], i, mode));
 
329
  }
 
330
  
 
331
  IGRAPH_FINALLY_CLEAN(1);
 
332
  return 0;
 
333
}
 
334
 
 
335
/**
 
336
 * \function igraph_adjedgelist_destroy
 
337
 * Destroy
 
338
 * 
 
339
 * Free all memory allocated for an adjacency list.
 
340
 * \param eal The adjcency list to destroy.
 
341
 * 
 
342
 * Time complexity: depends on memory management.
 
343
 */
 
344
 
 
345
void igraph_adjedgelist_destroy(igraph_adjedgelist_t *ael) {
 
346
  long int i;
 
347
  for (i=0; i<ael->length; i++) {
 
348
    /* This works if some igraph_vector_t's are 0, because igraph_vector_destroy can
 
349
       handle this. */
 
350
    igraph_vector_destroy(&ael->adjs[i]);
 
351
  }
 
352
  igraph_Free(ael->adjs);
 
353
}
 
354
 
 
355
/**
 
356
 * \function igraph_lazy_adjlist_init
 
357
 * Constructor
 
358
 *
 
359
 * Create a lazy adjacency list for vertices. This function only
 
360
 * allocates some memory for storing the vectors of an adjacency list,
 
361
 * but the neighbor vertices are not queried, only at the \ref
 
362
 * igraph_lazy_adjlist_get() calls. 
 
363
 * \param graph The input graph.
 
364
 * \param al Pointer to an uninitialized adjacency list object.
 
365
 * \param mode Constant, it gives whether incoming edges
 
366
 *   (<code>IGRAPH_IN</code>), outgoing edges
 
367
 *   (<code>IGRPAH_OUT</code>) or both types of edges
 
368
 *   (<code>IGRAPH_ALL</code>) are considered. It is ignored for
 
369
 *   undirected graphs.
 
370
 * \param simplify Constant, it gives whether to simplify the vectors
 
371
 *   in the adjacency list (<code>IGRAPH_SIMPLIFY</code>) ot not
 
372
 *   (<code>IGRAPH_DONT_SIMPLIFY</code>).
 
373
 * \return Error code.
 
374
 * 
 
375
 * Time complexity: O(|V|), the number of vertices, possibly, but
 
376
 * depends on the underlying memory management too.
 
377
 */
 
378
 
 
379
int igraph_lazy_adjlist_init(const igraph_t *graph,
 
380
                               igraph_lazy_adjlist_t *al,
 
381
                               igraph_neimode_t mode,
 
382
                               igraph_lazy_adlist_simplify_t simplify) {
 
383
  if (mode != IGRAPH_IN && mode != IGRAPH_OUT && mode != IGRAPH_ALL) {
 
384
    IGRAPH_ERROR("Cannor create adjlist view", IGRAPH_EINVMODE);
 
385
  }
 
386
 
 
387
  if (!igraph_is_directed(graph)) { mode=IGRAPH_ALL; }  
 
388
  al->mode=mode;
 
389
  al->simplify=simplify;
 
390
  al->graph=graph;
 
391
  
 
392
  al->length=igraph_vcount(graph);
 
393
  al->adjs=igraph_Calloc(al->length, igraph_vector_t*);
 
394
  if (al->adjs == 0) {
 
395
    IGRAPH_ERROR("Cannot create lazy adjlist view", IGRAPH_ENOMEM);
 
396
  }
 
397
 
 
398
  return 0;
 
399
}
 
400
 
 
401
/**
 
402
 * \function igraph_lazy_adjlist_destroy
 
403
 * Deallocate memory
 
404
 * 
 
405
 * Free all allocated memory for a lazy adjacency list.
 
406
 * \param al The adjacency list to deallocate.
 
407
 * 
 
408
 * Time complexity: depends on the memory management.
 
409
 */
 
410
 
 
411
void igraph_lazy_adjlist_destroy(igraph_lazy_adjlist_t *al) {
 
412
  long int i, n=al->length;
 
413
  for (i=0; i<n; i++) {
 
414
    if (al->adjs[i] != 0) {
 
415
      igraph_vector_destroy(al->adjs[i]);
 
416
      igraph_Free(al->adjs[i]);
 
417
    }
 
418
  }
 
419
  igraph_Free(al->adjs);
 
420
}
 
421
 
 
422
igraph_vector_t *igraph_lazy_adjlist_get_real(igraph_lazy_adjlist_t *al,
 
423
                                                igraph_integer_t pno) {
 
424
  long int no=pno;
 
425
  int ret;
 
426
  if (al->adjs[no] == 0) {
 
427
    al->adjs[no] = igraph_Calloc(1, igraph_vector_t);
 
428
    if (al->adjs[no] == 0) {
 
429
      igraph_error("Lazy adjlist failed", __FILE__, __LINE__, 
 
430
                   IGRAPH_ENOMEM);
 
431
    }
 
432
    ret=igraph_vector_init(al->adjs[no], 0);
 
433
    if (ret != 0) {
 
434
      igraph_error("", __FILE__, __LINE__, ret);
 
435
    }
 
436
    ret=igraph_neighbors(al->graph, al->adjs[no], no, al->mode);
 
437
    if (ret != 0) {
 
438
      igraph_error("", __FILE__, __LINE__, ret);
 
439
    }
 
440
 
 
441
    if (al->simplify == IGRAPH_SIMPLIFY) {
 
442
      igraph_vector_t *v=al->adjs[no];
 
443
      long int i, p=0, n=igraph_vector_size(v);
 
444
      for (i=0; i<n; i++) {
 
445
        if (VECTOR(*v)[i] != no && 
 
446
            (i==n-1 || VECTOR(*v)[i+1] != VECTOR(*v)[i])) {
 
447
          VECTOR(*v)[p]=VECTOR(*v)[i];
 
448
          p++;
 
449
        }
 
450
      }
 
451
      igraph_vector_resize(v, p);
 
452
    }
 
453
  }
 
454
  
 
455
  return al->adjs[no];
 
456
}
 
457
 
 
458
/**
 
459
 * \function igraph_lazy_adjedgelist_init
 
460
 * Constructor
 
461
 * 
 
462
 * Create a lazy adjacency list for edges. This function only
 
463
 * allocates some memory for storing the vectors of an adjacency list,
 
464
 * but the adjacent edges are not queried, only when \ref
 
465
 * igraph_lazy_adjedgelist_get() is called.
 
466
 * \param graph The input graph.
 
467
 * \param al Pointer to an uninitialized adjacency list.
 
468
 * \param mode Constant, it gives whether incoming edges
 
469
 *   (<code>IGRAPH_IN</code>), outgoing edges
 
470
 *   (<code>IGRPAH_OUT</code>) or both types of edges
 
471
 *   (<code>IGRAPH_ALL</code>) are considered. It is ignored for
 
472
 *   undirected graphs.
 
473
 * \return Error code.
 
474
 * 
 
475
 * Time complexity: O(|V|), the number of vertices, possibly. But it
 
476
 * also depends on the underlying memory management too.
 
477
 */
 
478
 
 
479
int igraph_lazy_adjedgelist_init(const igraph_t *graph,
 
480
                                   igraph_lazy_adjedgelist_t *al,
 
481
                                   igraph_neimode_t mode) {
 
482
 
 
483
  if (mode != IGRAPH_IN && mode != IGRAPH_OUT && mode != IGRAPH_ALL) {
 
484
    IGRAPH_ERROR("Cannot create adjlist view", IGRAPH_EINVMODE);
 
485
  }
 
486
  
 
487
  if (!igraph_is_directed(graph)) { mode=IGRAPH_ALL; }
 
488
  
 
489
  al->mode=mode;
 
490
  al->graph=graph;
 
491
  
 
492
  al->length=igraph_vcount(graph);
 
493
  al->adjs=igraph_Calloc(al->length, igraph_vector_t*);
 
494
  if (al->adjs == 0) {
 
495
    IGRAPH_ERROR("Cannot create lazy adjedgelist view", IGRAPH_ENOMEM);
 
496
  }
 
497
 
 
498
  return 0;
 
499
  
 
500
}
 
501
 
 
502
/**
 
503
 * \function igraph_lazy_adjedgelist_destroy
 
504
 * Deallocate memory
 
505
 * 
 
506
 * Free all allocated memory for a lazy edge adjacency list.
 
507
 * \param al The adjacency list to deallocate.
 
508
 * 
 
509
 * Time complexity: depends on memory management.
 
510
 */
 
511
 
 
512
void igraph_lazy_adjedgelist_destroy(igraph_lazy_adjedgelist_t *al) {
 
513
  long int i, n=al->length;
 
514
  for (i=0; i<n; i++) {
 
515
    if (al->adjs[i] != 0) {
 
516
      igraph_vector_destroy(al->adjs[i]);
 
517
      igraph_Free(al->adjs[i]);
 
518
    }
 
519
  }
 
520
  igraph_Free(al->adjs);
 
521
}
 
522
 
 
523
igraph_vector_t *igraph_lazy_adjedgelist_get_real(igraph_lazy_adjedgelist_t *al,
 
524
                                                    igraph_integer_t pno) {
 
525
  long int no=pno;
 
526
  int ret;
 
527
  if (al->adjs[no] == 0) {
 
528
    al->adjs[no] = igraph_Calloc(1, igraph_vector_t);
 
529
    if (al->adjs[no] == 0) {
 
530
      igraph_error("Lazy adjedgelist failed", __FILE__, __LINE__, 
 
531
                   IGRAPH_ENOMEM);
 
532
    }
 
533
    ret=igraph_vector_init(al->adjs[no], 0);
 
534
    if (ret != 0) {
 
535
      igraph_error("", __FILE__, __LINE__, ret);
 
536
    }
 
537
    ret=igraph_adjacent(al->graph, al->adjs[no], no, al->mode);
 
538
    if (ret != 0) {
 
539
      igraph_error("", __FILE__, __LINE__, ret);
 
540
    }
 
541
  }
 
542
  return al->adjs[no];
 
543
}