153 lines
3.6 KiB
C
153 lines
3.6 KiB
C
// vim:fileencoding=utf-8:foldmethod=marker
|
|
|
|
/* graph.c
|
|
|
|
A generic adjacency list graph data type.
|
|
*/
|
|
|
|
/* Copyright 2003-2020 by Steven S. Skiena; all rights reserved.
|
|
Permission is granted for use in non-commerical applications
|
|
provided this copyright notice remains intact and unchanged.
|
|
|
|
These programs appear in my books:
|
|
|
|
"The Algorithm Design Manual" by Steven Skiena, second edition, Springer,
|
|
London 2008. See out website www.algorist.com for additional information
|
|
or https://www.amazon.com/exec/obidos/ASIN/1848000693/thealgorith01-20
|
|
|
|
"Programming Challenges: The Programming Contest Training Manual"
|
|
by Steven Skiena and Miguel Revilla, Springer-Verlag, New York 2003.
|
|
See our website www.programming-challenges.com for additional information,
|
|
or https://www.amazon.com/exec/obidos/ASIN/0387001638/thealgorithmrepo/
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "queue.h"
|
|
#include "graph.h"
|
|
|
|
/* [[[ init_graph_c */
|
|
void initialize_graph(graph *g, bool directed) {
|
|
int i; /* counter */
|
|
|
|
g->nvertices = 0;
|
|
g->nedges = 0;
|
|
g->directed = directed;
|
|
|
|
for (i = 1; i <= MAXV; i++) {
|
|
g->degree[i] = 0;
|
|
}
|
|
|
|
for (i = 1; i <= MAXV; i++) {
|
|
g->edges[i] = NULL;
|
|
}
|
|
}
|
|
/* ]]] */
|
|
|
|
/* [[[ insert_edge_cut */
|
|
void insert_edge(graph *g, int x, int y, bool directed) {
|
|
edgenode *p; /* temporary pointer */
|
|
|
|
p = malloc(sizeof(edgenode)); /* allocate edgenode storage */
|
|
|
|
p->weight = 0;
|
|
p->y = y;
|
|
p->next = g->edges[x];
|
|
|
|
g->edges[x] = p; /* insert at head of list */
|
|
|
|
g->degree[x]++;
|
|
|
|
if (!directed) {
|
|
insert_edge(g, y, x, true);
|
|
} else {
|
|
g->nedges++;
|
|
}
|
|
}
|
|
/* ]]] */
|
|
|
|
/* [[[ read_graph_cut */
|
|
void read_graph(graph *g, bool directed) {
|
|
int i; /* counter */
|
|
int m; /* number of edges */
|
|
int x, y; /* vertices in edge (x,y) */
|
|
|
|
initialize_graph(g, directed);
|
|
|
|
scanf("%d %d", &(g->nvertices), &m);
|
|
|
|
for (i = 1; i <= m; i++) {
|
|
scanf("%d %d", &x, &y);
|
|
insert_edge(g, x, y, directed);
|
|
}
|
|
}
|
|
/* ]]] */
|
|
|
|
void delete_edge(graph *g, int x, int y, bool directed) {
|
|
edgenode *p, *p_back; /* temporary pointers */
|
|
|
|
p = g->edges[x];
|
|
p_back = NULL;
|
|
|
|
while (p != NULL) {
|
|
if (p->y == y) {
|
|
g->degree[x]--;
|
|
if (p_back != NULL) {
|
|
p_back->next = p->next;
|
|
} else {
|
|
g->edges[x] = p->next;
|
|
}
|
|
free(p);
|
|
if (!directed) {
|
|
delete_edge(g, y, x, true);
|
|
} else {
|
|
g->nedges--;
|
|
}
|
|
return;
|
|
} else {
|
|
p = p->next;
|
|
}
|
|
}
|
|
printf("Warning: deletion(%d,%d) not found in g.\n",x,y);
|
|
}
|
|
|
|
/* [[[ print_graph_cut */
|
|
void print_graph(graph *g) {
|
|
int i; /* counter */
|
|
edgenode *p; /* temporary pointer */
|
|
|
|
for (i = 1; i <= g->nvertices; i++) {
|
|
printf("%d: ", i);
|
|
p = g->edges[i];
|
|
while (p != NULL) {
|
|
printf(" %d", p->y);
|
|
p = p->next;
|
|
}
|
|
printf("\n");
|
|
}
|
|
}
|
|
/* ]]] */
|
|
|
|
/* [[[ graph_transpose_cut */
|
|
graph *transpose(graph *g) {
|
|
graph *gt; /* transpose of graph g */
|
|
int x; /* counter */
|
|
edgenode *p; /* temporary pointer */
|
|
|
|
gt = (graph *) malloc(sizeof(graph));
|
|
initialize_graph(gt, true); /* initialize directed graph */
|
|
gt->nvertices = g->nvertices;
|
|
|
|
for (x = 1; x <= g->nvertices; x++) {
|
|
p = g->edges[x];
|
|
while (p != NULL) {
|
|
insert_edge(gt, p->y, x, true);
|
|
p = p->next;
|
|
}
|
|
}
|
|
|
|
return(gt);
|
|
}
|
|
/* ]]] */
|