STACKS
A stack is a data structure in which elements are added and removed from only one end. At the logical level a stack is an ordered group of elements. The removal of elements from the stack and the addition of elements to it can take place only at the top of the stack. (ex. a stack of cafeteria trays).
A stack is an ordinal structure because at any time, given any two elements in the stack, one is closer to the top. In addition, a stack is a dynamic data structure because the elements in the stack, as well as the size of the stack, may constantly change.
Because elements are added and removed from the top of the stack, the last element added is the first to be removed. This is why the stack is generally known as a LIFO structure -- last in, first out.

STACK OPERATIONS
There is a group of basic stack operations with which the programmer should be familiar:
Pushing and popping are the major operations involving stacks.
Example -- you are writing a program designed to read in a string of characters followed by a period followed by the same string of characters in reverse order. Your program is to determine if the reversals are correct.
i.e. ABCD.DCBA returns TRUE
ABCD.ABCD returns FALSE
The code is shown below. Notice that in function reversedString the calls to the stack implementation routines are made but the routines are not included. This is an example of information hiding.
' Returns TRUE if the character string preceding the period ' is the reverse of the string following the period; FALSE ' otherwise. It assumes the presence of a period in the ' input and the same number of letters preceding and ' following the period. Private Function reversedString (ByVal str As String) As Boolean Dim stack As clsStack Dim matching As Boolean Dim noPeriodFound As Boolean Dim ctr As Integer Dim ch1 As String, ch2 As String Call stack.clearStack( ) ' set stack to empty ' Extract and Push all characters up to the period. noPeriodFound = True While noPeriodFound ctr = ctr + 1 ch1 = Mid(str, ctr, 1) If (ch1 = ".") Then noPeriodFound = False Else Call stack.push(ch1) End If Wend ' Read rest of string and compare characters to those in the stack matching = True While Not stack.emptyStack( ) And matching ctr = ctr + 1 ch1 = Mid(str, ctr, 1) ch2 = stack.pop( ) If (ch1 <> ch2) Then matching = False Wend reversedString = matching End Function |
IMPLEMENTATION
The programming language does not provide PUSH and POP, so the programmer must write them.
A stack can be implemented in a variety of ways. Stacks and queues can vary greatly in size during run time, and thus are best implemented as dynamic linked lists. The implementation should not affect the code in the higher levels of the program. Only low-level routines like PUSH and POP, and the declarations for the data structure will need to be modified.
Declarations
A stack can be represented as a linked list with an external pointer that points to the top of the stack. The class specification appears below. Note that in this example the nextNode instance variable is declared as Private, and get and set property methods are provided.
'--------------------------------------------------------------------- ' linkNode class '--------------------------------------------------------------------- ' instance variables Private info As Variant Private nextNode As linkNode ' class methods '--------------------------------------------------------------------- ' Constructor '--------------------------------------------------------------------- Private Sub Class_Initialize( ) Set nextNode = Nothing End Sub '--------------------------------------------------------------------- ' Set node value '--------------------------------------------------------------------- Public Sub setInfo(ByVal newValue As Variant) info = newValue End Sub '--------------------------------------------------------------------- ' Return node value '--------------------------------------------------------------------- Public Function getInfo( ) As Variant getInfo = info End Function '--------------------------------------------------------------------- ' Reset nextNode reference '--------------------------------------------------------------------- Public Sub setNextNode(ByRef followingNode As linkNode) Set nextNode = followingNode End Sub '--------------------------------------------------------------------- ' Return nextNode reference '--------------------------------------------------------------------- Public Function getNextNode( ) As linkNode Set getNextNode = nextNode End Function |
'--------------------------------------------------------------------- ' Class clsStack '--------------------------------------------------------------------- Private stack As linkNode '--------------------------------------------------------------------- ' Initializes the stack to empty. '--------------------------------------------------------------------- Public Sub clearStack( ) Set stack = Nothing End Sub '--------------------------------------------------------------------- ' Returns true if the stack is empty, false otherwise. '--------------------------------------------------------------------- Public Function emptyStack( ) As Boolean emptyStack = (stack Is Nothing) End Function '--------------------------------------------------------------------- 'Inserts node P at the top of the stack. '--------------------------------------------------------------------- Public Sub push(ByVal newValue As Variant) Dim newNode As New linkNode Call newNode.setInfo(newValue) Call newNode.setNextNode(stack) Set stack = newNode End Sub '--------------------------------------------------------------------- ' Removes the first element from the stack '--------------------------------------------------------------------- Public Function pop( ) As Variant Dim nodePtr As linkNode If emptyStack( ) Then MsgBox "Stack empty -- no item to pop.", vbOKCancel + _ vbExclamation + vbApplicationModal, "Pop Alert" Else Set nodePtr = stack Set stack = stack.getNextNode( ) pop = nodePtr.getInfo( ) Call nodePtr.setNextNode(Nothing) Set nodePtr = Nothing End If End Sub '--------------------------------------------------------------------- ' Cycle through a stack, counting each node '--------------------------------------------------------------------- Public Function stackSize( ) As Integer Dim ctr As Integer Dim Ptr As linkNode Set Ptr = stack ctr = 0 If Not emptyStack( ) Then While Not Ptr Is Nothing ctr = ctr + 1 Set Ptr = Ptr.getNextNode ( ) Wend End If stackSize = ctr End Function '--------------------------------------------------------------------- ' Returns the value of the top node in a stack '--------------------------------------------------------------------- Public Function stackTop( ) As Variant If Not emptyStack( ) Then stackTop = stack.getInfo( ) End Function |
Stack Operations
clearStack:
Clearing the stack is accomplished by setting stack, the external pointer to the stack, to Nothing. It doesn't matter if the stack contains several nodes, because once the external pointer is removed the reference count of the first cell becomes 0 and the garbage collector recovers the node, in the process eliminating the only external pointer to the second item, etc.
'--------------------------------------------------------------------- ' Initializes the stack to empty. '--------------------------------------------------------------------- Public Sub clearStack( ) Set stack = Nothing End Sub |
emptyStack:
Testing for an empty stack can be done by checking to see if the external pointer, stack, is equal to
Nothing.
'--------------------------------------------------------------------- ' Returns true if the stack is empty, false otherwise. '--------------------------------------------------------------------- Public Function emptyStack( ) As Boolean emptyStack = (stack Is Nothing) End Function |
PUSH
To add, or push, an element onto a stack, the routine must create a new stack node, set its next pointer to stack, and then move the stack pointer to the new node.
'--------------------------------------------------------------------- 'Inserts node P at the top of the stack. '--------------------------------------------------------------------- Public Sub push(ByVal newValue As Variant) Dim newNode As New linkNode Call newNode.setInfo(newValue) Call newNode.setNextNode(stack) Set stack = newNode End Sub |
Note the similarity between this Push routine and the pushNode method in the Linked
List notes.
Dim newNode As New linkNode
Call newNode.setInfo(newValue)

Call newNode.setNextNode(stack)

Set stack = newNode

POP
An item is popped off a stack by setting a pointer to the node referenced by stack, shifting stack to the next element, and returning the first element.
'--------------------------------------------------------------------- ' Removes the first element from the stack '--------------------------------------------------------------------- Public Sub pop(ByRef poppedItem As Variant) Dim nodePtr As linkNode If emptyStack( ) Then MsgBox "Stack empty -- no item to pop.", vbOKCancel + _ vbExclamation + vbApplicationModal, "Pop Alert" Else Set nodePtr = stack Set stack = stack.getNextNode( ) poppedItem = nodePtr.getInfo( ) Call nodePtr.setNextNode(Nothing) Set nodePtr = Nothing End If End Sub |
Set nodePtr = stack

Set stack = stack.getNextNode( )

poppedItem = nodePtr.getInfo( )
Call nodePtr.setNextNode(Nothing)

Set nodePtr = Nothing

<garbage collection>

stackSize determines the number of items in the stack.
'--------------------------------------------------------------------- ' Cycle through a stack, counting each node '--------------------------------------------------------------------- Public Function stackSize( ) As Integer Dim ctr As Integer Dim Ptr As linkNode Set Ptr = stack ctr = 0 If Not emptyStack() Then While Not Ptr.nextNode Is Nothing ctr = ctr + 1 Set Ptr = Ptr.nextNode Wend End If stackSize = ctr End Function |
stackTop returns the
value of the top node in the stack.
'--------------------------------------------------------------------- ' Returns the value of the top node in a stack '--------------------------------------------------------------------- Public Function stackTop( ) As Variant If Not emptyStack( ) Then stackTop = stack.getInfo( ) End Function |
What good is a stack? A stack is an appropriate data structure when information must be saved and then later retrieved in reverse order. A situation that requires the program to backtrack to some earlier position may be a good occasion to use a stack.
Okay, but when might such a situation arise? Maybe when solving a maze, but what practical use is that? It sounds like stacks will only be of use in a contrived situation.
However....
When a program gets to the end of a procedure or function how does it know when to continue? Many systems use a stack to keep track of the return addresses, parameter values or addresses and other information used by subprograms. For instance, when Procedure A is called its calling information is pushed onto the
run-time stack. Then, when Procedure B is called from A, B's calling information is pushed onto the top of the stack. B then calls Procedure
C, and C's calling information is pushed onto the stack. When C finishes executing, the stack is popped to retrieve the information needed to return to Procedure B. Then B finishes executing and its return address and so forth is popped from the stack. Finally Procedure A completes and the stack is popped again to get back to the main program.
Test Module
'--------------------------------------------------------------------- ' Primary Procedure '--------------------------------------------------------------------- Private Sub Form_Load( ) Dim stack As New clsStack Dim p As Variant Debug.Print "*=================*" Call stack.push("A") Debug.Print "Element = " & stack.stackTop( ) Call stack.push(14) Debug.Print "Element = " & stack.stackTop( ) Call stack.push(10) Debug.Print "Element = " & stack.stackTop( ) Debug.Print "Size = " & stack.stackSize( ) p = stack.pop( ) Debug.Print "Element = " & stack.stackTop( ) Debug.Print "Size = " & stack.stackSize( ) Call stack.clearStack( ) Debug.Print "Element = " & stack.stackTop( ) Debug.Print "Size = " & stack.stackSize( ) End Sub |