CISC4080, Computer Algorithms,
Lab 5

     

Home

Schedule

Assignments

Grading

 

Goal

We will study:

  1. Practice implementing two graph search algorithms: depth-first, and breadth-first.
  2. Practice using graph algorithms to solve problems.

Using C++ STL classes

  1. The sample graph class uses vector and list. They are container classes implemented using dynamic array and linked list as learned in data structure. Here are some beginners guide if you need more explanation and example other than the documents (yolinux tutorials for C++ STL library).
  2. You should also use queue while implementing BFS.
  3. Here is an example code demonstrating both reading from a text file and using STL map class:map_example.cpp.
    cp ~zhang/public_html/cs4080/Demo/map_example.cpp . 
    cp ~zhang/public_html/cs4080/Demo/article.txt . 
    

Graph Representation

You are free to start your project following any of the three options below:

  1. Use provided template class (graph.cpp, graph.h and graph_driver.cpp), which you can copy to your directory using the following command:
    cp ~zhang/public_html/cs4080/Demo/Graph*.* . 
    
    To compile, use the following command (note that Graph_driver.cpp include Graph.cpp):
    g++ Graph_driver.cpp 
    
    The above command will copy the following files to your current directory( Graph.h, Graph.cpp, Graph_driver.cpp). Note that for template class (or class template), you need to include the implementation file in the driver file.. (Here is a post explainning why that's the case, and another one is here.)
    //Implement Graph as a template class -- allow us to use it to create
    // graph where the nodes are of different type: string, int, char, 2D array ...
    template <class NodeType>
    class Graph{
    public:
    	... 
    private:
    	bool directed; //true: directed graph, false: undirected graph 
    
    	vector<NodeType> nodes; //vector is a container class like that
    	 //"unsorted list implemented using dynamic array" learned in data structure
    	 // it overload [] operator, so you can access it like accessing array
    
    	//The following is adjacency lists 
    	//    edges[i] is adjacency list for nodes[i], storing
    	//   the index of node that node i is connected to 
    	//
    	//for undirected graph, we store each edge twice, for example,
    	// if node a and b are connected by an edge, 
    	//   b is in the adjacent list of a, and a is in the adjacent list of b
    	vector<list<int>> edges; 
    
    };
    
  2. Use provided regular (non-template) class (StringGraph.h, StringGraph.cpp, StringGraph_driver.cpp) as your starting point. Chooce this option if you are not yet familiar with syntax of template functions/class. Use the following command to copy the codes:
    cp ~zhang/public_html/cs4080/Demo/StringGraph*.* . 
    
    To compile, use the following command:
    g++ StringGraph_driver.cpp StringGraph.cpp
    
  3. Define your own graph class and implement your own methods (constructors, destructor, AddEdge, AdjacenttNodes...).

Requirements:

The following direction assume you pick option #1 (template graph class). If you chooce option #2 (a non-template graph), you want to change all NodeType below to string.

  1. (Provided) Based upon the BFS algorithm discussed in class, implement it as member functions of the graph class, test them on simple graphs.
    	//Explore and visit all vertices of the graph that are 
    	//reachable from node s in BFS order 
    	// When finish: Display
    	//     * the depth of all reachable vertices (i.e., shortest distance to s)
    	//     * the predecessors of all reachable vertices (BFS tree) 
    	void BFS_Explore (NodeType s);
    	
    	
    Hint: Feel free to use an array or a C++ STL map to represent depth, predecessor, and color used in BFS. The code segment below illustrates how to illusrtate the color look-up table.
    		typedef enum Color{
                       White=0,
                       Gray=1,
                       Black=2
    		} Color;
    		
    		map<NodeType,Color> colors;
    
    		// initialize all nodes' colors to white
    		for (int i=0;i<nodes.size();i++)
    		{
                        colors[nodes[i]]=White;
    		}
    			
  2. Update the BFS_Explore member function, so that the depth and predecessor (i.e., d and pred) information are passed back to the caller as pass-by-reference parameters.
  3. Write a member function as follows that finds the shortest hop path from a given node to another node
    	/* find shortest hop path from node s to node t 
    	  Note: call BFS_Explore() and then use predecessor info to find the path 
    	    that leads to node t (from s)
    	 postcondition: 
    	    if there is a path from s to t, then 
    	          path[0]==s, path[path.size()-1]==t 
    	     if there is no path, then path.size()==0
             */
    	void ShortestHopPath (NodeType s, NodeType t, vector<NodeType> & path)
    
    	
  4. Use the graph in the slides (illustrating BFS) to test the above BFS traversal.
  5. Write the member function for graph as below to test if a sequence of nodes forms a path/cycle (Please refer to slides for definitions of both.)
    	/* Check if the given sequence of nodes is a path of the graph
    	@param: vector<NodeType> nodes
    	@param: isCycle is set to true if the sequence of nodes is a cycle 
    	@return true if n[0],n[1],...n[n.size()-1] is a path, false otherwise
    	*/
    	bool IsPath (vector<NodeType> n, bool & isCycle)
    
    	
  6. Write a member function that initializes a graph from a textfile. Please refer to this sample code for how to open and read from a text file. Test your BFS algorithms on the following two graphs: directed graph test case, undirected graph test case.
    class Graph{
    public:
          Graph() 
          {directed=false;}
          ... 
          /* the text file specify a graph as follows:
          true
          5 A B C D E 
          A -> B
          C -> D
          e -> A
          */
          void InitializeFromFile(string fileName){
    	/* open the file to read 
    	   read a string, if it's "true" set directed to true;
    	                  if it's "false", set directed to false.
    	   read an integer value (the number of vertices in the graph) 
    	   for loop to read the given number of node 
    		for each node read in, store it in "nodes" vector,
    		 and push an empty list<int> into the "edges" vector. 
    		   
    
    	   read one edge a time (by reading one node, one string and another node)
    	   	and insert the edge into the graph by calling
    		AddEdge
    		*/
    		
          }
    
    

Submission

Please submit each source files, class specficiation file (header file) and implemenetation file (.cpp file), and driver program using the script given. For example,

submit4080 LAB5 Graph.cpp
submit4080 LAB5 Graph.h
submit4080 LAB5 Graph_driver.cpp
...