Lab12 Data Struct Programming
Lab12 Data Struct Programming
Lab12
Lab 12 Graphs 2
Objectives
(a) Finds a minimum spanning tree using ADT Graph and Prims Algorithm. (b) Finds the shortest paths between any two vertices using ADT Digraph and Dijkstras algorithm.
Theory
(20 minutes)
Question 1 [Minimum Spanning Tree using Prims Algorithm]: Based on the weighted, connected, undirected graph as shown below, finds a minimum spanning tree using Prims algorithm beginning at vertex a.
Lab12
Question 2 [Shortest Path using Dijkstras Algorithm]: Based on the weighted directed graph as shown below, complete the trace of the following shortest path table using Dijkstras algorithm beginning at vertex 1. The first and second steps are already been filled in for you. Fill in the last three steps.
Step 1 2 3 4 5
v 5
dad 1
[1] 0 0
[2] 8 8
weight [3] 5
[4] 9 9
[5] 4 4
Practice
(30 + 50 minutes)
Complete the following tasks based on the given Edge.h, Graph.h, Graph.cpp, Digraph.h, Digraph.cpp and main.cpp files as shown below. Write your code only in places indicated between "TODO: Begin practice question" and "End question". Note that the given C++ ADT Graph and ADT Digraph that have been modified from the textbook begin their vertex with index 1 and not index 0. a) In the main.cpp file, implement
primsAlgorithm(Graph graph, int v)"
the Prims algorithm for " void method. Hint: Use the pseudocode given
below to implement Prims algorithm. primsAlgorithm(in graph:Graph, in v:Vertex) Mark vertex v as visited and include it in the minimum spanning tree while (there are unvisited vertices) { Find the least-cost edge (v, u) from a visited vertex v to some unvisited vertex u Mark u as visited Add the vertex u and the edge (v, u) to the minimum spanning tree }
Lab12
b) In
the
main.cpp
file,
implement
the
Dijkstras
pseudocode given below to implement Dijkstras algorithm. shortestPath(in digraph:Digraph, in v:Vertex) Create a set vertexSet that contains only vertex v n = number of vertices in the digraph for (vtx = 1 through n) weight[vtx] = matrix[v][vtx] for (step = 2 through n) { Find the smallest weight[vtx] such that vtx is not in vertexSet Add vtx to vertexSet for (all vertices u not in vertexSet) if ( weight[u] > weight[vtx] + matrix[vtx][u] ) weight[u] = weight[vtx] + matrix[vtx][u] } Expected Output for the above two tasks:
/** @file Edge.h */ #ifndef _EDGE_H #define _EDGE_H /** @class Edge * An Edge class for graph implementations. */ class Edge { public:
Lab12
using namespace std; /** An adjacency list representation of an undirected, * weighted graph. */ class Graph { public: int numVertices; /** Number of vertices in the graph. */ int numEdges; /** Number of edges in the graph. */ /** Adjacency list representation of the graph; * the map pair consists of the second vertex (key) * and the edge weight (value). */ vector<map<int, int> > adjList; /** Constructor. * @pre The graph is empty. * @post The graph is initialized to hold n vertices. */ Graph(int n); /** Determines the number of vertices in the graph. * @pre None. * @post None. * @return The number of vertices in the graph. */ int getNumVertices() const; /** Determines the number of edges in the graph. * @pre None. * @post None. * @return The number of edges in the graph. */ int getNumEdges() const; /** Determines the weight of an edge. * @pre The edge exists in the graph. * @post None.
Lab12
Lab12
void Graph::remove(Edge e) { int v = e.v, w = e.w, weight = e.weight; adjList[e.v].erase(w); adjList[e.w].erase(v); numEdges--; // end remove
map<int, int>::iterator Graph::findEdge(int v, int w) { map<int, int> m = adjList[v]; map<int, int>::iterator iter = m.find(w); } return iter; // end findEdge
/** @file Digraph.h */ #ifndef _DIGRAPH_H #define _DIGRAPH_H #include #include #include #include <vector> <list> <map> "Edge.h"
using namespace std; /** An adjacency list representation of a directed, * weighted graph. */ class Digraph { public: int numVertices; /** Number of vertices in the graph. */ int numEdges; /** Number of edges in the graph. */ /** Adjacency list representation of the graph; * the map pair consists of the second vertex (key) * and the edge weight (value). */ vector<map<int, int> > outVertexList; vector<map<int, int> > inVertexList; /** Constructor. * @pre The graph is empty. * @post The graph is initialized to hold n vertices. */ Digraph(int n);
Lab12
/** Removes a vertex and its edges from the graph * @pre The vertex v is existed in the graph. * @post The vertex v is removed from the graph. * Clients must labelled the removed vertex by themselves. */ void remove(int v); /** Finds the edge connecting v and w. * @pre The edge exists. * @post None. * @return An iterator to map key w in vector[v]. */ map<int, int>::iterator findEdge(int v, int w); }; // end Digraph // End of header file #endif /** @file Digraph.cpp * An adjacency list representation of a directed, * weighted graph. */ #include "Digraph.h" using namespace std; Digraph::Digraph(int n) { map<int, int> element;
Lab12
int Digraph::getNumVertices() const { return numVertices; } // end getNumVertices int Digraph::getNumEdges() const { return numEdges; } // end getNumEdges int Digraph::getWeight(Edge e) const { return e.weight; } // end getWeight void Digraph::add(Edge e) { int v = e.v, w = e.w, weight = e.weight; outVertexList[v].insert(make_pair(w, weight)); inVertexList[w].insert(make_pair(v, weight)); numEdges++; // end add
void Digraph::remove(Edge e) { int v = e.v, w = e.w, weight = e.weight; outVertexList[e.v].erase(w); inVertexList[e.w].erase(v); numEdges--; // end remove
void Digraph::remove(int v) { map<int, int> mOutFromV = outVertexList[v]; map<int, int> mInToV = inVertexList[v]; map<int, int>::iterator iter; // remove all out edges from vertex v for (iter = mOutFromV.begin(); iter != mOutFromV.end(); ++iter) { outVertexList[v].erase(iter->first); inVertexList[iter->first].erase(v); numEdges--;
Lab12
// uses either outVertexList or inVertexList method, choose only one map<int, int>::iterator Digraph::findEdge(int v, int w) { map<int, int> m = outVertexList[v]; map<int, int>::iterator iter = m.find(w); } return iter; // end findEdge <iostream> <vector> <list> <queue> <stack> "Edge.h" "Graph.h" "Digraph.h"
using namespace std; void initGraphFig13_22(Graph& graph) { // 9 vertices and 11 edges // this ADT Graph is an undirected weighted graph class // do not need to specify edges for both directions // the code below is based on theory question 1 figure Edge edge_1_2(1,2,6); Edge edge_1_6(1,6,4); Edge edge_1_9(1,9,2); Edge edge_2_3(2,3,7); Edge edge_2_5(2,5,9); Edge edge_3_4(3,4,4); Edge edge_3_5(3,5,3); Edge edge_4_7(4,7,5); Edge edge_4_8(4,8,1); Edge edge_5_7(5,7,8); Edge edge_6_7(6,7,2); graph.add(edge_1_2); graph.add(edge_1_6); graph.add(edge_1_9); graph.add(edge_2_3); graph.add(edge_2_5);
Lab12
// End question int totalCost = 0; cout << "The result of a Prim's algorithm beginning at vertex " << v << ":" << endl; for (int i=0; i<static_cast<int>(edges.size()); ++i) { cout << "edge ("<< vertexLabel[edges[i].v] << ", " << vertexLabel[edges[i].w] << ") " << "costs " << edges[i].weight << endl; totalCost = totalCost + edges[i].weight; } cout << "Total cost = " << totalCost << endl; } void initDigraphFig13_24(Digraph& digraph) { // 5 vertices and 9 edges // this ADT Digraph is a directed graph class // all the edges in the digraph are directed // the code below is based on theory question 2 figure
Lab12
Edge edge_1_2(1,2,8); Edge edge_1_4(1,4,9); //Edge edge_4_1(4,1,9); Edge edge_1_5(1,5,4); Edge edge_2_3(2,3,1); Edge edge_3_2(3,2,2); Edge edge_3_4(3,4,3); Edge edge_4_3(4,3,2); Edge edge_4_5(4,5,7); Edge edge_5_3(5,3,1); digraph.add(edge_1_2); digraph.add(edge_1_4); //digraph.add(edge_4_1); digraph.add(edge_1_5); digraph.add(edge_2_3); digraph.add(edge_3_2); digraph.add(edge_3_4); digraph.add(edge_4_3); digraph.add(edge_4_5); digraph.add(edge_5_3); } // Finds the min cost paths btwn an origin vertex // (eg: vertex 1) and all other vertices in a weighted directed // graph theGraph; theGraph's weights are nonnegative void shortestPath(Digraph digraph, int originVertex) { // Create a set vertexSet that contains only originVertex (vertex 1) int n = digraph.getNumVertices(); int weight[n+1]; weight[originVertex] = 0; for (int v=1; v<=n; ++v) { if (v != originVertex) weight[v] = numeric_limits<int>::max(); } map<int, int> m; //holds adjacency list of current vertex map<int, int>::iterator mapIter; //a pointer to map<int,int> m = digraph.outVertexList[originVertex]; for (mapIter = m.begin(); mapIter != m.end(); ++mapIter) { weight[mapIter->first] = mapIter->second; } int dad[n+1]; for (int v=1; v<=n; ++v) { dad[v] = -1; //unknown initially } cout << "The result of the shortest-path algorithm " << endl; cout << "beginning at vertex " << originVertex << ":" << endl; // print the first step of the shortest path table
Lab12
cout << " weight" << endl; cout << "Step\t" << " v\t" << "dad\t"; for (int v=1; v<=n; ++v) { cout << "[" << v << "]\t"; } cout << endl; for (int v=1; v<=n+3; ++v) { cout << "----\t"; } cout << endl; cout << "1 \t -\t -\t"; for (int v=1; v<=n; ++v) { if (weight[v] == numeric_limits<int>::max()) { cout << "inf" << "\t"; } else { cout << " " << weight[v] << "\t"; } } cout << endl; vector<bool> markedVertexSet(digraph.getNumVertices()+1, false); vector<int> visitedVertexSet; // Mark vertex originVertex as visited and // include it in the shortest path visitedVertexSet markedVertexSet[originVertex] = true; visitedVertexSet.push_back(originVertex); // TODO: Begin practice question (b)
Lab12