Fundamentals of Computer Science II (CSC-152 97F)

[News] [Basics] [Syllabus] [Outlines] [Assignments] [Examples] [Readings] [Bailey Docs]

# Outline of Class 31: Stacks and Queues

## Miscellaneous

• William is feeling somewhat better, but it will still be awhile until I get the remaining homework back to you. Sorry. I may also have to leave early today.
• The midterm is now graded, and solutions are now available. You folks generally did very well (except for a few problems on number three for which I'm allowing makeups). I don't report on median, mean, maximum, or minimum grades.
• I've updated yesterday's outline to include some notes from our discussion of characaters.
• You should have read chapter eight for today. You should read chapter nine for tomorrow.
• The revised suggestion for assignment five is Friday.
• There will be a Sunday night dinner this week. Let me know if you're interested. I'll also try to find another night for those of you who can't make Sunday nights.

## Linear Structures

• One problem with lists is that they provide just too many options. You can put at and retrieve elements from the front, back, or even middle of the list.
• This can make implementation more difficult, as we've already seen.
• This can also make usage of lists more difficult, as a user needs to consider the interrelationship of the different functions.
• Many uses of lists can be simplified to four basic operations:
• Add an element to the list (or related structure).
• Remove an element from the list (or related structure).
• Peek at the next element to be removed.
• Check if there are any elements remaning.
• Structures that support these three operations are often called linear structures.
• A policy determines the relationship between objects being added and objects being removed.
• A first-in, first-out (FIFO) policy says that objects are removed in the order that they're put in.
• A last-in, first-out (LIFO) policy says that objects are removed in the opposite order that they're put in (so the object most recently added is the next one to be removed).
• Other policies might place priorities on the objects, or randomly select objects.

## Stacks

• Stacks are linear structures that use the LIFO policy.
• They are similar to the stacks of dishes that you may see in cafeterias. As each dish is cleaned, it is added to the top of the stack. As customers need dishes, they remove them from the top of the stack.
• The standard names for stack operations are
• `push(Object o)` -- add an element to the top of the stack
• `Object pop()` -- remove an element from the top of the stack
• `Object peek()` -- look at the element on the top of the stack
• `boolean empty()` -- check if the stack is empty
• There are many uses for stacks, and we'll keep coming back to them as the term progresses. These uses include:
• Providing support for recursive procedure calls
• Searching structures
• Computation

### Reverse Polish Notation

• Many people, from mathematicians to primary school students, have criticized our standard infix representation of expressions as being ambiguous, or using a complex system for resolving ambiguity.
• Consider the expression 2 + 3 * 5. Which operation do we do first? Left-to-right makes sense, especially to beginners, but we use a complex system of priorities to determine which operation is done first.
• This is also complex to compute, as you need to look ahead to determine whether or not it is safe to do an operation (hmmm ... how far do you need to look ahead).
• For this reason, alternate notations have been developed. One of the easiest is reverse polish notation (RPN) in which the operations follows the operands.
• This is also called postfix notation.
• RPN is traditionally implemented using stacks. When you see a number, push it on the stack. When you see an operation, pop the operands off the stack, do the operation, and push the result back on the stack.
• For example, to add two to three and then multiply by five, we'd use
`2 3 + 5 *`.
• Similarly, to multiply three and five and then add 2, we might write
`2 3 5 * +`
• RPN is unambiguous and requires no parenthesization. It is used by a number of calculators (particularly HP's) and is supported by the Unix program `dc`.

### Implementing Stacks

• As you might guess from our multiple implementations of lists, there are also multiple implementations of stacks.
• The implementation we choose may depend on our knowledge of the use of the stack (e.g., are we going to have a limited or unlimited size?) and the limitations of our programming language (e.g., does it support dynamic data allocation).
• The two most basic ways to implement stacks are with vectors and lists.

#### Implementing Stacks with Lists

• A list-based implementation is relatively straightforward, as many list implementations include all the standard stack operations.
• `push(o)` is just another name for `insertAtFront(o)`
• `pop()` is just another name for `removeFromFront()`
• `peek()` is just another name for `head()`

#### Implementing Stacks with Arrays and Vectors

• Array-based (or vector-based) implementations are nearly as easy. We simply add elements to the end of the array, and remove elements from the end of the array.
• We may need to keep track of the position of the last element, but we can also use the `size()` or `length` to determine that.

## Queues

• Often, linear structures are used to organize tasks to be done (e.g., places in a maze to look at, potential solutions to a programming problem, ...).
• One problem with stacks is that the first things that are added to the stack are the last removed, so if we keep finding new things to try, we'll never try the first ones.
• To provide a sense of fairness, we might instead require that the earlier tasks are done first.
• Queues are FIFO linear structures. They are similar to lines at a bank teller or elsewhere.
• The main methods in queues are
• `enqueue(Object o)` -- add an object to the back of the queue
• `Object dequeue()` -- remove an object from the front of the queue
• `Object front()` -- determine what's at the front of the queue, but don't remove it.
• `boolean empty()` -- are there any elements in the queue?
• Like stacks, queues are used for a variety of purposes.
• Like stacks, queues can be implemented in multiple ways.

### Doubly-Ended Queues

• In some odd cases, it may make sense to add elements to or remove elements from both the front and back of the queue.
• Queues that support this extension are called doubly-ended queues or simply dequeues (isn't that a wonderful name conflict with the operation?)

### Implementing Queues with Lists

• The list-based implementation is trivial.

### Implementing Queues with Arrays

• If the queue will never exceed a particular side, it is also possible to implement queues with arrays by wrapping the end of the queue around to the front.
• Here's a sketch (not necc. correct, and with no error checking)
```public ArrayQueue {
/** The elements of the queue */
Object[] elements;
/** The index of the first element in the queue */
int first;
/** The index of the last element in the queue */
int last;
/** Add an element to the back of the queue */
public void enqueue(Object o) throws QueueException {
back = (back + 1) % elements.length;
elements[back] = o;
} // enqueue
/** Remove an element from the front of the queue */
public Object dequeue() throws QueueException {
Object returnme;
returnme = elements[front];
front = (front + 1) % elements.length;
return returnme;
} // dequeue
} // ArrayQueue
```
• Unfortunately, there are a host of potential errors in this implementation, particularly dealing with the differences between full and empty queues. In my experience, many people get a few cases wrong in this implementation.

Outlines: prev next

[News] [Basics] [Syllabus] [Outlines] [Assignments] [Examples] [Readings] [Bailey Docs]

Disclaimer Often, these pages were created "on the fly" with little, if any, proofreading. Any or all of the information on the pages may be incorrect. Please contact me if you notice errors.