Linked Stacks and Queues

We can go back and revisit our implementations of stacks and queues using linked lists. We first need to define a structure for the linked list.

struct NodeType {
    Item_type item;
    struct NodeType *pNext;
};

Also need the beginning of the list. Typically we use a header variable to point to the head of the list.

NodeType *pNodeHead;

To keep our Stack and Queue abstractions, we will put them as fields to these two structures.

Note that the variable must be initialized to NULL indicating that the list contains no members.

Look at following stackll.C code and work through the reverseread example. Can just replace stack.C code and recompile (also change definitions in header file stack.h.

Note the use of MakeNode() to explicitly make a node in the linked list. It is a private member function.

/* /cs/cs2005/pub/example/stackll.h -- header file for linked list stack */

#define MAXSTACK 10

typedef char Item_type;

typedef short Boolean;

struct NodeType {
    Item_type item;
    struct NodeType *pNodeNext;
};

class Stack {
  private:
    NodeType *pNodeHead;
    NodeType *MakeNode(Item_type item);
  public:
    Stack();
    Boolean EmptyStack();
    Boolean FullStack();
    int Push(Item_type item);
    int Pop(Item_type &item);
};

/*
 * /cs/cs2005/pub/example/stackll.C -- stack routines in C++
 */

#include <iostream.h>
#include "stackll.h"

/*
 * MakeNode - make a new node, return NULL on error, ptr to node on success.
 */
NodeType *Stack::MakeNode(Item_type item)
{
    NodeType *pNode;

    pNode = new NodeType;
    if (pNode != NULL) {
        pNode->item = item;
        pNode->pNodeNext = NULL;
    }
    return(pNode);
}

/*
 * Stack - initialize the stack
 */
Stack::Stack()
{
    pNodeHead = NULL;
}

/*
 * Push - push an item on the stack, return zero for success, -1 on error.
 */
int Stack::Push(Item_type item)
{
    NodeType *pNode;

    if ((pNode = MakeNode(item)) == NULL)
        return(-1);
    else {
        pNode->pNodeNext = pNodeHead;
        pNodeHead = pNode;
        return(0);
    }
}

/*
 * Pop - pop an item off the stack, return zero for success, -1 on error.
 */
int Stack::Pop(Item_type &item)
{
    NodeType *pNode;

    if (pNodeHead == NULL)
        return(-1);
    else {
        item = pNodeHead->item;
        pNode = pNodeHead;        /* save node pointer */
        pNodeHead = pNodeHead->pNodeNext;
        delete pNode;
        return(0);
    }
}

/*
 * Full - is the stack full (not really needed)
 */
Boolean Stack::FullStack()
{
    return(0);                        /* never full */
}

/*
 * Empty - is the stack empty?
 */
Boolean Stack::EmptyStack()
{
    return(pNodeHead == NULL);
}

Queues

With a linked list we no longer have to worry about a circular queue. Can avoid having to keep a count. However, just like we used two indices front and rear, we need two pointers pNodeFront and pNodeRear.

Otherwise code is similar to stack linked list implementation. With two pointers we must watch when making the transition from zero to one queue elements and one to zero queue elements.

We can recompile the reread.C code with these routines.

/* /cs/cs2005/pub/example/queuell.h -- header file for linked list queue */

#define MAXQUEUE 10

typedef char Item_type;

typedef short Boolean;

struct NodeType {
    Item_type item;
    struct NodeType *pNodeNext;
};

class Queue {
  private:
    NodeType *pNodeFront;      // front of the queue list
    NodeType *pNodeRear;       // rear of the queue list 
    NodeType *MakeNode(Item_type item);
  public:
    Queue();
    Boolean EmptyQueue();
    Boolean FullQueue();
    int AddQueue(Item_type);       /* enqueue */
    int DeleteQueue(Item_type &);  /* dequeue */
};

/*
 * /cs/cs2005/pub/example/queuell.C -- queue routines
 *
 */

#include <iostream.h>
#include "queuell.h"

/*
 * MakeNode - make a new node, return NULL on error, ptr to node on success.
 */
NodeType *Queue::MakeNode(Item_type item)
{
    NodeType *pNode;

    pNode = new NodeType;
    if (pNode != NULL) {
        pNode->item = item;
        pNode->pNodeNext = NULL;
    }
    return(pNode);
}

/*
 * Queue - initialize the queue
 */
Queue::Queue()
{
    pNodeFront = pNodeRear = NULL;
}

/*
 * AddQueue - add an item to the queue, return zero for success, -1 on error.
 */
int Queue::AddQueue(Item_type item)
{
    NodeType *pNode;

    if ((pNode = MakeNode(item)) == NULL)
        return(-1);
    else {
        if (pNodeFront == NULL) {
            /* first node in the list */
            pNodeFront = pNode;
            pNodeRear = pNode;
        }
        else {
            /* existing nodes in the list, add to rear */
            pNodeRear->pNodeNext = pNode;
            pNodeRear = pNode;
        }
        return(0);
    }
}

/*
 * DeleteQueue - delete an item from the queue, return zero for success, -1 on error.
 */
int Queue::DeleteQueue(Item_type &item)
{
    NodeType *pNode;

    if (pNodeFront == NULL)
        return(-1);
    else {
        item = pNodeFront->item;
        pNode = pNodeFront;
        pNodeFront = pNodeFront->pNodeNext;
        if (pNodeFront == NULL)
            pNodeRear = NULL;
        delete pNode;
        return(0);
    }
}

/*
 * FullQueue - is the queue full?
 */
Boolean Queue::FullQueue()
{
    return(0);                        /* never full */
}

/*
 * EmptyQueue - is the queue empty?
 */
Boolean Queue::EmptyQueue()
{
    return(pNodeFront == NULL);
}