You are on page 1of 4

Week 7 Tutorial: Graphs

Stage 1: fill out and implement the ADTs (we write AIs in Round 2)
GameView: access to all info to state of game
Design decision as to what to put in the struct
DracView, HunterView: access to a limited amount of info
Call stuff from GameView, but neither player calls from GameView directly
Cant modify header files and their signatures in Round 1. In Round 2 (AI), you are
welcome to
change stuff as you like.

Q3
Path: sequence of edges (connected by one another)
Shortest path is 1 edge
Cycle: edges bring you back to the same starting vertex
e.g. in tutorial: abcdefghikja
Tree: graph without any cycles
From the current graph, delete all edges that make it not a tree
e.g. delete the star, b-f, i-k, k-h
Spanning tree: a tree able to reach every node
Clique: totally connected subgraph - i.e. fully connected
Every node connected to every other node by a single edge
e.g. bcdef is a clique
e.g. smallest clique: a triangle
Q4.
1
0

3
2
4

(a).
6 vertices: therefore 6x6 matrix
012345
weight.
0

011

0/1 are true false values, can be > 1 to represent

1
2
3
4
5

10 1
1
11
11
1
1
1

Undirected graph = symmetry. For one edge, need to change 2 variables.


Directed graph: one side represents from, one side represents to.
Uses a lot of space. Size of matrix: V * V => huge, but if few connections, only one
entry.
Complete waste of space if there are few edges
(b).
Adjacency list representation: a jagged list of lists
0
12

1
02

2
034

3
12

4
25

5
4

6
- array of ptrs
null

(and then each linked list goes to NULL)


Again, represented twice for an undirected graph. And only once for a directed
graph.
More space efficient: space used = twice the amount of edges (for undirected) that
exist
There is a certain point where adjacency lists will use more memory than matrices.
Worse time complexity: need to scan through each list.
Q6.
Write a function to count the number of edges in a graph:
int nEdges (Graph g)
{
int count = 0;
for (int i = 0; i < g->nV; i++) {
for (int j = i+1; j < g->nV; j++) {
count += g->edges[i][j];
}
}

// triangle method
// could also count weight

}
Consider a triangle of the matrix
Could count all 1s, and divide by 2 (need to check no node points to itself or handle it
otherwise)
Q11.
BFS: explore nodes closest to it
DFS: go far away
Writing each one is the same - just that one uses a queue and one uses a stack.
BFS for example graph in q11:

current node queue


===================
nothing
0
0
1
- 1 is neighbour of 0
(visited: 0)
1
234
- could add 1 to the queue and check later
visited: (0,
1)
2
3435
- 1 is in visited but 3 isnt, so duplicate, but possible to
implement
some way to avoid this
visited: (0,1,5)
3
43545
visited: (0,1,5,3)
4
35455
etc. put 4 in visited
3
5455
- already in visited
5
45567

67
6
7
- 6 has no neighbouring nodes
7
nothing - finished BFS

DFS:
current node queue
===================
nothing
0
0
1
1
234

4
5
7
out.

2335
67
nothing

- goes deeper into the graph first, then goes back


Again, can have visited[] to prevent repeats.

DFS can be written recursively because it uses a stack:


ex. (but eats up your stack frame - stack overflow)
void explore (current_node):
for all the current nodes neighbours:
visit neighbour
No need to write up a stack - we just borrow the stack in memory