



Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
Abstract data types (adts) and focuses on the stack adt as a collection data type. The interface of a stack, which includes initialization, pushing, popping, and checking if it's empty. It also covers implementing stacks using python lists and using a stack to evaluate postfix expressions. The document highlights the benefits of using a stack, such as simplifying algorithm specification and providing a common high-level language.
Typology: Study notes
1 / 7
This page cannot be seen from the preview
Don't miss anything!




The data types you have seen so far are all concrete, in the sense that we have completely specified how they are implemented. For example, the Card class represents a card using two integers. As we discussed at the time, that is not the only way to represent a card; there are many alternative implementations.
An abstract data type, or ADT, specifies a set of operations (or methods) and the semantics of the operations (what they do), but it does not specify the implementation of the operations. That’s what makes it abstract.
Why is that useful?
190 Stacks
When we talk about ADTs, we often distinguish the code that uses the ADT, called the client code, from the code that implements the ADT, called the provider code.
In this chapter, we will look at one common ADT, the stack. A stack is a collection, meaning that it is a data structure that contains multiple elements. Other collections we have seen include dictionaries and lists.
An ADT is defined by the operations that can be performed on it, which is called an interface. The interface for a stack consists of these operations:
init : Initialize a new empty stack.
push: Add a new item to the stack.
pop: Remove and return an item from the stack. The item that is returned is always the last one that was added.
isEmpty: Check whether the stack is empty.
A stack is sometimes called a “last in, first out” or LIFO data structure, because the last item added is the first to be removed.
The list operations that Python provides are similar to the operations that define a stack. The interface isn’t exactly what it is supposed to be, but we can write code to translate from the Stack ADT to the built-in operations.
This code is called an implementation of the Stack ADT. In general, an implementation is a set of methods that satisfy the syntactic and semantic requirements of an interface.
Here is an implementation of the Stack ADT that uses a Python list:
class Stack : def init(self) : self.items = []
def push(self, item) : self.items.append(item)
192 Stacks
You should compare this bit of code to the implementation of printBackward in Section 17.4. There is a natural parallel between the recursive version of printBackward and the stack algorithm here. The difference is that printBackward uses the runtime stack to keep track of the nodes while it tra- verses the list, and then prints them on the way back from the recursion. The stack algorithm does the same thing, except that it uses a Stack object instead of the runtime stack.
In most programming languages, mathematical expressions are written with the operator between the two operands, as in 1+2. This format is called infix. An alternative used by some calculators is called postfix. In postfix, the operator follows the operands, as in 1 2 +.
The reason postfix is sometimes useful is that there is a natural way to evaluate a postfix expression using a stack:
As an exercise, apply this algorithm to the expression 1 2 + 3 *.
This example demonstrates one of the advantages of postfix—there is no need to use parentheses to control the order of operations. To get the same result in infix, we would have to write (1 + 2) * 3.
As an exercise, write a postfix expression that is equivalent to 1 + 2
To implement the previous algorithm, we need to be able to traverse a string and break it into operands and operators. This process is an example of parsing,
18.7 Evaluating postfix 193
and the results—the individual chunks of the string—are called tokens. You might remember these words from Chapter 1.
Python provides a split method in both the string and re (regular expression) modules. The function string.split splits a string into a list using a single character as a delimiter. For example:
import string string.split("Now is the time"," ") [’Now’, ’is’, ’the’, ’time’]
In this case, the delimiter is the space character, so the string is split at each space.
The function re.split is more powerful, allowing us to provide a regular ex- pression instead of a delimiter. A regular expression is a way of specifying a set of strings. For example, [A-z] is the set of all letters and [0-9] is the set of all numbers. The ^ operator negates a set, so [^0-9] is the set of everything that is not a number, which is exactly the set we want to use to split up postfix expressions:
import re re.split("([^0-9])", "123+456/") [’123’, ’+’, ’456’, ’’, ’’, ’/’, ’’]
Notice that the order of the arguments is different from string.split; the delimiter comes before the string.
The resulting list includes the operands 123 and 456 and the operators * and /. It also includes two empty strings that are inserted after the operands.
To evaluate a postfix expression, we will use the parser from the previous section and the algorithm from the section before that. To keep things simple, we’ll start with an evaluator that only implements the operators + and *:
18.9 Glossary 195
abstract data type (ADT): A data type (usually a collection of objects) that is defined by a set of operations but that can be implemented in a variety of ways.
interface: The set of operations that define an ADT.
implementation: Code that satisfies the syntactic and semantic requirements of an interface.
client: A program (or the person who wrote it) that uses an ADT.
provider: The code (or the person who wrote it) that implements an ADT.
veneer: A class definition that implements an ADT with method definitions that are invocations of other methods, sometimes with simple transforma- tions. The veneer does no significant work, but it improves or standardizes the interface seen by the client.
generic data structure: A kind of data structure that can contain data of any type.
infix: A way of writing mathematical expressions with the operators between the operands.
postfix: A way of writing mathematical expressions with the operators after the operands.
parse: To read a string of characters or tokens and analyze its grammatical structure.
token: A set of characters that are treated as a unit for purposes of parsing, such as the words in a natural language.
delimiter: A character that is used to separate tokens, such as punctuation in a natural language.