1 / 106

Graph ADT Inheritance

Graph ADT Inheritance. Final Exam. Not Thursday, May 20, 2-3:55am Check Spring course schedule Tuesday, May 18, 2-3:55pm, Here in LSci 185 Use the study sheet Assortment of programming questions Like the last midterm, except, 200 points (half on Tables, Trees, Graphs)

macy
Download Presentation

Graph ADT Inheritance

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Graph ADT Inheritance

  2. Final Exam • Not Thursday, May 20, 2-3:55am • Check Spring course schedule • Tuesday, May 18, 2-3:55pm, • Here in LSci 185 • Use the study sheet • Assortment of programming questions • Like the last midterm, except, 200 points • (half on Tables, Trees, Graphs) • (half on material from first half of course)

  3. Types of graphs • Graph ADT • Adjacency lists • directed • undirected • Adjacency matrices • directed • undirected

  4. Abstract classes • An abstract class encapsulates the most fundamental operations of the class • In C++ we call this an Abstract Base Class • We do not instantiate a Graph ADT • Instead we preferring to instantiate one of the four types of graph sub-ADT’s on the last slide.

  5. Base and derived classes • The Graph ADT is a general template for all graphs. It is a base class • The four sub-ADT’s we have defined are derived classes • They share all the characteristics of the base class, plus they add their own implementations.

  6. Inheritance • In C++, it is common to establish derived classes from base classes. • This is called ‘inheritance’.

  7. Inheritance Hierarchy for Graphs

  8. The Graph ADT abstract base class • class graph { • public: • graph(int size) : n(size), m(0) { } • virtual int vertexSize() { return n; } • virtual int edgeSize() { return m; } • virtual void addEdge(int fromV, int toV) = 0; // specify abstract class • protected: • int n; // number of vertices • int m; // number of edges • };

  9. C++ notes • The constructor • graph(int size) : n(size), m(0) { } • has no body to be included in another file (like that of a derived type), but • initializes n to the argument size, and • assigns m to 0 • recall: n is the number of vertices and m is the number of edges

  10. Deriving Adj. List graphs • The adjacency list graph is a sub-ADT of the Graph ADT. • We will establish it, so that a further classes (directed or undirected adjacency list ADT’s) can be derived from it.

  11. Adj. List Graph ADT • Characteristics: • A List L stores items of some type, called ListElementType. • The items in the List are ordered; • the Lists (1,2) and (2,1) are distinct.

  12. Operations • void L.insert(ListElementType elem) • Precondition: None. • Postcondition: L = L with an instance of elem added to the end of L.

  13. first() • bool L.first(ListElementType &elem) • Precondition: None. • Postcondition: If the list is empty, none. Otherwise, the variable elem contains the first item in L; the “next” item to be returned is the second in L. • Returns: true if and only if there is at least one element in L.

  14. next() • bool L.next(ListElementType &elem) • Precondition: The “first” operation has been called at least once. • Postcondition: Variable elem contains the next item in L, if there is one, and the next counter advances by one; if there is no next element, none. • Returns:true if and only if there was a next item.

  15. Use of first and next • For iteration • for (p=L.first(); p; p=L.next())

  16. Using our ALGraph ADT • The adjacency list is essentially a list of linked lists. • The standard List ADT provides a way to iterate through a list, it does not provide a way for two iterative process to work simultaineously however. • One way to solve the dilemma is to create and ‘iterator class’

  17. Iterator class • An iterator class provides a movable pointer. • We can instantiate as many of them as we need. • In our case, one will iterate through vertices while the other can be used to iterate through edges

  18. friend functions • Iterators only make sense however if they have some other object to iterate on. • Therefore, we will allow objects of our iterator class to have access to the internal (private) portions of our List ADT. • We do this by declaring the class to be a ‘friend class’ • friend class ListIter < ListElementType >;

  19. List and ListIter • Our List class will only construct the list and insert new members • Our List iterator class (ListIter) will move pointers around the List as we need to perform various key List operations.

  20. Class List: public section • template < class ListElementType > • class List { • public: • List() : head(0) { } • virtual void insert(const ListElementType & elem); • friend class ListIter < ListElementType >;

  21. Class List: protected section • protected: • struct Node; • typedef Node * Link; • struct Node { • ListElementType elem; • Link next; • }; • Link head; • }; elem next

  22. ListIter considerations • We will want to pass a list to the ListIter so that it constructs a pointer to that List and guarantees that the list will be not change through iteration (const) • We will also need to have some indication of when to stop iterating. Perhaps a sentinel value marking the end of the List under consideration.

  23. Class ListIter: public section • template < class ListElementType > • class ListIter { • public: // constructor makes const List called myList • // I is the list the iterator will work on • ListIter( const List < ListElementType > & l, ListElementType endFlag ) • : myList(l), myEndFlag(endFlag), iterPtr(0) { } • virtual ListElementType operator++();

  24. Class ListIter: protected section • protected: • const List < ListElementType > & myList; • List < ListElementType >::Link iterPtr; • ListElementType myEndFlag; • }; Works because of ‘friend’ status.

  25. Overloaded operator++ • template < class ListElementType > ListElementType • ListIter < ListElementType > :: operator++() • { if (iterPtr == 0) // if NULL point to head • iterPtr = myList.head; • else // else point to next Link • iterPtr = iterPtr->next; • // Now that the pointer is advanced... • if (iterPtr) // if it now points to a Link • return iterPtr->elem; // return the element • else // else it points to NULL • return myEndFlag; // return end-of-list • }

  26. insert() • template < class ListElementType > • void List < ListElementType > :: insert(const ListElementType & elem) • { // prepend to list • Link addedNode = new Node; • assert(addedNode); • addedNode->elem = elem; • addedNode->next = head; • head = addedNode; • }

  27. AL Base Class • Finally, we can construct an adjacency list base class from • the Graph abstract base class • the ListIter class

  28. Adjacency List Base Class header • #include "cx12-1.h" // graph base class • #include "cx12-2.h" // list class • typedef List < int > IntList; • typedef ListIter < int > IntListIter;

  29. Class ALGraph() • class ALGraph : public graph { • public: • ALGraph(int size) : graph(size) • { vertexList = new IntList[n]; assert(vertexList); } • friend class NeighborIter; • protected: • IntList * vertexList; • }; call the graph constructor

  30. Class NeighborIter() • class NeighborIter : public IntListIter { • public: • NeighborIter(const ALGraph & G, int startVertex) : • IntListIter (G.vertexList[startVertex], G.n) • { assert(startVertex < G.n); } • };

  31. UALists and DALists • Now that we have defined • Graph abstract base class • Iterator class • Adjacency list class • We can derive the bottom-most ADTs • Undirected adjacency lists • Directed adjacency lists

  32. Undirected ALGraph header • class UALGraph : public ALGraph { • public: • UALGraph(int size) : ALGraph(size) { } • virtual void addEdge(int fromV, int toV); • };

  33. Implementation of UALGraph • void • UALGraph::addEdge(int fromV, int toV) • { • assert(fromV < n && fromV >= 0 • && toV < n && toV >= 0); • vertexList[fromV].insert(toV); • vertexList[toV].insert(fromV); • m++; • }

  34. DALGraph header • #include "cx12-4.h" // ALGraph -- Adjacency List Base Class • class DALGraph : public ALGraph { • public: • DALGraph(int size) : ALGraph(size) { } • virtual void addEdge(int fromV, int toV); • };

  35. Implementation for DALGraph • void • DALGraph::addEdge(int fromV, int toV) • { • assert(fromV < n && fromV >= 0 • && toV < n && toV >= 0); • vertexList[fromV].insert(toV); • m++; • }

  36. Topological Sorting • A topological sort is a method of arranging the nodes of a graph in some logical order. • Example: the course prerequisites. • The problem: • given a partial order of nodes in a graph • find the total order that is consistent with the partial order (in other words, rearrange the vertices without changing the edge relationships so we can see a linear progression).

  37. Partial Order Example

  38. Topsort solutions • 0,1,2,3,4 • 0,2,3,1,4 • There is often more than one total order that displays the characteristics of the partial order.

  39. A Topsort algorithm • If a vertex has no ‘in-edges’, then it can be placed in order right away (see 1 below).

  40. Topsort algorithm after one step

  41. Topsort algorithm (con’t) • Now look for another vertex with no in-edges and take it out of circulation.

  42. Topsort after the second step

  43. Topsort (con’t) • Continue until all vertices have been considered. • Resulting total order: 1, 0, 3, 2, 4 • Note, this retains the original partial order

  44. Original partial order

  45. Topsort problem • Topsort only works as long as the graph lends itself to ordering. • Graphs with cycles in them cannot be topologically sorted because there is a portion in which every node had an ‘in-edge’.

  46. Graph with a cycle

  47. Improvements • To improve the Topsort algorithm we have a number of things we can do. • First, we must recognise cycles and abort. • Second, when we search for nodes with no ‘in-edges’ we should start with the likeliest candidates. These are nodes that were formerly adjacent to the last one we selected in our sort. After all, they just lost an in-edge and may not have any left.

  48. Topsort algorithm • nextLabel = 1 • find all vertex with no in-edges and push them onto a stack • while the stack is not empty do • pop a vertex v from the stack • label(v) = nextLabel • add 1 to nextLabel • remove all other edges from v • if any neighbor of v now has no in-edge, • push it onto the stack • if all vertices labeled, • report the labels • else • report that the digraph has a cycle

  49. One Step in a Topological Sort

  50. Step 1 Push all vertices without ‘in-edges’ onto the stack. Push 0 on the stack Push 1 on the stack 1 0 0

More Related