Skip to main content

What are Graphs?

· 6 min read
Strider

Graphs are data structures that form a kind of network. These come from graph theory and are nothing more than a set of nodes and edges, which are all somehow connected to each other. With graphs many everyday problems can be modeled e.g. city map, navigation systems etc...

Graphs are also used in network technology. Here the network is represented as a graph, so that routers form the nodes, and routed accordingly.

Here I don't want to go into how graphs are programmed but rather scratch around on the surface a bit.

Definition of a Graph

Let G=(K,E)G = (K, E) where GG is the graph and KK is the set of all nodes and EE is the set of all edges. With this information, one can build graphs.

A small example:
G=(K,E)G = (K, E)
K={A,B,C}K = \{A, B, C\}
E={(A,B),(A,C),(C,B)}E = \{(A, B), (A, C), (C, B)\}

Then our graph would look like this when we build everything together.

example.png

Types of Graphs

There are basically 2 types of graphs, directed and undirected graphs.

A directed graph looks like this:

dia.png

An undirected graph looks like this:

dia2.png

Note that not every directed graph can be converted to an undirected graph. The reason is that with an undirected graph, we can go from AA to BB, or from BB to AA.

dia3.png

Let's code some graphs

Ok, what can we do with it now? Let's assume we now want to know which paths there are to get from AA to FF for these graphs.

dia4.png

Naively, it would be a good idea to start from node AA and simply walk along all the paths. And that's exactly what we'll do now.

The paths are:

ADFA \rightarrow D \rightarrow F
ADEFA \rightarrow D \rightarrow E \rightarrow F
ADBCEFA \rightarrow D \rightarrow B \rightarrow C \rightarrow E \rightarrow F
ABCEFA \rightarrow B \rightarrow C \rightarrow E \rightarrow F
ABCDFA \rightarrow B \rightarrow C \rightarrow D \rightarrow F
ABCDEFA \rightarrow B \rightarrow C \rightarrow D \rightarrow E \rightarrow F

The same can be done to any node in the graph.

A small implementation in Prolog shows how to implement such a graph.

%edge(X, Y) X goes to Y
edge(a, b).
edge(a, d).
edge(b, c).
edge(c, d).
edge(c, e).
edge(d, e).
edge(d, f).
edge(e, f).
%edge(f, a).


path(X, X).
path(X, Y) :- edge(X, U), path(U, Y).

route(X, X, list(X, nil)).
route(X, Y, list(X, Xs)) :- edge(X, N), route(N, Y, Xs).

Note that I have commented out the edge FAF \rightarrow A because it comes to loops. Here a cycle recognition would have to purely, which would make however the code very unclear. Well no matter if we run the times we will see what happens.

The language used in the following image is german

console1.png

In the output we see that when we ask Prolog if there is a path from node AA to node FF, it returns true. In the next query we ask which paths exist and we get solutions thrown out. Prolog did not find all paths, but this is due to the depth-first search.

Adjacency matrix

A graph can also be represented in the form of an adjacency list or adjacency matrix.

For the adjacency matrix we do the following, we create a row for each node. Then create exactly as many columns of the same label.

This then looks like this:

ABCDEF
A
B
C
D
E
F

Now that we have created everything, we can start filling the matrix. We go through the matrix column by column. At node AA we look where we can get everywhere. From node AA we come out at BB and DD. We keep doing this until the matrix is full.

ABCDEF
A010100
B001000
C000110
D010011
E000001
F100000

What exactly does the matrix bring us?
We can represent this matrix as a two-dimensional array, and thus store graphs in files and read them out again.

Adjacency list

Another possibility is, as already mentioned, the adjacency list. This has a similar structure but a bit more memory efficient than the matrix. Here we have a one-dimensional array which contains lists. Also here we look where we come out at the single nodes.

This looks like this:

[A]BD[A] \rightarrow B \rightarrow D
[B]C[B] \rightarrow C
[C]DE[C] \rightarrow D \rightarrow E
[D]BEF[D] \rightarrow B \rightarrow E \rightarrow F
[E]F[E] \rightarrow F
[F]A[F] \rightarrow A

Great, now we have learned a few things about graphs, but what about graphs with weights on the edges?

Weights

First of all, what is a weight?
A weight is a real number, which represents e.g. the distance. Suppose we have a map and want to go from Aachen to Berlin. Here we would have different cities that are on the way and connected to Aachen and Berlin. Each route has a certain length. Each city is connected to another city by a highway. We want to know the shortest way to get to Berlin. There the weights (distance further) help us.

A graph with weighted edges looks like this:

dia5.png

The edges have all got numbers as mentioned these are the weights. The weights here are the kilometers we need to get from Aachen to Berlin. The other cities are possible intermediate stops. The kilometer numbers are only exemplary.

Here we can also go naively to the thing, in which we visit from Aachen all nodes and count the kilometers.

Aachen \rightarrow Bremen \rightarrow Potsdam \rightarrow Berlin = 510Km
Aachen \rightarrow Frankfurt \rightarrow Berlin = 500Km
Aachen \rightarrow Köln \rightarrow Berlin = 250Km
Aachen \rightarrow Frankfurt \rightarrow Potsdam \rightarrow Berlin = 210Km
...

I think you can see where this leads to. To algorithms, which look for us the shortest ways out e.g. Prim, Kruskal, Dijkstra etc...

I will go into this in the next post.

I hope I could provide a little insight into graphs 😄