7.12.2. Dynamic Stack Implementation

Time: 00:09:06 | Download: Large Small | Streaming
Review

The following example implements a stack as a structure with an array field. Unlike the previous automatic structure version, the dynamic version allocates the array dynamically on the heap with the new operator. Surprisingly, the change requires few modifications to the previous version. The driver in both versions creates a stack structure object as an automatic variable. However, in the dynamic version, the data array is a pointer rather than an array, allowing the client program to specify the stack's size when creating it.

Header File

struct dstack
{
	char*	st;
	int	sp;
	int	max;
};

dstack	make_stack(int size);
void	init_stack(dstack* s, int size);
void	push(dstack* s, char data);
char	pop(dstack* s);
int	size(dstack* s);
char	peek(dstack* s);
void	cleanup(dstack* s);
dstack.h (dynamic structure version). Converting the automatic to the dynamic version requires four significant changes:
  1. A pointer replaces the stack array (blue), allowing the user to specify the stack's size when creating the array.
  2. A structure field, max, replaces the symbolic constant SIZE (pink), allowing the stack object to "remember" its maximum size so the push function can detect and prevent a stack overflow (the if-statement).
  3. The client program passes the stack's size to make_stack and init_stack through an added argument called size (green).
  4. The dynamic version must provide a new function, named cleanup (yellow), to delete the dynamically allocated array, and the user must remember to call that function. (Object-oriented programming solves these problems more elegantly with a function called a destructor, which we explore in Chapter 9.)

Stack Functions

Construction Typical Operations Optional Operations Destruction
dstack make_stack(int size)
{
    dstack	temp;
    temp.st = new char[size];
    temp.sp = 0;
    temp.max = size;

    return temp;
}

void init_stack(dstack* s, int size)
{
    s->st = new char[size];
    s->sp = 0;
    s->max = size;
}
void push(dstack* s, char data)
{
    if (s->sp < s->max)
        s->st[s->sp++] = data;
    else
        throw "Stack Overflow";
}

char pop(dstack* s)
{
    if (s->sp > 0)
        return s->st[--(s->sp)];
    else
        throw "Stack Underflow";
}
 
int size(dstack* s)
{
    return s->sp;
}

char peek(dstack* s)
{
    return s->st[s->sp - 1];
}
 
 
 
 
 
 
 
void cleanup(dstack* s)
{
    delete s->st;
}
 
 
 
 
 
 
 
 
 
 
 
 
dstack.cpp (dynamic structure version). The dynamic structure version organizes the seven stack functions into four functional groups. Changes from the previous stack example are noted:
make_stack and init_stack
Adds a size parameter, dynamically allocates the stack array with new, sets max, the maximum size of the stack, to size, and sets the stack pointer, sp, to 0
push
Replaces the SIZE constant with the max structure field in the if-statement
pop, size, and peek
Unchanged
cleanup
Added; deletes the heap memory allocated with new

The Driver / Test Program

#include <iostream>
#include "dstack.h"
using namespace std;

int main()
{
	//dstack s = make_stack(10);
	dstack	s;
	init_stack(&s, 10)

	push(&s, 'x');
	push(&s, 'y');
	push(&s, 'z');

	char c = peek(&s);
	cout << c << endl;

	c = pop(&s);
	cout << c << endl;

	while (size(&s) > 0)
		cout << pop(&s) << endl;
	
	cleanup(&s);

	return 0;
}
dtest.cpp (dynamic structure version). The driver demonstrates the operations of a simple stack client. The highlighted statements illustrate two methods for making a stack. The first method, a call to the make_stack function, is inauthentic but consistent with the previous Time structure examples. The init_stack function is more authentic and sets the stage for a Stack Class implementation in Chapter 9.

Downloadable Code

Formatted with tab stops set at 8 spaces.

ViewDownload
dstack.h dstack.h
dstack.cpp dstack.cpp
dtest.cpp dtest.cpp