Copyright, 1997, Susan Anderson-Freed


Spanning Trees

A spanning tree is constructed by traversing the graph. Each node or vertex is visited once. If the graph contains n nodes, the spanning tree will contain n-1 edges.

There are two traversals for undirected graphs:
  1. Depth First Search. This traversal is similar to the preorder binary tree traversal.
  2. Breadth First Search. This traversal is similar to the level order binary tree traversal.

    We'll use our sample undirected graph to illustrate these traversals.

    A Sample Undirected Graph
          0      
         / \                  
         1  2                
         \ /                   
          3                     
          |                     
          4                    
         / \                    
        5   6                     
    


    The main() Function

    The portions of the main() function that apply to the traversals are highlighted.

    The main() function
    int main()
    /*  depth first and breadth first search of a graph */
    {
       int i;
       node_pointer graph[MAX_NODES];
       
       int n = 0; /* number of vertices currently in use */
    
       int choice = print_menu();
       while (choice !=5) {
          switch(choice) {
              case 1: create_list(graph,&n);
       	           break;
              case 2:  printf("The list has %d vertices in use.\n",n);
       		   print_list(graph, n);
       		   break;
              case 3:  start_depth_first(graph,n);
                       break;
              case 4:  breadth_first_search(0, graph,n);
             }
             printf("\n\n");
             choice = print_menu();
          }     
    }
    


    The depth first search

    The depth first search uses the following algorithm.

    1. Chose a starting vertex. Typically, this is the first vertex, Vertex 0.
    2. Mark this vertex as visited. Marking requires an auxiliary array. The array cells are initialized to 0 (false) for non-visted. When you visit a vertex you may mark it with a one (true) to indicate that the cell have been visited, or you may mark it with a number that indicates the order in which the vertex was visited, i.e., 1,2,3,etc. In our example, we'll mark the vertices as 0 or 1.
    3. Choose the first unvisited vertex from the current vertex's adjacency list. Continue the search with the new vertex's adjacency list.
    4. Continue this process until you reach a vertex that has no unvisited vertices in it adjacency list. At this point, back up to the adjacency list of the last vertex (on the stack).


    The depth first search is a stack algorithm and is usually implemented recursively. Prior to the first recursive call we must initialize the array that marks the vertices. We call this array, visited.

    The code that implements the initialization is called start_depth_first(). This function requires parameters representing the graph and the number of nodes in the graph. The code is found in the following table.

    The start_depth_first() function
    
    void start_depth_first(node_pointer graph[],int size)
    {
       int visited[MAX_NODES];
       int i;
       for (i = 0;  i < size;  i++)
           visited[i] = FALSE;
       printf("Depth first search: ");
       depth_first_search(0, graph, visited);
    }


    The depth_first_search() function

    The code for the depth first search is found in the following table. Notice that this search:
    1. Marks the node passed as a parameter as visited.
    2. Contains a statement that processes the node's adjacency list. This forstatement assigns node2 to point to the first block in node1's adjacency list. The depth_first_search() function is called recursively with node2. Because the recursive call is contained within the for statement, the function "remembers" the current position in each vertex's adjacency list.


    The depth_first_search() function
    void depth_first_search(int node1, node_pointer graph[], int visited[])
    {
    /* depth first traversal of a graph beginning with node1.  */
       node_pointer node2;
       visited[node1] = TRUE;
       printf("%5d",node1);
       for (node2 = graph[node1]; node2; node2 = node2->link)
          if (!visited[node2->vertex])
    	 depth_first_search(node2->vertex, graph, visited);
    }
    


    The program run with our sample graph is found in the following table.

    Depth First Search Test run
    Enter your choice: 3
    Depth first search:     0    2    3    4    6    5    1
    


    To understand how this search works, we must look at the adjacency lists. The following table contains the lists for our undirected graph.
    The adjacency lists
        vertex    Adjacency List
    
        0                 2  1
        1                 3  0
        2                 3  0
        3                 4  2  1
        4                 6  5  3
        5                 4
        6                 4
    


    The following list shows the action of the depth_first_search() function.
    1. Initial Call. The depth_first_search() function is called with vertex 0. This vertex is marked as visited. The for statement selects vertex 2 for the recursive call.

      Stack Selected Vertex Adjacency List
      ^0 2 1


    2. Second Call. Vertex 2 is marked as visited, and vertex 3 is selected for the next recursive call.

      Stack Selected Vertex Adjacency List
      ^2 3 0
      ^0 2 1


    3. Third Call Vertex 3 is marked as visited, and vertex 4 is selected for the next recursive call

      Stack Selected Vertex Adjacency List
      ^3 4 2 1
      ^2 3 0
      ^0 2 1


    4. Fourth Call Vertex 4 is marked as visited, and vertex 6 is selected for the next recursive call.

      Stack Selected Vertex Adjacency List
      ^4 6 5 3
      ^3 4 2 1
      ^2 3 0
      ^0 2 1


    5. Fifth Call Vertex 6 is marked as visited. The only vertex on six s adjacency list is four which was visited so four is popped from the stack

      Stack Selected Vertex Adjacency List
      ^6 NONE
      4 visited
      ^4 6 5 3
      ^3 4 2 1
      ^2 3 0
      ^0 2 1


    6. Vertex six is popped from the stack. The travesal continues with vertex four's adjacency list

      Stack Selected Vertex Adjacency List
      ^4 5 3
      ^3 4 2 1
      ^2 3 0
      ^0 2 1


    7. Vertex five is marked as visited. The only vertex on five's list is four which was previously visited. Five is popped from the stack.

      Stack Selected Vertex Adjacency List
      ^5 NONE
      ^4 5 5 3
      ^3 4 2 1
      ^2 3 0
      ^0 2 1


    8. Search returns to vertex four's adjacency list. Only vertex three remains. Since three was previously visisted, vertex 4 is popped from the stack.

      Stack Selected Vertex Adjacency List
      ^4 5 3
      ^3 4 2 1
      ^2 3 0
      ^0 2 1


    9. Search returns to vertex three's adjacency list. Links to vertex 2 and vertex 1 remain. Since vertex 2 was previously visited, vertex 1 is chosen.

      Stack Selected Vertex Adjacency List
      ^3 1 2 1
      ^2 3 0
      ^0 2 1


    10. Vetex 1 is marked as visited. Since each vertex in its list has been visited, the search would continue with vertex 3's list, then 2's then 0's. Since vertex 1 is the last vertex in the spanning tree, the for statement examines the lists and pops the vertices off of the stack.

      Stack Selected Vertex Adjacency List
      ^1 NONE 3 0
      ^3 1
      ^2 3 0
      ^0 2 1




    The following table shows the depth first spanning tree. The table shows only the finished tree, not the order in which the tree was built.

    Depth first Search for sample graph
          0      
          |                 
          2                 
          |                     
          3                     
         / \                    
        4   1                    
       / \                    
      6   5                     
    


    Spanning Trees may be built from and starting node. The following table shows spanning trees with different starting nodes.

    Vertex 3
         3 
       /  \ 
      4    2
     / \   |
    6   5  0
           |
           1     
    
    Vertex 4
       4  
     / | \ 
    6 5  3
         |
         2
         |
         0
         |
         1
    
    Vertex 5
     5
     |
     4
    / \ 
    6  3
       |
       2
       |
       0
       |
       1
    


    The breadth first search of an undirected graph

    The breadth first search of a graph is the graph equivalent of a level order tree traversal. The traversal:
    1. Initializes the visited array to FALSE
    2. Marks node1 as visited. (This is the node passes as the parameter.
    3. Adds node1's adjacency list to the queue
    4. Uses a while statement to:
      1. Delete a node from the queue
      2. Process each link in the deleted node's adjacency list. (The for statement takes care of this code.) If the vertex in the adjacency list has not been visited, it is:
        1. Marked as visited
        2. The vertex is printed to the screen
        3. The vertex's adjacency list is added to the queue.


    The following table contains the code for the breadth first search. The queue declarations appear in the previous Web page.

    The breadth_first_search() function
    void breadth_first_search(int node1, node_pointer graph[], int size)
    {
       int i;
       int visited [MAX_NODES];
       node_pointer node2;
       queue_pointer front,rear;
       
       for (i=0; i < size;  i++)
         visited[i] = FALSE;
       printf("\n\nBreadth first search:");
       
       front = rear = NULL; /* initialize queue */
       printf("%5d",node1);
       visited[node1] = TRUE;
       add_queue(&front,&rear,node1);
       while (front) {
          node1 = delete_queue(&front);
          for (node2 = graph[node1]; node2; node2 = node2->link)
    	if (!visited[node2->vertex]) {
    	   printf("%5d", node2->vertex);
    	   add_queue(&front,&rear,node2->vertex);
    	   visited[node2->vertex] = TRUE;
           }
        }
    }
    


    The following table contains a program run of the breath first search using Vertex 0 is the root of the spanning tree.

    Breadth First Search Test Run
    Enter your choice: 4
    
    Breadth first search:    0    2    1    3    4    6    5
    


    The spanning tree produced by this traversal appears in the following table.

    Depth first Search for sample graph
          0      
         / \                  
         2  1                
         |
         3                     
         |                     
         4                    
        / \                    
       6   5                     
    


    The following table shows the spanning trees produced from a breath first search with a root node.

    Vertex 3
         3 
       / | \ 
      4  2  1
     / \ |
    6  5 0 
    
    Vertex 4
       4  
     / | \ 
    6 5   3
         / \
        2   1
        |
        0
    
    Vertex 5
     5
     |
     4
    / \ 
    6  3
      / \
     2   1
     |
     0