UMBC CS 201, Fall 06
 UMBC CMSC 201 Fall '06 CSEE | 201 | 201 F'06 | lectures | news | help Search Notes:

The Stack

Implementations using arrays

Initial Implementation

Similar to the queue, we can implement a stack as an array. Again, let us create an array of some size to hold all of the data that think we will ever need to put into it. Let us also maintain the top of the stack in terms of the corresponding indicies.

```
int myStack[5];
int top;
```

Push

To Push, all we need to do is insert at the end of the used portion of the array. In other words insert immediately past the top and then increment top to reflect the new top of the stack.

Initially we have top = -1, as it does not really point to anything in the array, and thus should not have a valid array index.

0 1 2 3 4

So lets push...

```   Push ( myStack, &top, 5 );
```
 5
0 1 2 3 4

Now we have top = 0, as the top of the stack is at myStack[0].

Then after a couple more inserts...

```   Push ( myStack, &top, 1 );
Push ( myStack, &top, 6 );
```
 5 1 6
0 1 2 3 4

Now we have top = 2

Again, what happens is we want to do even more inserts...

```   Push ( myStack, &top, 1 );
Push ( myStack, &top, 9 );
Push ( myStack, &top, 7 );
Push ( myStack, &top, 8 );
```
 5 1 6 1 9
0 1 2 3 4

Again, we run into issues with filling up the array.

Pop

Unlike queues, stacks do not have a problem when removing an element from the array. All we are ever doing popping off what is at the end of the array. Thus we never have any problems with creating gaps in the array.

For example, given the following stack where top = 3, let us see what happens when popping...

 5 1 6 1
0 1 2 3 4

Okay, lets pop...

```   tmp = Pop ( myStack, &top );
```
 5 1 6
0 1 2 3 4

All we had to do was to return the value stored at myStack[top], and decrement top to reflect the new top of the stack, so top = 2. No gaps were ever created.

Problems with this Initial Array Implementation

• Well, we need to know ahead of time how large to make the array - too big and we are wasting memory, too small and we could fill it up.

Array Implementation - as good as it gets

Just like with the queue, we can take it a step further and manually allocate a contiguous chunk of memory ourselves. This will allow us to potentially allocate more memory as needed, thus in essence allowing us to be able to resize the stack. This will require us to keep track of the current size of the array allocated for stack use.

However, unlike the queue, we will never have the case where data wrapped around to the beginning of the array. The top is always to the right and the bottom is always to the left, thus we can copy over directly and simple insert it at the end.

Problems with this "as good as it gets" Implementation

• If we needed to resize when inserting, we would have to copy over all the elements from an old array into a new array.
• Just like the resize-able queue, the choice of how much to increase array by becomes critical. Do we increase it by some constant amount (size += 10), or do we increase it by some percentage (size *= 1.1), or do we double it (size *= 2).

Since we already know about linked lists, we should consider using a linked list implementation for the stack. The stack can be implemented without wasting any space, and by doing pointer manipulation rather than a series of value moves, we can make our stack work much faster than an array implementation could.

Benefits of using a linked list

• We never have to worry about copying over all of the elements, because a linked list is dynamic in size, it can shrink and grow as needed.
• Our memory need not be contiguous anymore.