using a directed graph

Post on 03-Jan-2016

53 Views

Category:

Documents

3 Downloads

Preview:

Click to see full reader

DESCRIPTION

Using a Directed Graph. Drozdek Chapter 8. Objectives. You will be able to Understand and use a C++ ADT for a directed graph. Describe and implement an algorithm for finding the shortest path between two nodes in a directed graph. New Project. New Project. - PowerPoint PPT Presentation

TRANSCRIPT

1

Using a Directed Graph

Drozdek Chapter 8

2

Objectives

You will be able to Understand and use a C++ ADT for

a directed graph. Describe and implement an

algorithm for finding the shortest path between two nodes in a directed graph.

3

New Project

4

New Project

5

Implementation of a Directed Graph ADT

Download to project directory: http://www.cse.usf.edu/~turnerr/Data_Structures/Dow

nloads/2011_04_25_Directed_Graphs/ Digraph.h shortest_path.cpp NetworkFile.txt

Delete .txt from the .h and .cpp files

Add the .h and .cpp files to the project

6

Implementation of a Directed Graph ADT

Examine Digraph.h

Adjacency list representation.

The Digraph is a vector of Vertex objects Node ID is the index. Element 0 is not used.

Each Vertex object has a data member Template class T A list of integers (Node IDs)

Nodes adjacent to this node.

7

NetworkFile.txt

Example: Digraph with string as template parameter.

Class Digraph method read() sets up the digraph with contents of a file.

8

NetworkFile.txt

1

2

3

4

5

6

7

8

First number in each list is the number of adjacencies.

The then IDs of adjacent cities.

Note that Denver has an adjacency to itself.

(Sight-seeing flight? )

9

Adjacencies in NetworkFile.txt

LA

1

SF

2

Den

3

Chi

4

Bos

5

NY

6

Miami

7

NO

8

Digraph<T>::read()template <typename T>

void Digraph<T>::read(ifstream & inStream)

{

Vertex vi;

int n; // number of adjacent vertices

int vertex_id; // the number of a vertex

// Create a garbage 0-th value so real indices start with 1

digraph.push_back(vi);

while (true)

{

inStream >> vi.data;

if (inStream.eof()) break;

vi.adjacencyList.clear();

inStream >> n; // Number of adjacent vertices

for (int i = 1; i <= n; i++)

{

inStream >> vertex_id;

assert(inStream.good());

vi.adjacencyList.push_back(vertex_id);

}

digraph.push_back(vi);

}

}

11

Digraph<T>::display( )

template <typename T>

void Digraph<T>::display(ostream & out)

{

out << "Adjacency-List Representation: \n";

for (size_t i = 1; i < digraph.size(); i++)

{

out << i << ": " << digraph[i].data << "--";

for (list<int>::iterator

it = digraph[i].adjacencyList.begin();

it != digraph[i].adjacencyList.end(); it++)

out << *it << " ";

out << endl;

}

}

12

Depth First Search

Public method:

void depthFirstSearch(int start = 1);

...

template <typename T>

inline void Digraph<T>::depthFirstSearch(int start)

{

vector<bool> unvisited(digraph.size(), true);

depthFirstSearch(start, unvisited);

}

13

Internal Depth First Search Method

// Internal (recursive) depth first search method

template <typename T>

void Digraph<T>::depthFirstSearch(int start, vector<bool> & unvisited)

{

visit(digraph[start].data);

unvisited[start] = false;

// Traverse the adjacency list, performing depth-first

// searches from each unvisited vertex in it.

list<int>::iterator it;

list<int>::iterator begin = digraph[start].adjacencyList.begin();

list<int>::iterator end = digraph[start].adjacencyList.end();

for (it = begin; it != end; it++)

{

// check if current vertex has been visited

if (unvisited[*it])

{

// Do a depth first search from this vertex

depthFirstSearch(*it, unvisited);

}

}

}

14

The visit() Method

template <typename T>

void Digraph<T>::visit(T& node_data)

{

cout << node_data << endl;

}

A Virtual Method Intended to be overridden in a derived

class in order to do something useful at each node.

15

get_digraph()

void get_digraph()

{

ifstream network_file;

while (true)

{

cout << "Enter name of network file: ";

string filename;

cin >> filename;

network_file.open(filename.c_str());

if (network_file.is_open())

{

break;

}

cout << "Could not open " << filename << endl;

cout << "Please try again" << endl;

}

digraph.read(network_file);

network_file.close();

cout << "The Digraph's adjacency list representation:\n";

digraph.display(cout);

cout << endl;

}

16

Initial main()

int main()

{

get_digraph();

cout << endl << "Normal termination" << endl;

cin.get();

cin.get();

return 0;

}

17

The Adjacency Lists

18

Depth First Search

Let's do a Depth First Search.

int main()

{

get_digraph();

digraph.depthFirstSearch();

cout << endl << "Normal termination" << endl;

cin.get();

cin.get();

return 0;

}

19

Depth First Search from LA

20

Depth First Search from LA

LA

1

SF

2

Den

3

Chi

4

Bos

5

NY

6

Miami

7

NO

8

21

Depth First Search from Boston

Do a depth first search from Boston.

int main()

{

get_digraph();

digraph.depthFirstSearch(5);

22

Depth First Search from Boston

23

Depth First Search from Boston

LA

1

SF

2

Den

3

Chi

4

Bos

5

NY

6

Miami

7

NO

8

24

Providing Our Own Visit Method

Add derived class Digraph2.h

http://www.cse.usf.edu/~turnerr/Data_Structures/Downloads/2011_04_25_Directed_Graphs/

Delete the .txt

25

Digraph2.h

#pragma once

#include "digraph.h"

template <typename T>

class Digraph2 : public Digraph<T>

{

public:

void visit(T& node_data);

};

template <typename T>

void Digraph2<T>::visit(T& node_data)

{

show_length(node_data);

}

Override visit() method in base class

26

In shortest_path.cpp

#include "Digraph2.h"

Digraph2<string> digraph;

void show_length(string name)

{

cout << "Length of " << name << " is "

<< name.length() << endl;

}

27

Own Visit Method

End of Section

28

Paths

Routing problems – find an optimal path in a network A shortest path in a digraph. A cheapest path in a weighted digraph.

Example – a directed graph that models an airline network Vertices represent cities. Arcs represent flights connecting cities.

Task: Find most direct route between two cities. (Fewest flights)

29

Paths in Directed Graph

Most direct route Shortest path. Path from start vertex to destination

vertex with minimum number of arcs.

Search algorithm for a shortest path: A minor modification of the breadth-first

search algorithm. Do a breadth first traversal, keeping track

of the predecessor of each node reached. Stop upon reaching the destination node.

30

Shortest Path Algorithm

Given a directed graph with nodes 1 to n, a starting node ID, start, and a destination node ID, dest: Let dist[] be an array of ints

dist[v] will hold the distance from start to node v.

Let pred[] be an array of node IDs. pred[v] will be the predecessor to node v on

a shortest path from start to dest.

Initialize dist[start] to 0 and dist[v] to infinity for all other nodes.

31

Shortest Path Algorithm

Initialize vertex_queue as a queue of ints, initially containing just the starting vertex ID.

While dest has not been visited and vertex queue is not empty:

Remove the front item from the vertex queue as v.

For each node, w, adjacent to v: If dist[w] is infinity

Set dist[w] to dist[v]+1 Set pred[w] to v. Add w to the vertex queue.

32

Shortest Path Algorithm

At this point, either we have reached dest or we have exhausted the possibilities.

If dist[dest] is infinity report failure. Else

Initialize a stack with dest. Initialize v as dest. Do the following

Set v to pred[v] Push v onto the stack

until v is start.

The stack now holds a shortest path from start to dest.

33

Implementation of Shortest_Path

In digraph.h

template<typename T>

vector<int> Digraph<T>::Shortest_Path(int start, int dest)

{

int n = digraph.size();

vector<int> dist(n, INT_MAX); // Distance from start

vector<int> pred(n, 0); // Predecessor on shortest path

int v; // The current vertex

queue<int> vertex_queue;

vertex_queue.push(start);

dist[start] = 0;

34

Implementation of Shortest_Path

while (dist[dest] == INT_MAX && !vertex_queue.empty())

{

v = vertex_queue.front();

vertex_queue.pop();

list<int>::iterator it;

list<int>::iterator begin = digraph[v].adjacencyList.begin();

list<int>::iterator end = digraph[v].adjacencyList.end();

for (it = begin; it != end; ++it)

{

int w = *it;

if (dist[w] == INT_MAX)

{

dist[w] = dist[v] + 1;

pred[w] = v;

vertex_queue.push(w);

}

}

}

35

Implementation of Shortest_Path

// Now reconstruct the shortest path if there is one

if (dist[dest] == INT_MAX)

{

cout << "Destination not reachable from start vertex\n";

return path;

}

stack<int> reverse_path;

reverse_path.push(dest);

v = dest;

do

{

v = pred[v];

reverse_path.push(v);

} while (v != start);

36

Implementation of Shortest_Path

vector<int> path;

while (!reverse_path.empty())

{

v = reverse_path.top();

path.push_back(v);

reverse_path.pop();

}

return path;

}

37

main()

int main(){ get_digraph(); char response; do { int start, destination; cout << "Number of start city? "; cin >> start; cout << "Number of destination? "; cin >> destination;

vector<int> path = digraph.Shortest_Path(start, destination);

if (path.size() > 0) { display_path(path); } else { cout << digraph.get_data(destination) << " is unreachable from " << digraph.get_data(start) << endl; } cout << endl << "More (Y or N)?"; cin >> response; } while (response == 'y' || response == 'Y');

38

Try it!

39

Computing Shortest Paths

40

A Defect

What happens if we ask for the shortest path from a city to itself?

41

A Defect

42

A Defect

What is the program doing?

What should it do?

End of Presentation

top related