Chapter 3.3: Implementing Graph Traversal w/Queues and Stacks

The BFS and DFS algorithms differ essentially only in that one uses a queue in its implementation and the other uses a stack.

There are two basic ways to represent a graph: using an adjacency matrix or an adjacency list.

Adjacency Matrix: Consider a graph G=(V,E) with n nodes and assume the set of nodes is V={1,…,n}. An adjacency matrix is an nxn matrix A where A[u,v] is equal to 1 if the graph contains the edge (u,v) and 0 otherwise. If the graph is undirected, A is symmetric with A[u,v]=A[v,u] for all nodes u and v in V. The adjacency matrix allows us to check in O(1) time if a given edge (u,v) is present in the graph. However:

  • The matrix takes θ(n^2) space which is not good if the graph has a lot fewer edges than n^2
  • Many graph algorithms need to examine all edges incident to a given node v. In an adjacency matrix, this involves considering all other nodes w, and checking the entry A[v,w] to see whether edge (v,w) is present. This takes θ(n) time.

Adjacency List: In this representation, there is a record for each node v, containing a list of all nodes to which v has edges. In other words, we have an array Adj where Adj[v] is a record containing a list of all nodes adjacent to node v. For an undirected graph G=(V,E), each edge e=(v,w) in E occurs on two adjacency lists, node w appears on the list for node v and node v appears on the list for node w.

  • The list takes O(n+m) space

A queue is a set from which we extract elements in first-in, first-out (FIFO) order; we select elements in the same order in which they were added. A stack is a set from which we extract elements in last-in, first-out (LIFO) order; each time we select an element, we choose the one that was added most recently. Both queues and stacks can be implemented via a doubly linked list. In both cases, we select the first element in the list, the difference is where we insert a new element. In a queue, we insert a new element at the end of the list as the last element, whereas in a stack we insert a new element in the first position on the list. Doubly linked lists have FIRST and LAST pointers, so insertion can be done in constant time.

Implementing BFS

  • Set Discovered[s] = true and Discovered[v] = false for all other v
  • Initialize L[0] to consist of the single element s
  • Set the layer counter i = 0
  • Set the current BFS tree T = {}
  • While L_i is not empty:
  • Initialize and empty list L[i+1]
  • For each node u in L[i]
  • Consider each edge (u,v) incident to u
  • If Discovered[u] = false then:
  • Set Discovered[v] = true
  • Add edge (u,v) to the tree T
  • Add v to the list L[i+1]
  • End if
  • End for
  • Increment the layer counter i by 1
  • End while

This implementation runs in O(n+m) time.

Implementing DFS

  • Initialize S to be a stack with one element s
  • While S is not empty:
  • Take a node u from S
  • If Explored[u] = false then:
  • Set Explored[u] = true
  • For each edge (u,v) incident to u
  • Add v to the stack S
  • End for
  • End if
  • End while

This implementation runs in O(n+m) time.

courses/cs211/winter2014/journals/alyssa/chapter_3.3.txt · Last modified: 2014/01/27 18:36 by hardnetta
CC Attribution-Noncommercial-Share Alike 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0