Fri, Apr 03, 2026
A network graph is a data structure that models pairwise relationships between discrete elements within a system. The visual presentation of this type of graph generally consists of a collection of nodes connected by edges between them.
We are not talking about graphs of functions in this context. We’re not talking about parabolas or sine waves or anything like that.
The following terms are synonymous
As are
Sometimes, I might refer to the nodes of a graph as vertices.
Sometimes, the nodes might be labeled.
Sometimes, the edges might be directed. We call this type of graph a directed graph or digraph.
Sometimes, the edges might be weighted and we might have more than one between any two vertices. We call this type of graph a directed multigraph.
Given all these possibilities, we often refer to a plain old graph with no directed edges, multi-edges or loops as a simple graph.
Graph theory, network analysis, or whatever you want to call it has a lot of applications. Here are just a few.
The foundations of graph theory and topology date back to Euler’s solution of the seven bridges of Königsberg problem. The problem asked for a walk through the city of Königsberg that crossed each bridge exactly once. Euler showed that there is no such walk.
Can you see how the graph below captures all the information in the map that’s essential to address the problem?

Public domain images from Wikipedia – Map by Bogdan Giuşcă
I guess social networks got bigger. The network graph below is a map of the internet. It could also be viewed as an application to engineering.
By The Opte Project - Originally from the English Wikipedia; description page is/was here., CC BY 2.5,
We’ve seen this before, of course.
I first learned of so-called directed multi-graphs when studying certain types of fractal objects in preparation for my dissertation in graduate school.
The fractal curves on the previous slide each consists of smaller copies of both curves. The combinatorics of how they all fit together can be described by the following directed multi-graph:
Recall that the seven bridges of Königsberg problem asks for a walk through the city of Königsberg that crossed each bridge exactly once. There’s a surprising amount of terminology to reformulate this problem as a graph theoretic problem.
An Eulerian trail is a trail that uses every edge of the graph exactly once.
Using this language, the Königsberg problem asks whether the Königsberg graph has an Eulerian trail.
Can you find an Eulerian trail through the graph below:
Can you find an Eulerian trail through the Königsberg graph?
What is the relevant distinction between these two graphs?
A graph is connected if for every pair of vertices \(u\) and \(v\), there exists a path from \(u\) to \(v\).
The degree of a vertex \(v\), denoted \(\deg(v)\), is the number of edges incident to \(v\). A loop (if allowed) contributes \(2\) to the degree.
A connected graph has an Eulerian trail (but not an Eulerian circuit) if and only if exactly two vertices have odd degree.
A connected graph has an Eulerian circuit if and only if each vertex has even degree.
A tree is a simple graph with no cycles.
Tournaments have the structure of a tree:
Hierarchical structures can often be visualized with a tree. Here’s a map based view of hierarchies within the US that I took from this US Census PDF:
We can examine that same data within a tree structure:
An abstract syntax tree or AST is a graph theoretic technique to represent a mathematical expression as a tree. Can you see, for example, how we might represent \(2x^3 + 1\) as
Here’s a data structure that might represent that tree:
In a data structure class, you’ll certainly discuss tree traversal. In the context of ASTs, this allows you do things like,
Here’s an evaluation function based on recursive tree traversal:
def evaluate_expr_tree(node: dict, env: dict) -> float:
node_type = node["type"]
if node_type == "Number":
return node["value"]
elif node_type == "Variable":
name = node["name"]
if name not in env:
raise ValueError(f"Variable '{name}' not provided")
return env[name]
elif node_type == "BinaryOp":
left_val = evaluate_expr_tree(node["left"], env)
right_val = evaluate_expr_tree(node["right"], env)
op = node["op"]
if op == "+":
return left_val + right_val
elif op == "-":
return left_val - right_val
elif op == "*":
return left_val * right_val
elif op == "/":
return left_val / right_val
elif op == "^":
return left_val ** right_val
else:
raise ValueError(f"Unknown operator: {op}")
else:
raise TypeError(f"Unknown node type: {node_type}")The following computation, for example, computes \[2\times4^3 + 1 = 129.\]
A directed, acyclic graph (or DAG) is a directed graph with no cycles.
Trees emanating from specified root clearly yield DAGs. There are other examples, though.
Given a set of positive integers as nodes, we can form a directed graph by placing a directed edge from node \(i\) to node \(j\) if \(i\) divides \(j\). The result is called a divisor graph and it’s pretty easy to see that it should be acyclic.
Here’s the divisor graph on the set \(1\) through \(12\):
Here’s another DAG.
In this case, the edge direction is implied to be upward. This kind of assumption is common in neural networks.
Do take a minute to check out
Social networks
The use of social networks to model relationships between people dates back quite a while. I found the image below in this paper from Volume 1 of the Journal of Social Structure. That article was a survey of earlier work and states that the image was taken from a 1934 paper studying human development. The image indicates who recognizes who among a collection of nine babies.