Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adjacency list and graph

Tags:

algorithm

ruby

I'm trying to build a graph by adjacency list, which means I need a list for all the nodes, and inside every node class, I also need a data structure to hold all the adjacent nodes. Just wondering what the best structure would be to do this (a fast search for target node class). Would an array work?

like image 564
flint_stone Avatar asked Oct 04 '12 05:10

flint_stone


People also ask

What is an adjacency list in a graph?

In graph theory and computer science, an adjacency list is a collection of unordered lists used to represent a finite graph. Each unordered list within an adjacency list describes the set of neighbors of a particular vertex in the graph.

How do you draw a graph using adjacency list?

In Adjacency List, we use an array of a list to represent the graph. The list size is equal to the number of vertex(n). Adjlist[0] will have all the nodes which are connected to vertex 0. Adjlist[1] will have all the nodes which are connected to vertex 1 and so on.

What is use of adjacency list in data structure?

An adjacency list represents a graph as an array of linked lists. The index of the array represents a vertex and each element in its linked list represents the other vertices that form an edge with the vertex.

What is stored in an adjacency list?

In general, an adjacency list consists of an array of vertices (ArrayV) and an array of edges (ArrayE), where each element in the vertex array stores the starting index (in the edge array) of the edges outgoing from each node. The edge array stores the destination vertices of each edge (Fig.


1 Answers

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(' ')}]"
  end

end

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]
  end

end

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.new
graph.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]
like image 115
Wayne Conrad Avatar answered Oct 21 '22 03:10

Wayne Conrad