EXAMPLE: X Y Z T 5 VERTICES 6 EDGES S Collection List Set ArrayList LinkedList SortedSet HashSet...

Post on 27-Mar-2015

216 views 3 download

Tags:

Transcript of EXAMPLE: X Y Z T 5 VERTICES 6 EDGES S Collection List Set ArrayList LinkedList SortedSet HashSet...

CHAPTER 14

GRAPHS

TREES

NETWORKS

AN UNDIRECTED GRAPH CONSISTS OFDISTINCT ITEMS CALLED VERTICESAND DISTINCT, UNORDEREDVERTEX-PAIRS CALLED EDGES.

EXAMPLE:

X

Y Z

T

5 VERTICES

6 EDGES S

Collection

List Set

 

ArrayList LinkedList SortedSet

 

HashSet TreeSet

TWO VERTICES ARE ADJACENT IF

THEY FORM AN EDGE. ADJACENT

VERTICES ARE CALLED NEIGHBORS.

List AND LinkedList ARE NEIGHBORS,

BUT NOT LinkedList AND ArrayList.

A PATH IN AN UNDIRECTED GRAPH

IS A SEQUENCE OF VERTICES IN

WHICH EACH SUCCESSIVE PAIR IS

AN EDGE. FOR EXAMPLE,

Collection, Set, SortedSet, TreeSet

THE LENGTH OF A PATH IS THE

NUMBER OF EDGES IN THE PATH.

FOR EXAMPLE, THE PATH

Collection, Set, SortedSet, TreeSet

HAS LENGTH 3.

X

Y Z

T

X, Y, T, Z, S HAS LENGTH 4.

SHORTEST PATH FROM

X to S = ? S

IN GENERAL, HOW CAN THE SMALLEST PATH

BETWEEN 2 VERTICES BE DETERMINED?

A CYCLE IS A PATH IN WHICH THE

FIRST AND LAST VERTICES ARE THE

SAME AND THERE ARE NO

REPEATED EDGES.

AN ACYCLIC GRAPH IS A GRAPH

WITH NO CYCLES.

X

Y Z

T

X, Y, T, Z, X IS A CYCLE.

Y, T, S, T, Y IS NOT A CYCLE.

S

IS Y, Z, T, S, Z, X, Y A CYCLE?

Collection

List Set

 

ArrayList LinkedList SortedSet

 

HashSet TreeSet

THIS UNDIRECTED GRAPH IS ACYCLIC.

AN UNDIRECTED GRAPH IS

CONNECTED IF THERE IS A PATH

BETWEEN ANY TWO DISTINCT

VERTICES IN THE GRAPH.

ALL OF THE ABOVE UNDIRECTED

GRAPHS ARE CONNECTED.

THE FOLLOWING GRAPH, WITH 6

VERTICES AND 6 EDGES, IS NOT

CONNECTED.

Minnesota Vikings

Chicago Bears Detroit Lions

Minnesota Twins

Chicago White Sox Detroit Tigers

A DIRECTED GRAPH – SOMETIMESCALLED A DIGRAPH – CONSISTS OFVERTICES AND EDGES; THE EDGESARE ORDERED PAIRS OF VERTICES.

AN ARROW IS DRAWN FROM THEFIRST VERTEX IN AN EDGE TO THESECOND VERTEX IN THAT EDGE.

Main Street

State Avenue Park Place

West Street East Street

South Kihei Road

A PATH IN A DIRECTED GRAPH IS A

SEQUENCE OF EDGES IN WHICH THE

SECOND VERTEX IN EACH EDGE

(EXCEPT THE LAST EDGE) IS THE

FIRST VERTEX IN THE NEXT EDGE.

THAT IS, A PATH MUST FOLLOW THE

DIRECTION OF THE ARROWS.

Main Street

State Avenue Park Place

West Street East Street

South Kihei Road

FIND A PATH FROM Park Place TO Main St.

A DIRECTED GRAPH IS CONNECTED

IF THERE IS A PATH BETWEEN ANY

PAIR OF VERTICES.

THE PATH MUST FOLLOW THE

DIRECTION OF THE ARROWS.

IS THE FOLLOWING GRAPH

CONNECTED?

Main Street

State Avenue Park Place

West Street East Street

South Kihei Road

A TREE, SOMETIMES CALLED A

DIRECTED TREE, IS A DIRECTED

GRAPH THAT EITHER IS EMPTY OR

HAS A VERTEX, CALLED THE ROOT,

SUCH THAT

1. THERE ARE NO EDGES COMINGINTO THE ROOT.

2. EVERY NON-ROOT VERTEX HASEXACTLY 1 EDGE COMING INTO IT.

3. THERE IS A PATH FROM THE ROOTTO EVERY OTHER ELEMENT.

Collection

List Set

 

ArrayList LinkedList SortedSet

 

HashSet TreeSet

SOMETIMES WE ASSOCIATE A NON-NEGATIVE NUMBER WITH EACHEDGE IN A GRAPH (DIRECTED ORUNDIRECTED). THE NON-NEGATIVENUMBERS ARE CALLED WEIGHTSAND THE RESULTING GRAPH ISCALLED A NETWORK OR WEIGHTEDGRAPH.

18 C F

3 15 4 10

12 5 19 A B D H

6 5 3 22 E G

GIVEN A PATH IN A NETWORK, THE

TOTAL WEIGHT OF THE PATH IS THE

SUM OF THE WEIGHTS OF THE

EDGES IN THE PATH.

18 C F

3 15 4 10

12 5 19 A B D H

6 5 3 22 E G

THE TOTAL WEIGHT OF THE PATH A,

C, F, H IS 31.

18 C F

3 15 4 10

12 5 19 A B D H

6 5 3 22 E G

THE TOTAL WEIGHT OF THE PATH A,B, D, H IS 36.

18 C F

3 15 4 10

12 5 19 A B D H

6 5 3 22 E G

EXERCISE: LIST ALL 8 PATHS FROM A TO H.

WHICH OF THOSE PATHS IS SHORTEST, THAT

IS, HAS THE LOWEST TOTAL WEIGHT?

GRAPH ALGORITHMS

ALL OF THE ALGORITHMS WE WILL

STUDY INVOLVE ITERATING, EITHER

THROUGH ALL VERTICES OR

THROUGH ALL VERTICES

REACHABLE FROM (THAT IS, ON

SOME PATH FROM) A GIVEN VERTEX.

BREADTH-FIRST ITERATION:

GIVEN A START VERTEX,

FIRST VISIT THE START VERTEX,

THEN VISIT ALL NOT-YET-REACHED NEIGHBORSOF THE START VERTEX,

THEN VISIT ALL NOT-YET-REACHED NEIGHBORSOF THOSE NEIGHBORS;

CONTINUE AS LONG AS THERE ARE ANYUNVISITED VERTICES TO WHICH THERE IS APATH FROM THE START VERTEX.

x v

Y Z

T

SASSUME THE VERTICES ARE ENTERED IN ALPHABETICAL ORDER.

PERFORM A BREADTH-FIRST ITERATION FROM S.

ANSWER: S, T, Z, Y, V, X

BASICALLY, FOR A BREADTH-FIRST ITERATION

FROM SOME VERTEX start, FIRST VISIT start,

THEN VISIT ALL THE UNVISITED VERTICES

THAT ARE ON A PATH OF LENGTH 1 FROM start,

THEN VISIT ALL THE UNVISITED VERTICES

THAT ARE ON A PATH OF LENGTH 2 FROM start,

AND SO ON.

breadth_first_iterator CLASS

METHODS?

breadth_first_iterator (const vertex* start), ++, !=, *

PRELIMINARY DESIGN:

WE NEED TO KEEP TRACK OF THECURRENT VERTEX, AND WHICHVERTICES HAVE BEEN REACHED. WEWILL RETRIEVE VERTICES IN THESAME ORDER THEY WERE SAVED.

DATA STRUCTURE?

A QUEUE!

breadth_first_iterator (vertex start){

for every vertex in the network:mark that vertex as not reached.

mark start as reached.vertex_queue.push (start);

} // algorithm for constructor

vertex operator*( ){

return vertex_queue.front( );

} // algorithm for operator*

breadth_first_iterator operator++ (int){

breadth_first_iterator temp = *this; current = vertex_queue.front( );

vertex_queue.pop( );

for each vertex that is a neighbor of current: if that vertex has not yet been reached

{mark that vertex as reached;

enqueue that vertex onto vertex_queue } // if

return temp;

} // algorithm for operator++ (int)

X V

Y Z

T

S

ASSUME THE EDGES ARE INSERTED INTO THE GRAPH AS FOLLOWS:

S, T (SAME AS T, S)S, ZT, YT, ZV, YV, ZX, YX, Z

PERFORM A BREADTH-FIRST ITERATION FROM S.

vertex_queue vertex where iterator returned by ++ is positioned S T, Z

S Z, Y

T Y, V, X

Z V, X

Y X

V X

NOTE: FOR A BREADTH-FIRST ITERATION OF A DIRECTED

GRAPH, THE ALGORITHM IS THE SAME, BUT “NEIGHBOR”

TAKES INTO ACCOUNT THE DIRECTION OF THE ARROW.

A

B C D

FOR A BREADTH-FIRST ITERATION STARTING AT A, THE

NEIGHBORS OF A ARE B AND C, BUT NOT D. D NEVER

GETS ENQUEUED, AND NEVER GETS RETURNED BY next( ).

DEPTH-FIRST ITERATOR RECALL THE PRE-ORDER

TRAVERSAL OF BINARY TREES:

preOrder (t) {

if (t is not empty) { access the root item of t; preOrder (leftTree (t)); preOrder (rightTree (t)); } // if } // preOrder traversal

Collection

List Set

 

ArrayList LinkedList SortedSet

 

HashSet TreeSet

DEPTH-FIRST ITERATION:

CollectionListArrayListLinkedListSetHashSetSortedSetTreeSet

SINCE A PRE-ORDER TRAVERSAL IS

RECURSIVE,WHAT DATA STRUCTURE SHOULD

WE USE TO HOLD THE VERTICES?

A STACK!

depth_first_iterator (vertex start) {

for every vertex in the network:mark that vertex as not reached.

mark start as reached.vertex_stack.push (start);

} // algorithm for constructor

depth_first_iterator operator++ (int){

depth_first_iterator temp = *this; current = vertex_stack.top( );

vertex_stack.pop( );

for each vertex that is a neighbor of current: if that vertex has not yet been reached

{mark that vertex as reached;

push that vertex onto vertex_stack } // if

return temp;

} // algorithm for operator++ (int) in a depth-first iteration

X V

Y Z

T

S

ASSUME THE EDGES ARE INSERTED INTO THE GRAPH AS

FOLLOWS:

S, T // SAME AS T, SS, ZT, YT, ZV, YV, ZX, YX, Z

PERFORM A DEPTH-FIRST ITERATION FROM S.

stack (top vertex is leftmost) vertex where iterator returned by ++ is positioned S Z, T S X, V, T Z Y, V, T X V, T Y T V

T

TOP OF STACK IS LEFTMOST.

IN A CONNECTED (DIRECTED OR

UNDIRECTED) NETWORK, A SPANNING

TREE IS A TREE THAT CONSISTS OF

ALL THE VERTICES AND SOME OF

THE EDGES – AND THEIR WEIGHTS.

A

5.0 7.0

B 10.0 C

8.0 6.0

D

HERE IS ONE SPANNING TREE:

A

5.0 7.0

B C

8.0

D

HERE IS ANOTHER SPANNING TREE: A

5.0 7.0

B 10.0 C

D

A MINIMUM SPANNING TREE HAS

LOWEST TOTAL WEIGHT AMONG

ALL SPANNING TREES.

IF THE WEIGHTS ARE DISTANCES

BETWEEN BUILDINGS, A MINIMUM

SPANNING TREE REPRESENTS THE

MINIMUM LENGTH OF CABLE

NEEDED TO CONNECT ALL THE

BUILDINGS.

FIND A MINIMUM SPANNING TREE:

A

5.0 7.0

B 10.0 C

8.0 6.0

D

A

5.0 7.0

B C

6.0

D

PRIM’S ALGORITHM FOR FINDING A MINIMUM

SPANNING TREE:

START WITH AN EMPTY TREE T AND PICK ANY

VERTEX v IN THE NETWORK. ADD v TO T.

FOR EACH VERTEX w SUCH THAT (v, w) IS AN

EDGE WITH WEIGHT wweight, SAVE THE

ORDERED TRIPLE <v, w, wweight> IN A

COLLECTION (SOON: WHAT KIND OF

COLLECTION).

THEN LOOP UNTIL T HAS AS MANY VERTICES

AS THE NETWORK. DURING EACH LOOP

ITERATION, REMOVE FROM THE COLLECTION

THE TRIPLE <x, y, yweight> FOR WHICH yweight IS

THE SMALLEST OF ALL TRIPLES IN THE

COLLECTION. IF y IS NOT ALREADY IN T, ADD y

AND THE EDGE (x, y) TO T, AND SAVE IN THE

COLLECTION EVERY TRIPLE <y, z, zweight> SUCH

THAT z IS NOT ALREADY IN T AND (y, z) IS AN

EDGE WITH WEIGHT zweight.

THE COLLECTION SHOULD BE ORDERED BY

WEIGHTS, AND DURING EACH LOOP ITERATION,

THE TRIPLE WITH LOWEST WEIGHT IS

REMOVED.

FOR THIS COLLECTION, SUPPOSE WE WANT, ON

AVERAGE, FOR INSERTIONS TO TAKE

CONSTANT TIME AND REMOVALS TO TAKE

LOGARITHMIC TIME. WHAT DATA STRUCTURE

DOES THIS SUGGEST FOR THE COLLECTION?

A PRIORITY QUEUE!

lowest weight = highest priority

A

5.0 7.0

B 10.0 C

8.0 6.0

D

SUPPOSE WE START WITH B.

T PRIORITY QUEUE B <B, A, 5>

<B, D, 8>

T PRIORITY QUEUE B <A, C, 7> 5 <B, D, 8>A <A, D, 10>

T PRIORITY QUEUE B <C, D, 6> 5 <B, D, 8>A C <A, D, 10> 7

T PRIORITY QUEUE B D <B, D, 8> 5 6 <A, D, 10>A C 7

WE ARE NOW DONE BECAUSE THE

TREE CONTAINS ALL OF THE

VERTICES.

EXERCISE:

FIND A MINIMUM SPANNING TREE

FOR THE FOLLOWING

UNDIRECTED NETWORK:

18 C F

3 15 4 10

12 5 19 A B D H

6 5 4 22 E G

FINDING THE SHORTEST

PATH THROUGH A NETWORK

GIVEN A NETWORK (DIRECTED ORUNDIRECTED) AND VERTICES v1 AND

v2, FIND A PATH FROM v1 TO v2

WHOSE TOTAL WEIGHT IS MINIMUM.

DIJKSTRA’S ALGORITHM:

LET pq BE A PRIORITY QUEUE OFVERTEX-WEIGHT PAIRS, <w, wweight>,WHERE wweight IS THE TOTAL WEIGHTOF ALL EDGES ON THE SHORTESTPATH SO FAR FROM v1 TO w.

LOWEST TOTAL WEIGHT= HIGHEST PRIORITY

ITERATE, BREADTH-FIRST, STARTINGAT v1 UNTIL A PAIR WITH v2 ISREMOVED FROM pq.

TO KEEP TRACK OF TOTAL PATH

WEIGHTS, WE HAVE A map OBJECT,weight_sum, THAT ASSOCIATES WITHEACH VERTEX x THE SUM OF THEWEIGHTS ON THE SHORTEST PATH SOFAR FROM v1 TO x.

FINALLY, predecessor, ANOTHER map

OBJECT, ASSOCIATES EACH VERTEX

x WITH ITS PREDECESSOR ON THESHORTEST PATH SO FAR FROM v1 TOx. THAT MAP ENABLES US TORETRIEVE THE SHORTEST PATH

WHEN WE ARE DONE.

B

10 18

A 2 D 25 7 5

C E 14

FIND THE SHORTEST PATH FROM A TO D.

INITIALIZE weight_sum AND predecessor,

AND FOR EACH NEIGHBOR w OF A,

ADD TO pq THE PAIR CONSISTING OF

THE NEIGHBOR AND THE WEIGHT OF

EDGE (A, w).

B weight_sum predecessor pq A, 0 A <C, 7> 10 18 B, 10 A <B, 10>

C, 7 AA 2 D D, 1000 25 E, 1000 7 5

C E 14

NOW LOOP UNTIL D IS REMOVED FROM pq. FOR

EACH PAIR <w, weight_sum> REMOVED FROM pq,

ITERATE OVER THE NEIGHBORS OF w. FOR

EACH NEIGHBOR x, IF w’S WEIGHT SUM +

WEIGHT OF (w, x) IS LESS THAN x’S WEIGHT SUM,

REPLACE x’S WEIGHT SUM WITH w’S WEIGHT

SUM + WEIGHT OF (w, x) AND INSERT x AND ITS

NEW WEIGHT SUM INTO pq. ALSO, MAKE w THE

PREDECESSOR OF x.

B weight_sum predecessor pq A, 0 A <B, 9> 10 18 B, 9 C <B, 10>

C, 7 A <E, 21>A 2 D D, 32 C <D, 32> 25 E, 21 C 7 5

C E 14

B weight_sum predecessor pq A, 0 A <B, 10> 10 18 B, 9 C <E, 21>

C, 7 A <D, 27>A 2 D D, 27 B <D, 32> 25 E, 21 C 7 5

C E 14

NOTHING HAPPENS WHEN <B, 10> IS REMOVED

FROM pq BECAUSE WE ALREADY HAVE A PATH

OF LENGTH 9 FROM A TO B.

B weight_sum predecessor pq A, 0 A <E, 21> 10 18 B, 9 C <D, 27>

C, 7 A <D, 32>A 2 D D, 27 B 25 E, 21 C 7 5

C E 14

B weight_sum predecessor pq A, 0 A <D, 26> 10 18 B, 9 C <D, 27>

C, 7 A <D, 32>A 2 D D, 26 E 25 E, 21 C 7 5

C E 14

DURING THE NEXT LOOP ITERATION, WHEN <D,

26> IS REMOVED FROM pq, WE STOP. THE

SHORTEST PATH FROM A TO D IS, ACCORDING

TO predecessor, A, C, E, D.

DEVELOPING A network CLASS

INSTEAD OF DEVELOPING SIX

CLASSES (DIRECTED OR UNDIRECTED

NETWORK, GRAPH AND TREE), WE

WILL DEVELOP A (DIRECTED)

network CLASS ONLY: THE OTHERS

CAN BE DEFINED BY INHERITANCE.

FOR EXAMPLES:

AN UNDIRECTED NETWORK IS A

(DIRECTED) NETWORK IN WHICH

EACH EDGE IS TWO-WAY.

A DIRECTED GRAPH IS A NETWORK

IN WHICH EACH EDGE HAS THE

SAME WEIGHT (FOR EXAMPLE, 1.0).

WHAT SHOULD WE START WITH?

FIELDS?

METHODS?

VERTEX-RELATED METHOD INTERFACES,

WITH TIME ESTIMATES GIVEN LATER:

// Postcondition: true has been returned if this network contains// v; otherwise, false has been returned.bool contains_vertex (const vertex& v);

// Postcondition: if v is already in this network, false has been// returned. Otherwise, the map with v and an// empty list has been added to this network and// true has been returned.bool insert_vertex (const vertex& v);

// Postcondition: if v is a vertex in this network, v and all of its// edges have been deleted from this network and// true has been returned. Otherwise, false has// been returned.bool erase_vertex (const vertex& v);

EDGE-RELATED METHOD INTERFACES:

// Postcondition: the number of edges in this network has been// returned.unsigned int get_edge_count();

// Postcondition: if <v1, v2> forms an edge in this network, the// weight of that edge has been returned.// Otherwise, -1.0 has been returned.double get_edge_weight (const vertex& v1, const vertex& v2);

// Postcondition: true has been returned if this network contains// the edge <v1, v2>. Otherwise, false has been// returned.bool contains_edge (const vertex& v1, const vertex& v2);

// Postcondition: if the edge <v1, v2> is already in this network// false has been returned. Otherwise, that edge// with the given weight has been inserted in this// network and true has been returned.bool insert_edge (const vertex& v1, const vertex& v2, const double& weight);

// Postcondition: if <v1, v2> is an edge in this network, that edge// has been removed and true has been returned.// Otherwise, false has been returned.bool erase_edge (const vertex& v1, const vertex& v2);

NETWORK-AS-A-WHOLE METHOD INTERFACES:

// Postcondition: this network is empty.network( );

// Postcondition: this network contains a copy of other.network (const network& other);

// Postcondition: the number of vertices in this network has been// returned.unsigned int size( );

// Postcondition: true has been returned if this network contains// no vertices. Otherwise, false has been returned.bool empty( );

// Precondition: v is in this network.// Postcondition: the list of neighbors of v has been returned.list< vertex > get_neighbor_list (const vertex& v);

// Postcondition: true has been returned if this network is// connected. Otherwise, false has been// returned.bool is_connected( );

// Precondition: this network is connected.// Postcondition: a minimum spanning tree for this network has// been returned.network<vertex> get_minimum_spanning_tree( );

// Postcondition: the shortest path from v1 to v2 and its total// weight have been returned.pair<list<vertex>, double> get_shortest_path (const vertex&v1, const vertex& v2);

// Postcondition: an iterator positioned at the beginning of this// network has been returned.iterator begin( );

// Postcondition: the iterator returned can be used in// comparisons to terminate an iteration of this// network.iterator end( );

// Precondition: vertex v is in this network.// Postcondition: a breadth_first_iterator over all vertices// reachable from v has been returned.breadth_first_iterator breadth_first_begin (const vertex& v);

// Postcondition: the breadth_first_iterator returned can be used// in comparisons to terminate this iteration of// this network.breadth_first_iterator breadth_first_end( );

// Precondition: vertex v is in this network.// Postcondition: a depth_first_iterator over all vertices// reachable from v has been returned.depth_first_iterator depth_first_begin (const vertex& v);

// Postcondition: the depth_first_iterator returned can be used// in comparisons to terminate this iteration of// this network.depth_first_iterator depth_first_end( );

FIELDS IN THE (DIRECTED) network

CLASS

GIVEN A VERTEX v, WHAT

INFORMATION ABOUT v ISRELEVANT?

ANSWER:

1. EACH VERTEX w SUCH THAT<v, w> FORMS AN EDGE;

2. THE WEIGHT OF THAT EDGE.

SO WITH EACH VERTEX v, WE WILL

ASSOCIATE ALL PAIRS <w, weight>

WHERE <v, w> FORMS AN EDGE

WHOSE WEIGHT IS weight.

HOW CAN WE SAVE “ALL PAIRS”?

A COLLECTION IN WHICH ORDER ISUNIMPORTANT:

A LINKED LIST

WHAT STRUCTURE SHOULD WE USE

TO “ASSOCIATE” v WITH ITS LINKED

LIST?

HINT: GIVEN A VERTEX, WE WANT

TO RETRIEVE ITS LINKED LIST VERY

QUICKLY.

BEST: A hash_map

BUT THE hash_map CLASS IS NOT

(YET) IN THE STANDARD TEMPLATELIBRARY. SO IN THE INTEREST OFCONFORMITY TO THE LIBRARY:

SECOND BEST: A map

EXERCISE:

USING weight_sum, predecessor, AND pq,

FIND THE SHORTEST PATH FROM A

TO H IN THE FOLLOWING NETWORK:

18 C F

3 15 4 10

12 5 19 A B D H

6 5 3 22 E G

THE network CLASS HAS ONLY ONEFIELD:

template<class vertex, class Compare = less<vertex> >class network{

protected:map<vertex, list< vertex_weight_pair >, Compare>

adjacency_map;

WHICH MAPS EACH VERTEX v TO

THE LinkedList OF NEIGHBORS OF v.

THIS DESIGN IS REFERRED TO AS THEADJACENCY LIST DESIGN OF THE

network CLASS.

WHAT IS vertex_weight_pair? ROUGHLY,A PAIR WITH A VERTEX AND AWEIGHT. TECHNICALLY:

struct vertex_weight_pair{ vertex to; // the end of the edge that starts // with the key vertex double weight;

// Postcondition: this vertex_weight_pair has been initialized// from x and y.

vertex_weight_pair (const vertex& x, const double& y) { to = x; weight = y; } // two-parameter constructor

// Postcondition: true has been returned if this// vertex_weight_pair is less than x.

// Otherwise, false has been returned. bool operator> (const vertex_weight_pair& p) const { return weight > p.weight; } // operator>}; // class vertex_weight_pair

THE REASON FOR OVERLOADINGoperator> IS THAT, IN THEget_shortest_path METHOD, THEPRIORITY QUEUE CONSISTS OFVERTEX-WEIGHT PAIRS, AND WEWANT THE LOWEST WEIGHT TOHAVE HIGHEST PRIORITY. SO THEFUNCTION CLASS FOR COMPARISONSMUST BE greater, NOT THE DEFAULT(less).

Mark

10.0 8.3

7.4 Karen Don Tara

14.2 20.0 15.0

Courtney

ASSUME THESE ARE ENTERED Karen, Mark,

Don, Courtney, Tara. HERE IS adjacency_map:

Karen [(Mark,10.0), (Don,7.4), (Courtney,14.2)]

Don [ ] Mark [(Tara,8.3)]

Courtney [(Don,20.0), (Tara,15.0)] Tara [ ]

METHOD DEFINITIONS IN THE

network CLASS

SEVERAL DEFINITIONS ARE ONE-

LINERS BECAUSE THE WORK IS

DONE IN THE map CLASS. FOR

EXAMPLE:

unsigned size( ) { return adjacency_map.size( ); } // method size bool contains_vertex (const vertex& v) { return adjacency_map.find (v) != adjacency_map.end( ); } // method contains_vertex

INSERTING A VERTEX CAN BE

ACCOMPLISHED WITH THE insert

METHOD IN THE map CLASS:

bool insert_vertex (const vertex& v){ return adjacency_map.insert (

pair<vertex, list<vertex_weight_pair> >(v, list<vertex_weight_pair>( ))).second ;

} // method insert_vertex

HERE IS ANOTHER DEFINITION OFinsert_vertex, ONE THAT IS LESSEFFICIENT BUT FAR EASIER TOUNDERSTAND:

bool insert_vertex (const vertex& v){ if (adjacency_map.find (v) != adjacency_map.end( )) return false; adjacency_map [v] = list< vertex_weight_pair >( ); return true;} // method insert_vertex

TO DELETE A VERTEX v, WE FIRST

UTILIZE THE find METHOD IN THE

map CLASS TO GET AN ITERATOR itr

POSITIONED AT v. WE THEN

DELETE THE VALUE (THAT IS,

VERTEX-LIST PAIR) THAT itr IS

POSITIONED AT:

bool erase_vertex (const vertex& v) { map_class::iterator itr = adjacency_map.find (v); if (itr == adjacency_map.end( )) return false; adjacency_map.erase (itr); WE MUST ALSO REMOVE ALL EDGES

GOING INTO v. SO WE ITERATE

THROUGH THE ADJACENCY MAP:

FOR EACH LIST, IF THERE IS A PAIR

WITH VERTEX v, THAT PAIR IS

DELETED FROM THE LIST:

bool erase_vertex (const vertex& v) { map_class::iterator itr = adjacency_map.find (v); if (itr == adjacency_map.end( )) return false; adjacency_map.erase (itr);

list<vertex_weight_pair>::iterator list_itr; for (itr = adjacency_map.begin( ); itr != adjacency_map.end( )); itr++)

// In the list in (*itr).second, delete any pair <v, ?> for (list_itr = (*itr).second.begin(); list_itr != (*itr).second.end(); list_itr++) if ((*list_itr).to == v) { (*itr).second.erase (list_itr); break; // to exit the inner for loop } // v found in the list (*itr).second return true; } // erase_vertex

TO DETERMINE IF THE NETWORK

CONTAINS AN EDGE <v1, v2>, WE

FIRST CHECK TO MAKE SURE BOTH

v1 AND v2 ARE IN THE ADJACENCY

MAP. IF SO, WE ITERATE THROUGH

v1’S ASSOCIATED LIST FOR A

VERTEX-WEIGHT PAIR WITH v2:

bool contains_edge (const vertex& v1, const vertex& v2) { map_class::iterator itr = adjacency_map.find (v1); if (itr == adjacency_map.end() || adjacency_map.find (v2) == adjacency_map.end()) return false; // See if v2 is in the list of vertices adjacent from v1: list<vertex_weight_pair >::iterator list_itr;

for (list_itr = ((*itr).second).begin(); list_itr != ((*itr).second).end(); list_itr++)

if ((*list_itr).to == v2) return true; return false; } // method contains_edge

map_class IS AN ABBREVIATION FOR map<vertex, list< vertex_weight_pair > , Compare>

TO INSERT AN EDGE <v1, v2> AND ITS

WEIGHT, WE (TRY TO) INSERT THE

VERTICES v1 AND v2, AND THEN

APPEND <v2, weight> TO THE LIST OF

VERTEX-WEIGHT PAIRS ASSOCIATED

WITH VERTEX v1:

bool insert_edge (const vertex& v1, const vertex& v2, double weight) { if (contains_edge (v1, v2)) return false; insert_vertex (v1); insert_vertex (v2); (*(adjacency_map.find(v1))).second.push_back (vertex_weight_pair (v2, weight)); return true; } // method insert_edge

TO DELETE EDGE <v1, v2>, ITERATE

OVER THE LIST ASSOCIATED WITH v1.

DELETE, FROM THE LIST, ANY PAIR

WHOSE FIRST COMPONENT IS v2:

bool erase_edge (const vertex& v1, const vertex& v2){ map_class::iterator itr = adjacency_map.find (v1);

if (itr == adjacency_map.end( )|| adjacency_map.find (v2) == adjacency_map.end())

return false;

// If <v1, v2> forms an edge, remove, from the list of edges// adjacent from v1, the edge <v1, v2> and its weight:

list<vertex_weight_pair >::iterator list_itr; for (list_itr = (*itr).second.begin( );

list_itr != (*itr).second.end(); list_itr++) if ((*list_itr).to == v2) { (*itr).second.erase (list_itr); return true; } // if return false;} // method erase_edge

FINALLY, WE’LL LOOK ATITERATING, SPECIFICALLY, DEPTH-FIRST ITERATING.

FOR A DEPTH-FIRST ITERATION, WENEED NOT ONLY A START VERTEX,BUT ALSO THE NETWORK WE AREITERATING OVER. A POINTER TO

adjacency_map IS SUFFICIENT: WE

DON’T NEED A COPY OF

adjacency_map.

// Precondition: vertex v is in this network.// Postcondition: a depth_first_iterator over all vertices// reachable from v has been returned.depth_first_iterator depth_first_begin (const vertex& v){ depth_first_iterator d_itr (v, &adjacency_map); return d_itr;} // method depth_first_begin

IN THE EMBEDDED depth_first_iterator

CLASS, WE’LL HAVE A STACK OFVERTICES. ALSO GIVEN A VERTEX,WE WANT A QUICK DETERMINATIONOF WHETHER THAT VERTEX IS

REACHABLE FROM THE STARTVERTEX, SO WE’LL MAP EACH

VERTEX TO true OR false. FINALLY,WE HAVE (A COPY OF) THEADJACENCY MAP:

class depth_first_iterator{ friend class network;

protected:

stack<vertex>* vertex_stack; map<vertex, bool, Compare>* reached; map_class* map_ptr;

BY USING POINTER FIELDS, WESIMPLIFY THE TEST FOR EQUALITYOF ITERATORS.

BEFORE WE GET TO THE DEFINITIONOF THE CONSTRUCTOR (CALLED BYdepth_first_begin), RECALL THEOUTLINE GIVEN EARLIER:

depth_first_iterator (vertex start) {

for every vertex in the network:mark that vertex as not reached.

mark start as reached.vertex_stack.push (start);

} // algorithm for constructor

depth_first_iterator (const vertex& start, map_class* ptr){

map_ptr = ptr; reached = new map<vertex, bool, Compare>(); vertex_stack = new stack<vertex>();

// Mark each vertex as not reached: map_class::iterator itr; for (itr = (*map_ptr).begin(); itr != (*map_ptr).end(); itr++) (*reached)[(*itr).first] = false;

(*reached)[start] = true; (*vertex_stack).push (start);} // two-parameter constructor

AS PROMISED, THE DEFINITION OF

operator== IS STRAIGHTFORWARD:

bool operator== (const depth_first_iterator& other){

return (vertex_stack == other.vertex_stack) && (reached == other.reached) && (map_ptr == other.map_ptr);} // operator==

BEFORE WE TACKLE operator++ (int),RECALL THE ALGORITHM GIVENEARLIER:

depth_first_iterator operator++ (int){

depth_first_iterator temp = *this; current = vertex_stack.top( );

vertex_stack.pop( );

for each vertex that is a neighbor of current: if that vertex has not yet been reached

{mark that vertex as reached;

push that vertex onto vertex_stack } // if

return temp;

} // algorithm for operator++ (int) in a depth-first iteration

depth_first_iterator operator++ (int){

depth_first_iterator temp = *this; vertex current = (*vertex_stack).top(); (*vertex_stack).pop(); map_class::iterator itr = (*map_ptr).find (current); list<vertex_weight_pair >::iterator list_itr; for (list_itr = (*itr).second.begin(); list_itr != (*itr).second.end(); list_itr++) { vertex to = (*list_itr).to; if ((*reached) [to] == false) { (*reached) [to] = true; (*vertex_stack).push (to); } // if } // for

if ((*vertex_stack).empty()) { vertex_stack = NULL; reached = NULL; map_ptr = NULL; } // if stack empty return temp;} // operator++

EXERCISE: FOR A DEPTH-FIRST ITERATOR,

operator* RETURNS A VERTEX, NAMELY,

(*vertex_stack).top( );

FOR A NETWORK ITERATOR, operator*

RETURNS A PAIR. WHAT ARE THE TYPES OF

THE COMPONENTS OF THE PAIR? THAT IS,

WHAT ARE THE TYPES OF (*itr).first AND

(*itr).second IF itr IS A NETWORK ITERATOR?