Topic: | Graphs (Overview, Traversal) |
---|---|
Author: | Peter Bui <pbui@cse.nd.edu> |
Date: | September 30, 2009 |
Defined by a set of vertices or nodes and edges which connect one vertex to another:
G = (V, E)
Undirected vs. Directed
If undirected, then edge (x, y) also implies (y, x).
Acyclic vs. Cyclic
If acyclic, then no cycles or loops. Trees are acyclic, undirected graphs.
NxN matrix that records the edges.
0 1 2 3 4 0[0 1 1 1 0] 1[1 0 1 0 0] 2[1 1 0 1 0] 3[1 0 1 0 0] 4[0 0 0 0 0]
Good for checking if edge(x,y) is in the graph, but can take up a lot of space.
typedef struct {
size_t nedges;
size_t nvertices;
bool edges[][];
} Graph;
static void create_graph(Graph &g, size_t nedges, size_t nvertices) {
g.nedges = nedges;
g.nvertices = nvertices;
g.edges = new bool*[nvertices];
for (size_t v = 0; v < nvertices; v++)
g.edges[v] = new bool[nvertices];
}
Each vertex contains a collection of connected vertices
0 [1 2 3] 1 [0 2] 2 [0 1 3] 3 [0 2] 4 []
Space efficient, but less efficient for checking if edge is in graph.
typedef struct {
size_t nedges;
size_t nvertices;
vector < vector<int> > edges;
} Graph;
static void create_graph(Graph &g, size_t nedges, size_t nvertices) {
g.nedges = nedges;
g.nvertices = nvertices;
g.edges.resize(nvertices);
}
You could use the same struct for either representation, it's just how you use it.
Basically uses backtracking to traverse a graph:
// Perform DFS traversal and print vertex
static void dfs(Graph &g, int v = 0) {
if (!g.visited[v]) {
g.visited[v] = true;
cout << "visited " << v << endl;
for (size_t i = 0; i < g.edges[v].size(); i++)
dfs(g, g.edges[v][i]);
}
}
Process neighbors first, then process the next level.
// Perform DFS traversal and print vertex
static void bfs(Graph &g, vector<int> &v) {
while (!v.empty())
if (!g.visited[v.front()]) {
g.visited[v.front()] = true;
cout << "visited " << v.front() << endl;
for (size_t j = 0; j < g.edges[v.front()].size(); j++)
nv.push_back(g.edges[v.front()][j]);
}
v.pop_front();
}
}