Graph: Simple implementation non-linear data structure with Go

wahyurudiyan

Wahyu Rudiyan Saputra

Posted on January 4, 2024

Graph: Simple implementation non-linear data structure with Go

Brief of Graph

Graph is a non-linear data structure in programming. This data structure commonly implemented for short-path-finding and often use to validate programming skill in a Software Engineer job.

Graph built with connection nodes or commonly called Vertex, each connected Vertex called Edge, and distance of edge usually called Adjacent.

Simple graph

The Algorithm

First of all, you need to define the data storage, let's use Golang struct.

type Graph struct {
    Vertice []*Vertex
}

type Vertex struct {
    Key      int
    Adjacent []*Vertex
}

func isExist(key int, vertices []*Vertex) bool {
    for _, v := range vertices {
        if v.Key == key {
            return true
        }
    }

    return false
}
Enter fullscreen mode Exit fullscreen mode

There are two data types defined that called Graph and Vertex. The Graph is base data type that store all Vertices that inputted in the main code in the future. Then Vertex defined to store the Key and all Adjacent.

In the section below the definition of types, the isExist function written to validate is inputted Key exist in vertices or not. We need to check the key to avoid duplicated inserted key into vertices.

Now, let's write a method of type of Graph to add the Vertices. This method consist of:

  1. Check is the Key exists?
  2. Add Key into graph vertices.
func (g *Graph) AddVertex(vertex int) error {
    // Check is vertex available
    if isExist(vertex, g.Vertice) {
        return fmt.Errorf("vertex is exist")
    }

    // Insert vertex into graph
    g.Vertice = append(g.Vertice, &Vertex{
        Key: vertex,
    })

    return nil
}
Enter fullscreen mode Exit fullscreen mode

At this moment, we can add the vertex into our struct, but we need to get it. Let's write the GetVertex method in our code. We just need to get our vertex by it's key that inserted before. If the key is match, return the vertex from vertices.

func (g *Graph) GetVertex(vertex int) *Vertex {
    for i, v := range g.Vertice {
        if v.Key == vertex {
            return g.Vertice[i]
        }
    }

    return nil
}
Enter fullscreen mode Exit fullscreen mode

Remember, we need to connect the vertex and to set the Edge and append the destination vertex into adjacent of current vertex. So, the logic suppose like this:

  1. Get the current Vertex (from Vertex) and destination vertex. If it's not exist, return error.
  2. Check the destination vertex in current adjacent is exist or not. It should be doesn't exist.
  3. If everything okay, let's insert destination vertex into current adjacent.
func (g *Graph) AddEdge(from int, dest int) error {
    // Check is vertext exists
    fromVertex := g.GetVertex(from)
    destVertex := g.GetVertex(dest)
    if fromVertex == nil || destVertex == nil {
        return fmt.Errorf("vertex from (%v) --> (%v) is not valid", from, dest)
    }

    // Check is adjacent vertex exists or not
    if isExist(destVertex.Key, fromVertex.Adjacent) {
        return fmt.Errorf("edge from vertex (%v) --> (%v) already exists", fromVertex.Key, destVertex.Key)
    }

    // insert new adjacent for from and dest vertex
    fromVertex.Adjacent = append(fromVertex.Adjacent, destVertex)
    return nil
}
Enter fullscreen mode Exit fullscreen mode

Finally, everything is set, and we need to print all vertex and its adjacent, let's write the code.

func (g *Graph) Print() {
    for _, val := range g.Vertice {
        fmt.Printf("(%v): ", val.Key)
        for i, adj := range val.Adjacent {
            if i > 0 {
                fmt.Printf(" -> ")
            }
            fmt.Printf("(%v)", adj.Key)
        }
        fmt.Println()
    }
}
Enter fullscreen mode Exit fullscreen mode

Let's run the code

To run these code, we need to write the main function.

func main() {
    graph := &Graph{}
    graph.AddVertex(0)
    graph.AddVertex(1)
    graph.AddVertex(2)
    graph.AddVertex(3)
    graph.AddVertex(4)
    graph.AddVertex(5)
    graph.AddVertex(6)

    // Set the edges
    graph.AddEdge(0, 1)
    graph.AddEdge(0, 2)
    graph.AddEdge(0, 5)

    graph.AddEdge(1, 0)
    graph.AddEdge(2, 0)
    graph.AddEdge(5, 0)

    graph.AddEdge(2, 1)
    graph.AddEdge(2, 3)
    graph.AddEdge(2, 6)

    graph.AddEdge(1, 2)
    graph.AddEdge(3, 2)
    graph.AddEdge(6, 2)

    graph.AddEdge(6, 5)
    graph.AddEdge(5, 6)

    graph.Print()
}
Enter fullscreen mode Exit fullscreen mode

Output:

(0): (1) -> (2) -> (5)
(1): (0) -> (2)
(2): (0) -> (1) -> (3) -> (6)
(3): (2)
(4): 
(5): (0) -> (6)
(6): (2) -> (5)
Enter fullscreen mode Exit fullscreen mode

For the full code, please look at my gists here: Graph Gists

💖 💪 🙅 🚩
wahyurudiyan
Wahyu Rudiyan Saputra

Posted on January 4, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related