Stacks

From

Revision as of 13:15, 1 April 2009 by Admin (Talk | contribs)
Jump to: navigation, search

The Stack ADT is a collection of homogeneous data that organizes its entries according to the order in which they were added. The organization is called LIFO or Last In, First Out (Sometimes called FILO). In the ADT Stack, there is one access point called the top of the stack, and only the item at the top, which is the most recently added item, is visible. The normal operations that can be performed on a stack are: push(), pop(), peek(), and isEmpty(). Sometimes there will be an operation called isFull().

Intuitively, a stack is like a pile of plates where we can only remove a plate from the top and can only add a new plate on the top. In computer science we commonly place numbers on a stack, or perhaps place records on the stack.

Behavior of Stacks

The Push operation places a new data item on top of the stack. Pop removes the top item and sends it back via the parameter. Finally, the Empty operation tells us whether or not the stack object is empty. Here are a picture of a small stack of integers and another picture of the stack after 34 has been pushed:
Image:Stack1.gif

Implementation of Stacks

One of the many uses of a stack is to reverse data. Consider a singly linked list of numbers that is kept in order from smallest (at the head) to the largest (at the rear). What if I wanted to print out the numbers in order from largest to smallest? Implementation. A stack is usually implemented in one of two ways: either using an array or a linked list.


With an array, we need an isFull() operation. There is normally an index called top, which is initialized to -1. Given this, the push() operation is

FUNCTION push( )
    IF not isFull( )
        Let top = top + 1
        Let Stack[ top ] = data 
    ENDIF
ENDFUNCTION

The pop() operations can then be implemented with

FUNCTION pop( )
    IF not isEmpty( ) 
        LET top = top - 1
        return( stack[ top ] )
    ELSE
        return null
    ENDIF
ENDFUNCTION

The isFull() operation is

FUNCTION isFull( )
    IF top equals N - 1 THEN
        return TRUE
    ELSE
        return FALSE
    ENDIF
ENDFUNCTION 

And the isEmpty() operation is

FUNCTION isEmpty( )
    IF top equals - 1 THEN
        return TRUE
    ELSE
        return FALSE
    ENDIF
ENDFUNCTION

When a stack is implemented as a linked list, we do not usually need the isFull() operations, but the isEmpty() operation is the same as that of the list. The normal way to implement the stack is to add and remove nodes from the head of the list. Note that if we do this, we do not need to use a rear pointer for the list.

Note also that a stack is an efficient data structure as all operations are constant. The array based stack wastes space that the linked list does not.

A Stack Usage Example

Evaluating a Postfix Expression:
You may be asking what a stack is good for, other than reversing a sequence of data items. One common application is to convert an infix expression to postfix. Another is to find the value of a postfix expression. We will not look at the conversion algorithm here, but we will examine the algorithm to evaluate a postfix expression.

First, let's explain the terminology. An infix expression is the type that we are used to in ordinary algebra, such as 3 + 9, which is an expression representing the sum of 3 and 9. Infix expressions place their (binary) operators between the two values to which they apply. In the above example, the addition operator was placed between the 3 and the 9.

A postfix expression, in contrast, places each operator after the two values to which it applies. (Post means "after", right?) The above expression would be 3 9 +, when rewritten in postfix.

Here are a few more examples in the following table. The infix form is shown on the left, and the postfix form is given on the right.

Infix: Postfix:
16 / 2 16 2 /
(2 + 14) * 5 2 14 + 5 *
2 + 14 * 5 2 14 5 * +
(6 - 2) * (5 + 4) 6 2 - 5 4 + *


Note that postfix expressions do not use parentheses for grouping; it is not needed! Infix sometimes requires parentheses to force a certain order of evaluation. For example, in the second example above, parentheses were needed to indicate that the addition should be done before the multiplication. Without the parentheses you get the third example, where the multiplication is done before the addition (using the precedence rules from ordinary arithmetic, or from C++, for that matter).

Arithmetic expressions like the above can of course be much longer. We could also allow other operators, such as ^ for exponentiation, or perhaps a unary minus. A sample infix expression that uses exponentiation is 4 ^ 2, which means 4 to the second power. A unary minus is sometimes used as in the infix expression -(4 + 2). A unary operator is one that is applied to a single value, as opposed to the typical binary operators, which are applied to two values. We will not consider unary operators or exponentiation further here.

The algorithm to evaluate a postfix expression works like this: Start with an empty stack of floats. Scan the postfix expression from left to right. Whenever you reach a number, push it onto the stack. Whenever you reach an operator (call it Op perhaps), pop two items, say First and Second, and then push the value obtained using Second Op First. When you reach the end of the postfix expression, pop a value from the stack. That value should be the correct answer, and the stack should now be empty. (If the stack is not empty, the expression was not a correct postfix expression.)

Let's look at the postfix expression evaluation algorithm by way of example. Consider the postfix expression 2 14 + 5 * that was mentioned above. We already know from its infix form, (2 + 14) * 5, that the value should be 16 * 5 = 80. The following sequence of pictures depicts the operation of the algorithm on this example. Read through the pictures from left to right.

Personal tools
MediaWiki Appliance - Powered by TurnKey Linux