Anda di halaman 1dari 13

TCS1011 Data Structures and Algorithms

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.

TCS1011 Data Structures and Algorithms

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 }

TCS1011 Data Structures and Algorithms

Lab12

b) In

the

main.cpp

file,

implement

the

Dijkstras

shortestPath(Digraph digraph, int originVertex)"

algorithm for " void method. Hint: Use the

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:

TCS1011 Data Structures and Algorithms


int v, w, weight; Edge(int firstVertex, int secondVertex, int edgeWeight) { v = firstVertex; w = secondVertex; weight = edgeWeight; } // end constructor }; // end Edge // End of header file #endif /** @file Graph.h */ #ifndef _GRAPH_H #define _GRAPH_H #include #include #include #include <vector> <list> <map> "Edge.h"

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.

TCS1011 Data Structures and Algorithms


* @return The weight of the edge parameter. */ int getWeight(Edge e) const; /** Creates an edge in the graph. * @pre The vertices exist in the graph. * @post Adds to both v and w's list. */ void add(Edge e); /** Removes an edge from the graph. * @pre The vertices exist in the graph. * @post Removes edges from both v and w's list. */ void remove(Edge e); /** 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 Graph // End of header file #endif /** @file Graph.cpp * An adjacency list representation of an undirected, * weighted graph. */ #include "Graph.h" Graph::Graph(int n) { map<int, int> element; adjList.assign(n+1, element); numVertices = n; numEdges = 0; } // end constructor int Graph::getNumVertices() const { return numVertices; } // end getNumVertices int Graph::getNumEdges() const { return numEdges; } // end getNumEdges int Graph::getWeight(Edge e) const { return e.weight; } // end getWeight void Graph::add(Edge e) { int v = e.v, w = e.w,

Lab12

TCS1011 Data Structures and Algorithms


weight = e.weight; adjList[v].insert(make_pair(w, weight)); adjList[w].insert(make_pair(v, weight)); numEdges++; // end add

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);

TCS1011 Data Structures and Algorithms


/** 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. * @return The weight of the edge parameter. */ int getWeight(Edge e) const; /** Creates an edge in the graph. * @pre The vertices exist in the graph. * @post Adds to both v and w's list. */ void add(Edge e); /** Removes an edge from the graph. * @pre The vertices exist in the graph. * @post Removes edges from both v and w's list. */ void remove(Edge e);

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;

TCS1011 Data Structures and Algorithms


outVertexList.assign(n+1, element); inVertexList.assign(n+1, element); numVertices = n; numEdges = 0; // end constructor

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--;

TCS1011 Data Structures and Algorithms


} // remove all in edges to vertex v for (iter = mInToV.begin(); iter != mInToV.end(); ++iter) { inVertexList[v].erase(iter->first); outVertexList[iter->first].erase(v); numEdges--; } } numVertices--; // end remove

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"

#include #include #include #include #include #include #include #include

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);

TCS1011 Data Structures and Algorithms


graph.add(edge_3_4); graph.add(edge_3_5); graph.add(edge_4_7); graph.add(edge_4_8); graph.add(edge_5_7); graph.add(edge_6_7); } // Determines a MST for a weighted connected, // undirected graph whose weights are nonnegative, // beginning with any vertex v void primsAlgorithm(Graph graph, int v) { char vertexLabel[graph.getNumVertices()+1]; for (int i=1; i<graph.getNumVertices()+1; ++i) { vertexLabel[i] = 'a'+ i - 1; } vector<bool> markedVertex(graph.getNumVertices()+1, false); vector<int> visitedVertex; // Mark vertex v as visited and include it in the MST markedVertex[v] = true; visitedVertex.push_back(v); vector<Edge> edges; map<int, int> m; //holds adjacency list of current vertex map<int, int>::iterator mapIter; // TODO: Begin practice question (a)

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

TCS1011 Data Structures and Algorithms

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

TCS1011 Data Structures and Algorithms

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)

// End question } int main() { Graph graphFig13_22(9); initGraphFig13_22(graphFig13_22); primsAlgorithm(graphFig13_22, 1);

TCS1011 Data Structures and Algorithms


cout << endl; Digraph graphFig13_24(5); initDigraphFig13_24(graphFig13_24); shortestPath(graphFig13_24, 1); } return 0;

Lab12

Anda mungkin juga menyukai