Author: Hayden Smith 2021
Why?
What?
Often, graphs don't look like the one on the left. They look like the one on the right. They have directions and weights.
Digraphs are very similar to normal graphs, except that edges have a sense of direction such that:
v → w ≠ w → v
Array of edges | Adjacency Matrix | Adjacency List | |
---|---|---|---|
Space usage | E | V^2 | V + E |
Insert edge | E | 1 | deg(v) |
exists edge (v,w) | E | 1 | deg(v) |
get edges leaving v | E | V | deg(v) |
Identical to undirected graphs
Weighted graphs are similar to our previous graphs, except the edges have a sense of COST / WEIGHT.
Generally speaking, this means that when we traverse the graph certain edges will be "cheaper" to explore than others.
Each edge is now (s, t, w) instead of (s, t)
Weighted graphs have substantially more parallels to reality:
There are two main problems we try to solve with weighted graphs:
1. Cheapest way to connect all vertices (minimal spanning tree problem) - for undirected weighted graphs
2. Cheapest way to get from A to B (shortest path problem) - for directed weighted graphs
We will cover these in more detail.
Adjacency Matrix Representation
Adjacency List Representation
Array/List of Edges Representation
Graph.h
// edges are pairs of vertices (end-points) plus weight
typedef struct Edge {
Vertex v;
Vertex w;
int weight;
} Edge;
// returns weight, or 0 if vertices not adjacent
int GraphAdjacent(Graph, Vertex, Vertex);
typedef struct GraphRep {
int **edges; // adjacency matrix storing weights
// 0 if nodes not adjacent
int nV; // #vertices
int nE; // #edges
} GraphRep;
int GraphAdjacent(Graph g, Vertex v, Vertex w) {
assert(valid graph, valid vertices)
return (g->edges[v][w] != 0);
}
void GraphEdgeInsert(Graph g, Edge e) {
assert(valid graph, valid edge)
// edge e not already in graph
if (g->edges[e.v][e.w] == 0) g->nE++;
// may change weight of existing edge
g->edges[e.v][e.w] = e.weight;
g->edges[e.w][e.v] = e.weight;
}
void GraphEdgeRemove(Graph g, Edge e) {
assert(valid graph, valid edge)
// edge e not in graph
if (g->edges[e.v][e.w] == 0) return;
g->edges[e.v][e.w] = 0;
g->edges[e.w][e.v] = 0;
g->nE--;
}
Graph.c