440 likes | 614 Views
CSE331 - Lecture 22 & 23. 1. Main Index. Contents. Chapter 16 - Graphs Graph Categories Example of Digraph Connectedness of Digraph Adjacency Matrix Adjacency Set vertexInfo Object Vertex Map and Vector vInfo VtxMap and Vinfo Example Breadth-First Search Algorithm Dfs().
E N D
CSE331 - Lecture 22 & 23 1 Main Index Contents • Chapter 16 - Graphs • Graph Categories • Example of Digraph • Connectedness of Digraph • Adjacency Matrix • Adjacency Set • vertexInfo Object • Vertex Map and Vector vInfo • VtxMap and Vinfo Example • Breadth-First Search Algorithm • Dfs() • Strong Components • Graph G and Its Transpose GT • Shortest-Path Example • Dijkstra Minimum-Path Algorithm • Minimum Spanning Tree • Minimum Spanning Tree: vertices A and B • Completing the Minimum Spanning-Tree with Vertices C and D • Summary Slides
2 Main Index Contents Graph Categories • A graph is connected if each pair of vertices have a path between them • A complete graph is a connected graph in which each pair of vertices are linked by an edge
3 Main Index Contents Example of Digraph • Graph with ordered edges are called directed graphs or digraphs
4 Main Index Contents Connectedness of Digraph • Strongly connected if there is a path from any • vertex to any other vertex. • Weakly connected if, for each pair of vertices vi and vj, there is either a path P(vi, vj) or a path P(vi,vj).
5 Main Index Contents Adjacency Matrix • An m by m matrix, called an adjacency matrix, identifies the edges. An entry in row i and column j corresponds to the edge e = (vi, vj). Its value is the weight of the edge, or -1 if the edge does not exist.
6 Main Index Contents Adjacency Set (or List)
Neighbor object (edges to adjacent vertices) class neighbor { public: int dest; // index of destination vertex in vInfo vector int weight; // weight of this edge // constructor neighbor(int d=0, int c=0) : dest(d), weight(c) {} // operators to compare destination vertices friend bool operator< (const neighbor& lhs, const neighbor& rhs) { return lhs.dest < rhs.dest; } friend bool operator== (const neighbor& lhs, const neighbor& rhs) { return lhs.dest == rhs.dest; } };
8 Main Index Contents vertexInfo Object • A vertexInfo object consists of seven data members. The first two members, called vtxMapLoc and edges, identify the vertex in the map and its adjacency set.
9 Main Index Contents Vertex Map and Vector vInfo • To store the vertices in a graph, we provide a map<T,int> container, called vtxMap, where a vertex name is the key of type T. The int field of a map object is an index into a vector of vertexInfo objects, called vInfo. The size of the vector is initially the number of vertices in the graph, and there is a 1-1 correspondence between an entry in the map and a vertexInfo entry in the vector parent
vertexInfo object • vtxMapLoc – iterator to vertex (name) in map • edges – set of vInfo index / edge weight pairs • Each is an OUT edge to an adjacent vertex • vInfo[index] is vertexInfo object for adjacent vertex • inDegree – # of edges coming into this vertex • outDegree is simply edges.size() • occupied – true (this vertex is in the graph), false (this vertex was removed from graph) • color – (white, gray, black) status of vertex during search • dataValue – value computed during search (distance from start, etc) • parent – parent vertex in tree generated by search
vertexInfo object (items in vInfo vector) template <typename T> class vertexInfo { public: enum vertexColor { WHITE, GRAY, BLACK }; map<T,int>::iterator vtxMapLoc; // to pair<T,int> in map set<neighbor> edges; // edges to adjacent vertices int inDegree; // # of edges coming into vertex bool occupied; // currently used by vertex or not vertexColor color; // vertex status during search int dataValue; // relevant data values during search int parent; // parent in tree built by search // default constructor vertexInfo(): inDegree(0), occupied(true) {} // constructor with iterator pointing to vertex in map vertexInfo(map<T,int>::iterator iter) : vtxMapLoc(iter), inDegree(0), occupied(true) {} };
Graph object data items template <typename T> class graph { public: ~~~~~ member functions ~~~~ private: // vertex names and corresponding vInfo indices typedef map<T,int> vertexMap; vertexMap vtxMap; vector<vertexInfo<T> > vInfo; // info on each vertex int numVertices; // current # of vertices in graph int numEdges; // current # of edges in graph stack<int> availStack; // available (unused) vInfo indices };
Find location for vertexInfo of vertex with name v // uses vtxMap to obtain the index of v in vInfo // private helper function template <typename T> int graph<T>::getvInfoIndex(const T& v) const { vertexMap::const_iterator iter; int pos; // find the vertex : the map entry with key v iter = vtxMap.find(v); if (iter == vtxMap.end()) pos = -1; // wasn’t in the map else pos = (*iter).second; // the index into vInfo return pos; }
Find in and out degree of v // return the number of edges entering v template <typename T> int graph<T>::inDegree(const T& v) const { int pos=getvInfoIndex(v); if (pos != -1) return vInfo[pos].inDegree; else throw graphError("graph inDegree(): v not in the graph"); } // return the number of edges leaving v template <typename T> int graph<T>::outDegree(const T& v) const { int pos=getvInfoIndex(v); if (pos != -1) return vInfo[pos].edges.size(); else throw graphError("graph outDegree(): v not in the graph"); }
Insert a vertex into graph template <typename T> void graph<T>::insertVertex(const T& v) { int index; // attempt insertion, set vInfo index to 0 for now pair<vertexMap::iterator, bool> result = vtxMap.insert(vertexMap::value_type(v,0)); if (result.second) { // insertion into map succeeded if (!availStack.empty()) { // there is an available index index = availStack.top(); availStack.pop(); vInfo[index] = vertexInfo<T>(result.first); } else { // vInfo is full, increase its size vInfo.push_back(vertexInfo<T>(result.first)); index = numVertices; } (*result.first).second = index; // set map value to index numVertices++; // update size info } else throw graphError("graph insertVertex(): v in graph"); }
Insert an edge into graph // add the edge (v1,v2) with specified weight to the graph template <typename T> void graph<T>::insertEdge(const T& v1, const T& v2, int w) { int pos1=getvInfoIndex(v1), pos2=getvInfoIndex(v2); if (pos1 == -1 || pos2 == -1) throw graphError("graph insertEdge(): v not in the graph"); else if (pos1 == pos2) throw graphError("graph insertEdge(): loops not allowed"); // insert edge (pos2,w) into edge set of vertex pos1 pair<set<neighbor>::iterator, bool> result = vInfo[pos1].edges.insert(neighbor(pos2,w)); if (result.second) // it wasn’t already there { // update counts numEdges++; vInfo[pos2].inDegree++; } }
Erase an edge from graph // erase edge (v1,v2) from the graph template <typename T> void graph<T>::eraseEdge(const T& v1, const T& v2) { int pos1=getvInfoIndex(v1), pos2=getvInfoIndex(v2); if (pos1 == -1 || pos2 == -1) throw graphError("graph eraseEdge(): v not in the graph"); // find the edge to pos2 in the list of pos1 neighbors set<neighbor>::iterator setIter; setIter = vInfo[pos1].edges.find(neighbor(pos2)); if (setIter != edgeSet.end()) { // found edge in set, so remove it & update counts vInfo[pos1].edges.erase(setIter); vInfo[pos2].inDegree--; numEdges--; } else throw graphError("graph eraseEdge(): edge not in graph"); }
Erase a vertex from graph(algorithm) • Find index of vertex v in vInfo vector • Remove vertex v from map • Set vInfo[index].occupied to false • Push index onto availableStack • For every occupied vertex in vInfo • Scan neighbor set for edge pointing back to v • If edge found, erase it • For each neighbor of v, • decrease its inDegree by 1 • Erase the edge set for vInfo[index]
Breadth First Search (traversal) • Uses a queue to order search and a set to store visited vertices • Start with all unvisited (white) vertices • Push start vertex onto Q • While Q is not empty • Remove vertex V from Q • Mark V as visited (black) • Insert V into the visited set • For each adjacent vertex (each neighbor) U • If U is unvisited (white) • Mark it seen (gray) and push it onto Q • Return visited set (vertices reached from start) • Running time – O(V + E)
Depth first search (traversal) • Emulates a postorder traversal, backtracking search • Visits occur while backing out • DfsVisit(V, checkCycles) • If V is unvisited (white) • Mark V as seen (gray) • For each neighbor U of V • If U is unvisited (white) • DfsVisit(U,checkCycles) • Else if U is previously discovered (gray) && checkCycles • Throw exception (found cycle) • Mark V as visited (black) • Push V onto FRONT of dfsList
dfs() discovery and visiting 1/7 A 2/3 5/6 B E 3/2 6/4 7/5 Back edge C F G 4/1 m/n == discovered/visited D
Strong Components • A strongly connected component of a graph G is a maximal set of vertices SC in G that are mutually accessible.
Graph G and Its Transpose GT • The transpose has the same set of vertices V as graph G but a new edge set ET consisting of the edges of G but with the opposite direction.
Finding Strong Components • Perform dfs() of graph G, creating dfsGList • Create GT (transform of graph G) • Color all vertices in GT white • For each vertex V in GT • If V is white • Perform dfsVisit() of GT from V and create dfsGTList • Append dfsGTList to component vector • At end of process, the component vector contains a set of vertices for each strong component in the graph G • Finding GT is O(V+E) and dfs() is O(V+E) • So, finding strong components is also O(V+E)
G, GT and its Strong Components • dfsGList: A B C E D G F • dfsGTLists: {A C B} , {E} , {D F G}
Topological sort of acyclic graphs • Important in determining precedence order in graphs representing scheduling of activities • Dfs() produces a topological sort of the vertices in the graph, returning them in the dfsList • Graph must be acyclic • To show that dfs() performs a topological sort • show that if a path exists from V to W then V always appears ahead of W in dfsList • We examine the three colors W may have when first encountered in path …
Shortest-Path Example • Shortest-path is a modified breadth-first search • Path length is number of edges traversed and is stored in dataValue field of vertex at time of its discovery • The parent field is set to the index of the parent at the same time • Path is recovered in reverse, using parent fields
Shortest-Path Example(path from F to C) • Start: visitQ = F:0:F format(vertex:dataValue:parent) • Next: visitQ = D:1:F, E:1:F • Next: visitQ = E:1:F, A:2:D • Next: visitQ = A:2:D • Next: visitQ = B:3:A, C:3:A • Next: visitQ = C:3:A • Finish: C found, path length = 3, path = F,D,A,C : parent( parent( parent(C) ) )
Minimum (weight) path – Dijkstra’s algorithm • Uses priority queue containing identities of all fringe vertices and the length of the minimum path to each from the start • Algorithm builds a tree of all minimum length paths from start • Each vertex is either tree, fringe or unseen At each step The fringe vertex V with the minimum path is removed from priorityQ and added to the tree V’s non-tree neighbors U become fringe and the minimum path length is computed from start, thru V to U and is stored in U.dataValue, V is saved as U.parent and V:pathlength is added to priorityQ • Process stops when queue is empty, or chosen destination vertex is found
35 Main Index Contents Dijkstra Minimum-Path Algorithm From A to D Example PriQ: (A,0) Tree (vertices & path weight) (B,4) (C,11) (E,4) A,0 (E,4) (C,11) (C,10) (D,12) A,0 B,4 (C,10) (C,11) (D,12) A,0 B,4 C,10 empty A,0 B,4 C,10 D,12
Minimum Spanning TreePrim’s Algorithm • Spanning tree for graph with minimum TOTAL weight • Min Spanning Tree may not be unique, but total weight is same value for all • All vertices are either tree, fringe, or unseen • Priority queue is used to hold fringe vertices and the minimum weight edge connecting each to the tree Put start vertex in priorityQ While priorityQ not empty The nearest vertex V is removed from the queue and added to the tree For each non-tree neighbor U of V if the edge V,U weight < current U.dataValue U.dataValue is set to weight of edge V,U U.parent is set to V push U:weight pair onto priority queue
37 Main Index Contents Minimum Spanning Tree Example
38 Main Index Contents Minimum Spanning Tree: Vertices A and B
Completing the Minimum Spanning-Tree Algorithm with Vertices C and D
Runtime Orders of Complexity • Min Spanning Tree – O(V + E log2E) • Min Path (Dijkstra) – O(V + E log2E) • Strong Components – O(V + E) • Dfs – O(V+E) • BFS – O(V+E)
41 Main Index Contents Summary Slide 1 §- Undirected and Directed Graph (digraph) - Both types of graphs can be either weighted or nonweighted.
42 Main Index Contents Summary Slide 2 §- Breadth-First, bfs() - locates all vertices reachable from a starting vertex - can be used to find the minimum distance from a starting vertex to an ending vertex in a graph.
43 Main Index Contents Summary Slide 3 §- Depth-First search, dfs() - produces a list of all graph vertices in the reverse order of their finishing times. - supported by a recursive depth-first visit function, dfsVisit() - an algorithm can check to see whether a graph is acyclic (has no cycles) and can perform a topological sort of a directed acyclic graph (DAG) - forms the basis for an efficient algorithm that finds the strong components of a graph
44 Main Index Contents Summary Slide 4 §-Dijkstra's algorithm - if weights, uses a priority queue to determine a path from a starting to an ending vertex, of minimum weight - This idea can be extended to Prim's algorithm, which computes the minimum spanning tree in an undirected, connected graph.