- 117 Views
- Uploaded on
- Presentation posted in: General

Main Index

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

- 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

- Graph with ordered edges are called directed graphs or digraphs

4

Main Index

Contents

- 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

- 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

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

- 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

- 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

- 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

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)

{}

};

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

};

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

}

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

}

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

}

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

}

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

- 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

- If U is unvisited (white)

- Return visited set (vertices reached from start)
- Running time – O(V + E)

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

- If U is unvisited (white)
- Mark V as visited (black)
- Push V onto FRONT of dfsList

- If V is unvisited (white)

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

- A strongly connected component of a graph G is a maximal set of vertices SC in G that are mutually accessible.

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

- 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

- If V is white
- 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)

- dfsGList: A B C E D G F
- dfsGTLists: {A C B} , {E} , {D F G}

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

- Start: visitQ = F:0:Fformat(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) ) )

- 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

PriQ:(A,0)Tree (vertices & path weight)

(B,4)(C,11)(E,4)A,0

(E,4)(C,11)(C,10)(D,12)A,0B,4

(C,10)(C,11)(D,12)A,0B,4C,10

emptyA,0B,4C,10 D,12

- 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

38

Main Index

Contents

- 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

§- Undirected and Directed Graph (digraph)

- Both types of graphs can be either weighted or nonweighted.

42

Main Index

Contents

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

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

§-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.