1 / 26

Chapter 3: Lists, Stacks, and Queues

Chapter 3: Lists, Stacks, and Queues. Abstract Data Types. Lists and Sorted Lists. Stacks and Stack Applications. Queues and Queue Applications. CS 340. Page 34. Abstract Data Types. An ADT is a set of operations upon a set of data. Implementation details are not specified in an ADT.

maj
Télécharger la présentation

Chapter 3: Lists, Stacks, and Queues

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. Chapter 3: Lists, Stacks, and Queues • Abstract Data Types • Lists and Sorted Lists • Stacks and Stack Applications • Queues and Queue Applications CS 340 Page 34

  2. Abstract Data Types An ADT is a set of operations upon a set of data. • Implementation details are not specified in an ADT. • The program designer determines the operations that are needed and the specific data that will be used in the implementation. • The implementation of the ADT should be easy to modify, and such modifications should be transparent to any code deploying the ADT. CS 340 Page 35

  3. ADT #1: The List A list is a finite ordered collection of items of the same type. Common list operations include: • Emptying the entire list • Determining whether the list is empty • Determining the size of the list • Determining the location of a particular list element • Determining the value of an element at a particular location in the list • Inserting a new list element at a particular location • Removing a particular element from the list • Outputting the entire list CS 340 Page 36

  4. a1 a2 Emptying the list O(1) a3 Determining if the list is empty O(1) : Determining the size of the list O(1) an-2 Determining the location of a particular element O(n) Determining the value of an element in a particular location O(1) an-1 Inserting a new element into a particular location O(n) an Removing a particular element O(n) ? Outputting the list O(n) ? : ? List Implementation Option: Array An Array Implementation’s Performance n • Problems with the array implementation: • Data movement really slows down insertions to and removals from the list • The maximum list size must be specified CS 340 Page 37

  5. a1 Emptying the list O(n) Determining if the list is empty O(1) a2 Determining the size of the list O(n) Determining the location of a particular element O(n) a3 Determining the value of an element in a particular location O(n) Inserting a new element into a particular location O(1) : Removing a particular element O(1) Outputting the list O(n) an-2 an-1 an List Implementation Option: Linked List A Linked List Implementation’s Performance • Problems with the linked list implementation: • Pointers consume memory not needed with arrays • Lack of indexing necessitates repeated list traversals (e.g., binary search is impossible) CS 340 Page 38

  6. Linked List Implementation in Visual C++ #ifndefLIST_H #include <cstdlib> template <classEtype> class list { protected: structnode { Etype element; node *next; node(Etype e = 0, node *n = NULL) : element(e), next(n) {} }; node *head; node *current; voiddeleteList(); public: list(): head(new node), current(head) {} virtual ~list() { deleteList(); } constlist& operator = (list &value); constlist& operator ++ (); bool operator ! () const; constEtype& operator () () const; boolisEmpty() const{ return (head->next == NULL); } virtual boolfind(constEtype &x); virtual boolfindPrevious(constEtype &x); void first() { if (head->next != NULL) current = head->next; } void header() { current = head; } boolremove(constEtype &x); virtual void insert(constEtype &x); virtual void insertAsFirstElement(constEtype &x); }; Class Template Structure Structure Constructor Virtual Function: Derived classes may have their own version of this function Class Constructor Class Destructor Constant Modifier: This operator accesses but doesn’t modify Constant Return: Value returned is treated as a constant In-Line Code CS 340 Page 39

  7. // Member function to free all memory associated with the linked list. template <classEtype> void list<Etype>:: deleteList() { node *p = head->next; node *temp; while (p != NULL) { temp = p->next; delete p; p = temp; } delete head; } // Assignment operator: duplicates parameterized linked list. template <classEtype> inline constlist<Etype>& list<Etype>:: operator = (list &value) { if (this == &value) return *this; deleteList(); current = head = new node; for (value.first(); !value; ++value) { current->next = new node(value(), current->next); current = current->next; } current->next = NULL; first(); value.first(); return *this; } In-Line Function: Prompts the compiler to generate code inline instead of laying it down once and calling it through the usual mechanisms, improving performance for functions that do little but are called often CS 340 Page 40

  8. // Increment operator: moves current pointer to next node (if possible). template <classEtype> inline const list<Etype>& list<Etype>:: operator ++ () { if (current != NULL) current = current->next; return *this; } // Logical “not” operator: indicates whether current pointer is non-NULL. template <classEtype> inline boollist<Etype>:: operator ! () const { return (current != NULL); } // Parenthetical operator: returns value of current node (or head node if current is NULL). template <classEtype> inline constEtype& list<Etype>:: operator () () const { if (current != NULL) return current->element; else return head->element; } CS 340 Page 41

  9. // Member function to determine whether parameterized element is in list. template <classEtype> boollist<Etype>:: find(constEtype &x) { node *p; for (p = head->next; p != NULL; p = p->next) { if (p->element == x) { current = p; return true; } } return false; } // Member function to locate predecessor of parameterized value in list. template <classEtype> boollist<Etype>:: findPrevious(constEtype &x) { node *p; for (p = head; p->next != NULL; p = p->next) { if (p->next->element == x) { current = p; return true; } } return false; } CS 340 Page 42

  10. // Member function to remove first occurrence of parameterized value from list. template <classEtype> boollist<Etype>:: remove(constEtype &x) { node *cellToDelete; if (findPrevious(x)) { cellToDelete = current->next; current->next = cellToDelete->next; deletecellToDelete; return true; } return false; } // Member function to insert parameterized value after current node in list. template <classEtype> void list<Etype>:: insert(constEtype &x) { node *p = new node(x, current->next); if (p != NULL) { current->next = p; current = current->next; } } // Member function to insert parameterized value as new head element in list. template <classEtype> void list<Etype>:: insertAsFirstElement(constEtype &x) { header(); insert(x); } #define LIST_H #endif CS 340 Page 43

  11. A Test Driver For The Linked List Implementation #include "List.h" #include <iostream> using namespacestd; voidprintList(list<int> &lst); // The main function generates a couple of integer lists // to test the functionality of the linked list class. void main() { list<int> lst1, lst2; cout << "(This should be empty)" << endl; printList(lst1); for (int i = 1; i <= 5; i++) lst1.insertAsFirstElement(i); cout << "(This should be 5 4 3 2 1)" << endl; printList(lst1); for (int i = 4; i <= 6; i++) if (lst1.find(i)) cout << "Found " << lst1() << endl; else cout << i << " not found" << endl; lst2 = lst1; cout << "(This should be 5 4 3 2 1)" << endl; printList(lst2); lst2.remove(3); cout << "(This should be 5 4 2 1)" << endl; printList(lst2); cout << "(but this should still be 5 4 3 2 1)" << endl; printList(lst1); } CS 340 Page 44

  12. // The printList function outputs the contents // of the linked list, starting at the head. voidprintList(list<int> &lst) { if (lst.isEmpty()) cout << "Empty list." << endl; else for (lst.first(); !lst; ++lst) cout << lst() << endl; } CS 340 Page 45

  13. Inheritance: The sortedList Class If Etype values can be sorted, then the list class can be modified to accommodate this sorting. This can be easily accomplished by deriving a subclass of list, and overriding the two insertion functions insert and insertAsFirstElement. #include "List.h" template <classEtype> classsortedList: public list<Etype> { public: virtual void insert(constEtype &x); virtual void insertAsFirstElement(constEtype &x) { insert(x); } } // This member function inserts the parameterized // value and preserves the sorted nature of the list. template <classEtype> voidsortedList<Etype>:: insert(constEtype &x) { for (node *p = head; p->next != NULL; p = p->next) { if (p->next->element > x) { current = p; break; } } list<Etype>::insert(x); } CS 340 Page 46

  14. A Test Driver For The Sorted List Implementation #include "SortedList.h" #include <iostream> using namespace std; voidprintList(list<int> &lst); // The main function generates a couple of integer lists // to test the functionality of the linked list class. void main() { sortedList<int> lst1, lst2; cout << "(This should be empty)" << endl; printList(lst1); for (int i = 1; i <= 5; i++) lst1.insertAsFirstElement(i); cout << "(This should be 1 2 3 4 5)" << endl; printList(lst1); for (int i = 4; i <= 6; i++) if (lst1.find(i)) cout << "Found " << lst1() << endl; else cout << i << " not found" << endl; lst2 = lst1; cout << "(This should be 1 2 3 4 5)" << endl; printList(lst2); lst2.remove(3); cout << "(This should be 1 2 4 5)" << endl; printList(lst2); cout << "(but this should still be 1 2 3 4 5)" << endl; printList(lst1); } // The printList function outputs the contents // of the linked list, starting at the head. voidprintList(list<int> &lst) { if (lst.isEmpty()) cout << "Empty list." << endl; else for (lst.first(); !lst; ++lst) cout << lst() << endl; } CS 340 Page 47

  15. Polynomial p1(x) = 35x6 - 7x4 + 19x - 5 -4 -3 35 -7 20 19 -5 3 1 6 0 8 1 4 Polynomial p2(x) = -3x8 + 20x3 - 4x Example List Application: Polynomials Let Etype be a two-field structure containing the coefficient and exponent of each monomial within the polynomial. Sort the nodes comprising each polynomial based upon the values of their exponents. The operations for this ADT could include: • Addition, subtraction, and multiplication of polynomials • Derivatives of polynomials • Evaluation of polynomials (i.e., plugging in values) CS 340 Page 48

  16. #include <vector> #include <iostream> using namespace std; void printVector(vector<int> &vec); // The main function generates two integer lists // to test the functionality of the vector class. void main() { vector<int> vec1, vec2; cout << "(This should be empty)" << endl; printVector(vec1); vector<int>::iterator itr = vec1.begin(); for (int i = 1; i <= 5; i++) itr = vec1.insert(itr, i); cout << "(This should be 5 4 3 2 1)" << endl; printVector(vec1); for (int val = 4; val <= 6; val++) { int i = 0; bool found = false; while ( (i < vec1.size()) && (!found) ) if (vec1.at(i) == val) { found = true; cout << "Found " << val << endl; } else i++; if (!found) cout << val << " not found" << endl; } vec2 = vec1; cout << "(This should be 5 4 3 2 1)" << endl; printVector(vec2); for (vector<int>::iterator itr = vec2.begin(); itr != vec2.end(); itr++) if (*itr == 3) itr = vec2.erase(itr); STL List Alternative #1: vector The C++ Standard Template Library provides a built-in implementation of a list ADT: the vector. cout << "(This should be 5 4 2 1)" << endl; printVector(vec2); cout << "(but this should still be 5 4 3 2 1)" << endl; printVector(vec1); } // The printVector function outputs the entire // contents of the vector. void printVector(vector<int> &vec) { if (vec.empty()) cout << "Empty vector." << endl; else for (vector<int>::iterator itr = vec.begin(); itr != vec.end(); itr++) cout << *itr << endl; } The Good News Like arrays, vectors are indexable in constant time. The Bad News Insertion and removal is expensive, except at the end of the vector. CS 340 Page 49

  17. #include <list> #include <iostream> using namespace std; void printList(list<int> &lst); // The main function generates two integer lists // to test the functionality of the list class. void main() { list<int> lst1, lst2; cout << "(This should be empty)" << endl; printList(lst1); for (int i = 1; i <= 5; i++) lst1.push_front(i); cout << "(This should be 5 4 3 2 1)" << endl; printList(lst1); for (int val = 4; val <= 6; val++) { list<int>::iterator itr = lst1.begin(); bool found = false; while ( (itr != lst1.end()) && (!found) ) if (*itr == val) { found = true; cout << "Found " << val << endl; } else itr++; if (!found) cout << val << " not found" << endl; } lst2 = lst1; cout << "(This should be 5 4 3 2 1)" << endl; printList(lst2); for (list<int>::iterator itr = lst2.begin(); itr != lst2.end(); itr++) if (*itr == 3) itr = lst2.erase(itr); STL List Alternative #2: list The C++ STL also provides a second built-in implementation of a list ADT: the list. cout << "(This should be 5 4 2 1)" << endl; printList(lst2); cout << "(but this should still be 5 4 3 2 1)" << endl; printList(lst1); } // The printList function outputs the entire // contents of the vector. void printList(list<int> &lst) { if (lst.empty()) cout << "Empty list." << endl; else for (list<int>::iterator itr = lst.begin(); itr != lst.end(); itr++) cout << *itr << endl; } The Good News Insertion and removal at any known position is inexpensive. The Bad News Like traditional linked lists, this doubly linked list is not easily indexable. CS 340 Page 50

  18.        stk.pop( ) stk.push()       ADT #2: The Stack A stack is a list in which insertions and removals can only transpire at one end of the list, i.e., the top of the stack. CS 340 Page 51

  19. Example Stack Application: Arithmetic Expressions Stacks can be used to convert infix expressions into postfix expressions Following these rules, then, the infix expression 7 + 6 - 3 * ( 5 + 8 / 2 ) is converted into the postfix expression 7 6 + 3 5 8 2 / + * - CS 340 Page 52

  20. 2 8 8 4 5 5 5 5 9 3 6 3 3 3 3 3 27 13 7 13 13 13 13 13 13 Arithmetic Expression Evaluation (continued) Then a separate stack can be used to evaluate the postfix expression Following these rules with the postfix expression 7 6 + 3 5 8 2 / + * - yields: 7 13 -14 CS 340 Page 53

  21. Example Stack Application: The Run-Time Stack • Stores local data and call information for nested procedures in a program • Grows downward from its origin • Stack pointer points to current topmost data item on the stack • Push operation decrements pointer and copies data to stack • Pop operation copies data from stack and then increments pointer • Each procedure called in the program stores procedure return information (in yellow) and local data (in other colors) by pushing them onto stack CS 340 Page 54

  22. Stack Implementation Alternatives • An Array Implementation • Positives • Trivial implementation due to indexing • Negatives • Size must be declared in advance • A Linked List Implementation • Positives • Dynamically allocates the right amount of memory • Straightforward (if not quite trivial) implementation • Negatives • Wastes memory for pointers that are underutilized CS 340 Page 55

  23.     que.dequeue( )     que.enqueue()      ADT #3: The Queue A queue is a list in which insertions can only occur at one end of the list (the front of the queue) and removals can only occur at the opposite end of the list (the back of the queue). CS 340 Page 56

  24. Example Queue Application: Server Access The “first-come, first-served” nature of the queue ADT can be adapted to providing orderly access to file servers, print servers, Web servers, etc. Curly’s Print Job #1 Moe’s Print Job #2 Larry’s Print Job #1 Moe’s Print Job #1 CS 340 Page 57

  25. Example Queue Application: Breadth-First Search • Search a tree structure for a goal, beginning at the root node and exploring all neighboring nodes • Use a queue to remember which nodes have yet to be fully explored • If the queue is ever empty without the goal being found, then the goal isn’t in the tree bfs(v) enqueue(v) while queue not empty v=dequeue() process(v) for all unvisited vertices i adjacent to v mark i as visited enqueue(i) CS 340 Page 58

  26. Queue Implementation Alternatives • An Array Implementation • Positives • Straightforward implementation due to indexing • Negatives • Size must be declared in advance • Wraparound is needed to avoid false overflows • A Linked List Implementation • Positives • Dynamically allocates the right amount of memory • Wraparound problem is circumvented • Negatives • Wastes memory for pointers that are underutilized CS 340 Page 59

More Related