Traverse a graph represented in an adjacency matrix

breadth-first-search, c#, depth-first-search, matrix, traversal

Solution

Every problem in computer science except one can be solved by adding more abstraction.

Start by writing the breadth-first-traversal in the most abstract way possible:

void BreadthFirstTraversal(Graph graph, Vertex start)
{
    /* A miracle happens */
}

We have a method that does what we want. Except that it hasn't been written yet. So write it with slightly less abstraction:

void BreadthFirstTraversal(Graph graph, Vertex start)
{
    /* make a queue of vertices */
    /* make a mark set of vertices */
    /* enqueue and mark start */
    /* while the queue is not empty */
        /* dequeue a vertext */
        /* enqueue and mark all the unmarked neighbours of the vertex */
}

Keep on going, removing more and more abstraction.

void BreadthFirstTraversal(Graph graph, Vertex start)
{
    var queue = new VertexQueue();
    var markSet = new VertexMarkSet();
    queue.Enqueue(start);
    markSet.Add(start);
    while(queue.NotEmpty())
    {
        var vertex = queue.Dequeue();
        foreach(Vertex neighbour in graph.ListNeighbours(vertex))
        {
            if (!markSet.Contains(neighbour))
            {
                markSet.Add(neighbour);
                queue.Enqueue(neighbour);
            }
        }
     }
}

OK, now you've got an algorithm that will work for any graph, no matter what its representation internally. So all you have to do is write `ListNeighbours(Vertex)` and you're done. (Assuming that you already know how to write a queue and a set, or are willing to use the types that come with the base class library.) How are you going to do that?

You see how I used abstraction there? I really don't care whether its an adjacency matrix or an adjacency list, all I care about is that the graph provides me the service of giving me the neighbours of a vertex.

So, how are you going to write `ListNeighbours(Vertex)` given your adjacency matrix?

Two possible solutions to investigate:

Make the `Graph.ListNeighbours(Vertex)` method return a `List<Vertex>`. Construct the list and hand it out.

Make it return `IEnumerable<Vertex>` and use `yield return` to yield a sequence of neighbouring vertices.

UPDATE: OK, so how do we actually make a sequence of neighbours out of an adjacency matrix?

Let's suppose that every vertex is numbered, so `Vertex` is really `int`; this is traditionally how things are done with adjacency matrices. We want to take in a vertex -- an int -- and return a sequence of vertices that are its neighbours.

We have an array that has the property that `array[i, j]` is non-zero if vertex `j` is a neighbour of vertex `i`.

Again, start abstract and work your way towards implementation:

public List<int> ListNeighbours(int vertex)
{
    /* a miracle happens */
}

What do we need to do to make that miracle happen?

public List<int> ListNeighbours(int vertex)
{
    /* create a new list */
    /* for each vertex j in the graph */
        /* if j is a neighbour of i then add it to the list */
    /* return the list */
}

Alternatively, you can use `yield return` to create a sequence:

public IEnumerable<int> ListNeighbours(int vertex)
{
    /* for each vertex j in the graph */
        /* if j is a neighbour of i then yield return j */
}

`yield return` iterators tend to be simpler, but beginner programmers often have a hard time sussing out the control flow. Try writing it both ways and see how it goes.

Problem

I am wanting to use the depth-first and breadth-first methods for traversing a graph. I have done this on a simple list of nodes before, but I have never tried it with an adjacency matrix and I honestly don't even know where to start. Here is my matrix: ``` 999999999 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 999999999 0 3 1 0 0 0 0 0 0 0 0 0 0 0 1 0 999999999 3 0 1 0 0 0 0 0 0 0 0 0 0 0 3 3 999999999 0 0 0 8 0 0 0 0 0 0 0 0 0 1 0 0 999999999 0 1 3 0 0 0 0 0 0 0 0 0 0 1 0 0 999999999 0 3 1 0 0 0 0 0 0 0 0 0 0 0 1 0 999999999 0 0 3 0 1 0 0 0 0 0 0 0 8 3 3 0 999999999 0 8 8 0 3 0 0 0 0 0 0 0 0 1 0 0 999999999 0 3 0 0 1 0 0 0 0 0 0 0 0 3 8 0 999999999 0 0 0 0 3 0 0 0 0 0 0 0 0 8 3 0 999999999 0 0 0 0 3 0 0 0 0 0 0 1 0 0 0 0 999999999 0 0 1 0 0 0 0 0 0 0 0 3 0 0 0 0 999999999 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 999999999 0 1 0 0 0 0 0 0 0 0 0 3 0 1 1 0 999999999 0 0 0 0 0 0 0 0 0 0 0 3 0 1 1 0 999999999 ``` Here is how I created this matrix (C#): ``` private static int[,] CreateMatrix() { int A = 0; int B = 1; int C = 2; int D = 3; int E = 4; int F = 5; int G = 6; int H = 7; int I = 8; int J = 9; int K = 10; int L = 11; int M = 12; int N = 13; int O = 14; int P = 15; int[,] matrix = new int[16, 16]; matrix[A, B] = 1; matrix[A, C] = 1; matrix[B, D] = 3; matrix[B, E] = 1; matrix[C, D] = 3; matrix[C, F] = 1; matrix[D, H] = 8; matrix[E, G] = 1; matrix[E, H] = 3; matrix[F, H] = 3; matrix[F, I] = 1; matrix[G, J] = 3; matrix[G, L] = 1; matrix[H, J] = 8; matrix[H, K] = 8; matrix[H, M] = 3; matrix[I, K] = 3; matrix[I, N] = 1; matrix[J, O] = 3; matrix[K, P] = 3; matrix[L, O] = 1; matrix[M, O] = 1; matrix[M, P] = 1; matrix[N, P] = 1; matrix[B, A] = 1; matrix[C, A] = 1; matrix[D, B] = 3; matrix[E, B] = 1; matrix[D, C] = 3; matrix[F, C] = 1; matrix[H, D] = 8; matrix[G, E] = 1; matrix[H, E] = 3; matrix[H, F] = 3; matrix[I, F] = 1; matrix[J, G] = 3; matrix[L, G] = 1; matrix[J, H] = 8; matrix[K, H] = 8; matrix[M, H] = 3; matrix[K, I] = 3; matrix[N, I] = 1; matrix[O, J] = 3; matrix[P, K] = 3; matrix[O, L] = 1; matrix[O, M] = 1; matrix[P, M] = 1; matrix[P, N] = 1; for (int i = 0; i < 16; i++) { for (int j = 0; j < 16; j++) { if (matrix[i, j] == 0) matrix[i, j] = 0; if (i == j) matrix[i, j] = 999999999; } } return matrix; } ``` Any help would be appreciated!! Graph that this matrix represents:

Original source