Personal tools
You are here: Home Classes Fall 2004 - Spring 2005 CS 151 Stacks and Queues
Navigation
Log in


Forgot your password?
« May 2008 »
Su Mo Tu We Th Fr Sa
123
456789 10
11121314151617
18192021222324
25262728293031
 
Document Actions

Stacks and Queues

by admin last modified 2005-05-11 18:12

Stacks and Queues

Stacks and queues are among the most frequently used data structures in computer science.  Both are examples of restricted access containers .  Like lists, they are containers which hold collections of objects.  They are one-dimensional structures.  Unlike lists, however, the access to those objects is limited to the first or last elements only.

Question:  What is the advantage of restricting access?  Why not just use a List?


Applications


Stacks:
  • parsing of context-free languages (compilers)
  • implementation of method call and return at the machine language level (run-time stack)
  • implementation of recursion
  • backtracking algorithms
  • operand stack in the Java Virtual Machine

Queues:
  • simulation
  • event-driven programs
  • operating systems

Note:  java.util contains a Stack class but not a Queue class.

Some queue references

Interfaces

Access to a stack is on a last in, first out basis.  This is accomplished by allowing insertions and deletions to be performed only at one end of the stack..  Access to a queue is on a first in, first out basis.   This is accomplished by allowing insertions only at one end of the queue and deletions only at the other end of the queue.  A deque (doubly-ended queue) is a generalization which allows both insertions and deletions to be performed at either end of the deque.


Stack interface

boolean isEmpty();  
void push(Object obj);  //  insert an object into the stack.  Items are pushed onto the "top" of the stack.
Object pop();  //  remove an item from the stack.  The item which is removed is the one on the top of the stack.
Object top();  //  returns the top element from the stack without removing it.

Queue interface

boolean isEmpty();
void enqueue(Object obj);  //  insert an object into the queue.  Items are added to the rear of the queue.
Object dequeue();  //  remove an object from the queue.  Items are removed from the front of the queue.


example  Write a method which counts the number of elements in a given stack.

int count(Stack s);

example  Write a method which creates a copy of a given stack.

Stack copy(Stack s);


Stack Implementation


A stack can be implemented using either a linked list or an array.  In fact, it can be implemented with any version of the List interface.  However, it may be more efficient to implement it directly.

We'll look at a few different versions:

1.  Using a generic SimpleList.

Question:  We can choose to use either the beginning or end of the list to perform push and pop operations.  Which is the better choice?  Does it matter?

version 1:  push and pop at the end of the list

void push(Object obj)
{
    add(obj);
}

Object pop()
{
    return remove(size()-1);
}

Object top()
{
    return get(size()-1);
}


version 2:  push and pop at the beginning of the list

void push(Object obj)
{
    add(0,obj);
}

Object pop()
{
    return remove(0);
}

Object top()
{
    return get(0);
}


2.  Using the low-level methods of the RecursiveList.

void push(Object obj)
{
    prepend(obj);
}

Object pop()
{
    return removeFirst();
}

Object top()
{
    return getFirst();
}


3.  Using an array.


4.  Use a linked list.

Queue Implementation

A queue can also be implemented using either a linked list or an array.  We'll consider several implementations:


1.  Using a LinkedList with head and tail pointers.

Enqueueing can be done at the tail and dequeueing at the head, both in time O(1).  If enqueuing is done at the head and dequeuing at the tail, the dequeuing time becomes O(n).

If a doubly-linked list is used, access to both head and tail are O(1), so both enqueue and dequeue will have time O(1).


2.  Using a recursively-defined linked list.

A recursively-defined list has a first and a rest.  This gives immediate access to the first element, but not the last.  If it is used to implement a queue, one could  let the first element be the front of the queue or the rear of the queue.  If the first element is the front, then dequeue is O(1), but enqueue is O(n).  On the other hand, if the first element is the rear, then enqueue is O(1), but dequeue is O(n).

Conclusion:  A recursively-defined linked list is probably not a good choice for a queue implementation.


3.  Using an array.

The traditional way of using an array to implement a queue is called a circular queue.  Two array indices are maintained:  one to the front element of the queue and the other to the rear element.  As items are enqueued, the rear index is incremented; as items are dequeued, the front index is incremented.  When the rear index reaches the end of the array, it "wraps around" to slot 0 and continues.  Both enqueue and dequeue are O(1) (not considering resize operations).







 

Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: