Adjacency list and graph Adjacency list and graph ruby ruby

Adjacency list and graph


Here's one way of building a directed graph in Ruby, where each node maintains references to its successors, but nodes can be referenced by name. First we'll need a class for the nodes:

class Node  attr_reader :name  def initialize(name)    @name = name    @successors = []  end  def add_edge(successor)    @successors << successor  end  def to_s    "#{@name} -> [#{@successors.map(&:name).join(' ')}]"  endend

Each node maintains references to its successors. Not knowing what kind of operations you need, I haven't defined any that actually do graph traversal, but each node having references to its successors makes traversing the graph trivial.

Now we'll create a class to represent the entire graph:

class Graph  def initialize    @nodes = {}  end  def add_node(node)    @nodes[node.name] = node  end  def add_edge(predecessor_name, successor_name)    @nodes[predecessor_name].add_edge(@nodes[successor_name])  end  def [](name)    @nodes[name]  endend

This class keeps a hash of its nodes, keyed by name. This makes retrieval of a specific node easy.

Here's an example of a graph containing a cycle:

graph = Graph.newgraph.add_node(Node.new(:a))graph.add_node(Node.new(:b))graph.add_node(Node.new(:c))graph.add_edge(:a, :b)graph.add_edge(:b, :c)graph.add_edge(:c, :a)puts graph[:a]    #=> a -> [b]puts graph[:b]    #=> b -> [c]puts graph[:c]    #=> c -> [a]