1 / 93

Chapter 5

Chapter 5. Stacks. Chapter Objectives. To learn about the stack data type and how to use its four functions: push pop top empty To understand how C++ implements a stack To learn how to implement a stack using an underlying array or linked list

lavender
Download Presentation

Chapter 5

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

  2. Chapter Objectives • To learn about the stack data type and how to use its four functions: • push • pop • top • empty • To understand how C++ implements a stack • To learn how to implement a stack using an underlying array or linked list • To see how to use a stack to perform various applications, including finding palindromes, testing for balanced (properly nested) parentheses, and evaluating arithmetic expressions

  3. Stacks are Specialized Lists • A client using a list can access any element, remove any element, and insert an element anywhere in the list • A client using a stack can access (and remove) only the most recently inserted element, and can insert an element only at the “top” of the stack • Stacks are among the most commonly used data structures in computer science

  4. The Stack Abstract Data Type Section 5.1

  5. Stack Abstract Data Type • A stack is one of the most commonly used data structures in computer science • A stack can be compared to a Pez dispenser • Only the top item can be accessed • You can extract only one item at a time • The top element in the stack is the last added to the stack (most recently) • The stack’s storage policy is Last-In, First-Out, or LIFO

  6. Specification of the Stack Abstract Data Type • Only the top element of a stack is visible; therefore the number of operations performed by a stack are few • We need the ability to • test for an empty stack (empty) • retrieve the top element (top) • remove the top element (pop) • put a new element on the stack (push)

  7. Specification of the Stack Abstract Data Type (cont.)

  8. A Stack of Strings • We create the (a) stack using the following statements: stack<string> names; names.push("Rich"); names.push("Debbie"); names.push("Robin"); names.push("Dustin"); names.push("Jonathan");

  9. A Stack of Strings (cont.) • For stack names in (a), the value of names.empty() is false • The statement string last = names.top(); • stores "Jonathan" in last without changing names • The statement names.pop() • removes "Jonathan" from names • The stack names now contains four elements as shown in (b)

  10. A Stack of Strings (cont.) • The statement names.push("Philip"); • pushes "Philip" onto the stack • The stack names now contains five elements and is shown in (c)

  11. Stack Applications Section 5.2

  12. Finding Palindromes • Palindrome: a string that reads identically in either direction, letter by letter (ignoring case) • kayak • "I saw I was I" • “Able was I ere I saw Elba” • "Level madam level" • Problem: Write a program that reads a string and determines whether it is a palindrome

  13. Finding Palindromes (cont.) • Analysis: • Possible solutions: • Set up a loop in which we compare the characters at each end of a string as we work towards the middle • If any pair of characters is different, the string can’t be a palindrome • Scan a string backward (from right to left) and append each character to the end of a new string, which would become the reverse of the original string. Then we can determine see if the strings were equal • The approach we will take here uses a stack to assist in forming the reverse of a string • It is not the most efficient way to solve the problem, but it makes good use of a stack

  14. Finding Palindromes (cont.) • Analysis: • If we scan the input string from left to right and push each character in the input string onto a stack of characters, we can form the reverse of the string by popping the characters and joining them together in the order that they come off the stack • For example, the stack at left contains the characters in the string "I saw" • If we pop them off and join them together, we get "w" + "a" + "s" + " " + "I", or the string "was I" • When the stack is empty, we can compare the string we formed with the original • If they are the same, the original string is a palindrome

  15. Data Requirements • PROBLEM INPUTS • An input string to be tested • PROBLEM OUTPUTS • A message indicating whether the string is a palindrome

  16. Design

  17. Implementation

  18. Implementation (cont.)

  19. Testing • To test this class using the following inputs: • A single character (always a palindrome) • Multiple characters in one word • Multiple words • Different cases • Even-length strings • Odd-length strings • An empty string (considered a palindrome)

  20. Testing (cont.) • An application of class Palindrome_Finder should have the following main function: int main() { string line; cout << "Enter a string followed by a new line\n" << "To quit, enter an empty line: "; while (getline(cin, line) && (line != "")) { cout << line; if (Palindrome_Finder(line).is_palindrome()) cout << " is a palindrome\n\n"; else cout << " is not a palindrome\n\n"; cout << "Enter a new string to test: "; } }

  21. Balanced Parentheses • When analyzing arithmetic expressions, it is important to determine if an expression is balanced with respect to parentheses • The expression below is balanced: (w * (x + y) / z – (p / (r - q))) • The problem is complicated if braces or brackets are used in conjunction with parentheses • The expression below is not balanced: (w * [x + y) / z – [p / {r – q}])

  22. Analysis • An expression is balanced if each subexpression that starts with the symbol “{“ ends with the symbol “}”, and the same statement is true for the other symbol pairs • Another way of saying this is that an opening parenthesis at position k in the sequence “{[(“ must be paired with the closing parenthesis at position k in the sequence “}])”

  23. Analysis (cont.) • We can use a stack to determine whether the parentheses are balanced (or nested properly): • We will scan the expression from left to right, ignoring all characters except for parentheses • We will push each open parenthesis onto a stack of characters • When we reach a closing parenthesis, we will see whether it matches the open parenthesis symbol on the top of the stack • If so, we will pop it off and continue the scan • If the characters don’t match or the stack is empty, there is an error in the expression • If there are any characters left on the stack when we are finished, that also indicates an error

  24. Data Requirements • PROBLEM INPUTS • An expression string • PROBLEM OUTPUTS • A message indicating whether the expression has balanced parentheses

  25. Design

  26. Balanced Parentheses (cont.) (w * [x + y] / z) Expression: 0 1 2 3 4 5 6 7 8 9 10 ( w * [ x + y ] / z ) ( ( balanced : true index : 0

  27. Balanced Parentheses (cont.) (w * [x + y] / z) Expression: 0 1 2 3 4 5 6 7 8 9 10 ( w * [ x + y ] / z ) ( ( balanced : true index : 1

  28. Balanced Parentheses (cont.) (w * [x + y] / z) Expression: 0 1 2 3 4 5 6 7 8 9 10 ( w * [ x + y ] / z ) ( ( balanced : true index : 2

  29. Balanced Parentheses (cont.) (w * [x + y] / z) Expression: 0 1 2 3 4 5 6 7 8 9 10 ( w * [ x + y ] / z ) [ [ ( ( ( balanced : true index : 3

  30. Balanced Parentheses (cont.) (w * [x + y] / z) Expression: 0 1 2 3 4 5 6 7 8 9 10 ( w * [ x + y ] / z ) [ ( ( balanced : true index : 4

  31. Balanced Parentheses (cont.) (w * [x + y] / z) Expression: 0 1 2 3 4 5 6 7 8 9 10 ( w * [ x + y ] / z ) [ ( ( balanced : true index : 5

  32. Balanced Parentheses (cont.) (w * [x + y] / z) Expression: 0 1 2 3 4 5 6 7 8 9 10 ( w * [ x + y ] / z ) [ ( ( balanced : true index : 6

  33. Balanced Parentheses (cont.) (w * [x + y] / z) Expression: 0 1 2 3 4 5 6 7 8 9 10 ( w * [ x + y ] / z ) [ ( ( ( Matches! Balanced still true balanced : true index : 7

  34. Balanced Parentheses (cont.) (w * [x + y] / z) Expression: 0 1 2 3 4 5 6 7 8 9 10 ( w * [ x + y ] / z ) ( ( balanced : true index : 8

  35. Balanced Parentheses (cont.) (w * [x + y] / z) Expression: 0 1 2 3 4 5 6 7 8 9 10 ( w * [ x + y ] / z ) ( ( balanced : true index : 9

  36. Balanced Parentheses (cont.) (w * [x + y] / z) Expression: 0 1 2 3 4 5 6 7 8 9 10 ( w * [ x + y ] / z ) ( ( Matches! Balanced still true balanced : true index : 10

  37. Implementation

  38. Implementation • (please split the listing on the preceding slide at “boolis_balanced…” putting the second half here, and enlarging both halves)

  39. Testing • Provide a variety of input expressions displaying the result true or false • Try several levels of nested parentheses • Try nested parentheses where corresponding parentheses are not of the same type • Try unbalanced parentheses • Try no parentheses at all! • PITFALL: • If you attempt to pop an empty stack your program will probably halt and report a run-time error • The nature of the error message will depend on the compiler and operating system • It is possible that no error is reported at all. You can guard against this error by testing for a nonempty stack before calling top or pop

  40. Implementing a Stack Section 5.3

  41. Implementing a Stack • A stack is similar to a vector • The standard library defines the stack as a template class that takes any of the sequential containers (vector, list, or deque – described in Chapter 6) as a template parameter • We present two implementations in this section: • A standard template container • A special-purpose single-linked list

  42. Implementing a Stack (cont.)

  43. Implementing a Stack (cont.)

  44. Implementing a Stack (cont.) • This implementation is similar to the implementation in the C++ standard library • All sequential containers provide the functions empty, size, back (equivalent to stack::top), push_back (equivalent to stack::push) and pop_back (equivalent to stack::pop), so we could use any of these containers

  45. Adapter Classes and the Delegation Pattern • The stack class uses the delegation pattern discussed in Chapter 4 by making the functions in the underlying container class do its work for it • It is also said to be an adapter class because it adapts the functions available in another class to the interface its clients expect by giving different names to essentially the same operations • For example, if a vector is used as the container object, stack::push corresponds to vector::push_back, stack::top corresponds to vector::back, and so on

  46. Revisiting the Definition File stack.h • To implement the stack using a vector object as a container, change the definition of the data member container in the private part of the class definition: std::vector<Item_Type> container; • If you prefer to use a deque for a container, substitute deque<Item_Type> for vector<Item_Type> in the declaration of container

  47. Revisiting the Definition File stack.h(cont.) • The member function implementations shown in the preceding listing should be included after the class definition but before the end of the namespace • Template member function implementations must be included with the class definitions • In the preceding listing, we used an include directive to insert the code for the member function definitions at the end of the file: // Insert implementation of member functions here #include Stack.tc } // End namespace KW #endif • The listing on the next slide shows an alternative which replaces each function declaration in file stack.h with its actual definition

  48. Revisiting the Definition File stack.h(cont.)

  49. Implementing a Stack as a Linked Data Structure • We can also implement a stack using a linked list of nodes

  50. Implementing a Stack as a Linked Data Structure (cont.) • File Linked_Stack.tc defines a stack class that contains a collection of Node objects • Recall that inner class Node has data fields data (type Item_Type) and next (type Node*) • To use this implementation we need to replace the statements at the end of file stack.h with the following: private: #include "Node.h" Node* top_of_stack; }; // End class stack #include "Linked_Stack.tc" } // End namespace KW #endif

More Related