Skip to content

Latest commit

 

History

History

GraphMatrix

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 

GraphMatrix

A graph matrix is a way of representing a graph data structure. This can be done in two common ways, either using an adjacency matrix or a distance matrix. Depending on what you want/need to do you would use one over the other.

For example, if I wanted to graph out flights in the United States, I could simply use an adjacency matrix:

MCO SFO LAX JFK
MCO 0 1 1 1
SFO 1 0 0 0
LAX 1 0 0 0
JFK 1 0 0 0

Here we graph out whether or not we can go from one airport to another. A 1 means theres a connection and a 0 means theres no connection. We assume there are no self loops, as this wouldn't make much sense for an airport to depart and land at the same place in one trip. Our graph above is also undirected thus we can go from either LAX to JFK or from JFK to LAX, which makes sense in the real world context.

A distance matrix, works similarly except we can measure or weigh out our edges. This type of matrix is helpful when we want to find, for example, the shortest path between two cities, or how much it costs for a trip from LAX to JFK:

MCO SFO LAX JFK
MCO -1 330 200 420
SFO 450 -1 -1 -1
LAX 600 -1 -1 -1
JFK 911 -1 -1 -1

In the above, we are again, undirected. We also represent no connections with -1 for example since this makes some-what sense since hopefully our airport isn't returning money instead of making it.

In programming we can represent the above data-structures using a 2-D array. We can check if there is a connection from MCO to LAX by checking if array[0][2] == 1 since if there is a 1 in that location there is a connection between LAX and MCO. For an undirected graph we can even save some space, if we assume there are no self loops. We could, instead of storing the full 2-D array store only the top or bottom half. This is because as you can see in the adjacency matrix above, there are a lot of duplicate/wasted space across the diagonal and for undirected locations.

A simple implementation of this data structure is implemented in JavaScript here:

class GraphMatrix {
    // Constructs an GraphMatrix with a given nodes array
    // Each element in nodes must be hashable
    // You can also specify the type of graph, either directed or
    // undirected. By default the graph is directed.
    constructor(nodes = [], type = "directed") {
        this.type = type

        // Init nodes map
        this.nodes = new Map()
        for (let i = 0; i < nodes.length; ++i)
            this.nodes.set(nodes[i], i)

        // Init adjacency matrix
        this.data = new Array(nodes.length)
        for (let i = 0; i < nodes.length; ++i) {
           this.data[i] = new Array(nodes.length)
          for (let j = 0; j < nodes.length; ++j)
              this.data[i][j] = 0
        }
    }

    // Returns whether node a is connected to node b
    isConnected(nodeA, nodeB) {
        if (this.nodes.length == 0) return false
        let indexA = this.nodes.get(nodeA), indexB = this.nodes.get(nodeB)
        return this.data[indexA][indexB] == 1
    }

    // Inserts a node into the graph
    insert(node) {
        this.nodes.set(node, this.nodes.size)
        this.data.push(new Array(this.nodes.size).fill(0))
        // Fix other rows
        for (let i = 0; i < this.nodes.size - 1; ++i)
            this.data[i].push(0)
    }

    // Conncets nodeA with nodeB
    // Nodes must exist in the graph already.
    connect(nodeA, nodeB) {
        let indexA = this.nodes.get(nodeA), indexB = this.nodes.get(nodeB)
        this.data[indexA][indexB] = 1
        if (this.type == "undirected")
          this.data[indexB][indexA] = 1
    }
}

A live demo can be found here