Vous êtes sur la page 1sur 15

Stacks

• Consider a card game with a discard pile


o Discards always placed on the top of the pile
o Players may retrieve a card only from the top

• A stack is a last-in-first-out (LIFO) data structure


• Adding an item
– Referred to as pushing it onto the stack
• Removing an item
– Referred to as popping it from
the stack

Where do we use stack?

- Many places that require stack. Here are a few.


- Activation records.
 Whenever a function call is happened, a stack is utilized.
- Simple calculators.
 Postfix notation.

Formal definition of Stack:

 A storage,
 Which holds an ordered collection of data items,
 can be accessed at only one end (the top).

 This accessing method is called last-in first-out (LIFO).


 The operations are:
 constructor: constructs an empty stack (usually)
 empty(): check if it is empty
 push(): add an element to the top
 GetTop() : returns the top element
 pop(): remove the top element

1
Selecting Storage Structure

 Using Array
o Let position 0 be top of stack

 Problem … consider pushing and popping


o Requires much shifting

 A better approach is to let position 0 be the bottom of the stack

 Thus our design will include


o An array to hold the stack elements
o An integer variable, such as myTop, to indicate the top of the stack

Implementing Operations

 Constructor
 Compiler will handle allocation of memory
 Empty
 Check if value of myTop == -1
 Push (if myArray not full)
 Increment myTop by 1
 Store value in myArray [myTop]

2
 GetTop
 If stack not empty, return myArray[myTop]
 Pop
 If array not empty, decrement myTop
 Output routine added for testing

Let’s look at Static array implementation of stack.

#include <iostream>
using namespace std;

const int MAX_STACK = 10;


typedef int stackItemType;

class stackClass {
public: //constructors and destructors
stackClass() ; //
constructor
stackClass(const stackClass& S) ; // copy constructor
~stackClass() ; // destructor
// stack operations
bool StackIsEmpty() ; // determine whether stack
is empty
void Push (stackItemType NewItem ) ;
bool Pop () ;
stackItemType stackClass::GetTop();

private:
stackItemType Items[MAX_STACK] ; //array
int Top ;
} ; // end class

stackClass::stackClass(): Top(-1) {} //end constructor


//copy constructor
stackClass::stackClass(const stackClass& S) {
Top = S.Top ;
for (int Index = 0 ; Index <= S.Top; Index++)
Items[Index] = S.Items[Index] ;
} // end copy constructor
//destructor -- no need for static arrays
stackClass::~stackClass() {} // end destructor
//Check if stack is empty
bool stackClass::StackIsEmpty(){
return (Top < 0);
} // end StackIsEmpty
//push item on top of stack
void stackClass::Push(stackItemType NewItem ) {

if (Top < (MAX_STACK -1 )) {


Top++ ;
Items[Top] = NewItem ;

3
} // end if
} //end Push

//Pop -- remove the element from the top of the stack


bool stackClass::Pop( )
{
if (!StackIsEmpty()) {
Top-- ;
return true;
}
else {
cerr << "*** Stack is empty "
<< " -- returning garbage value ***\n" ;
return false;
}
} //end Pop
//Get the top of the stack

stackItemType stackClass::GetTop() {
if (!StackIsEmpty()) // if stack is not empty
return Items[Top] ;
} // end Getstack

void main() {
stackItemType AnItem ;
stackClass S, Back;

for (int i=0; i < 5 ; i++)


S.Push(i) ;
Back = S;
while (!Back.StackIsEmpty()) {
cout << Back.GetTop() << endl;
Back.Pop();
}
}

Linked List Stack


• Another alternative to allowing stacks to grow as needed
• Linked list stack needs only one data member
– Pointer myTop
– Nodes allocated (but not part of stack class)
• Here is the “Node” class definition

class Node{
public:
StackElement data;
Node * next;
//--- Node constructor
Node(StackElement value, Node * link = 0)
/*------------------------------------------------------
Precondition: value is received
Postcondition: A Node has been constructed with value
in its data part and its next part set to link

4
(default 0).
------------------------------------------------------*/
{ data = value; next = link; }
};

• Constructor
– Simply assign null pointer to myTop
• Empty
– Check for myTop == null
• Push
– Insertion at beginning of list
• Top
– Return data to which myTop
points

• Pop
– Delete first node in the
linked list
ptr = myTop;
myTop = myTop->next;
delete ptr;
• Output
– Traverse the list
for (ptr = myTop; ptr != 0; ptr = ptr->next)
out << ptr->data << endl;

• Destructor
– Must traverse list and deallocate nodes
– Note need to keep track of ptr->next before calling delete ptr;

• Copy Constructor
– Traverse linked list,
copying each into
new node
– Attach new node
to copy

• Assignment operator

5
– Similar to copy constructor
– Must first rule out self assignment
– Must destroy list in stack being assigned a new value

//// LStack.h
#include <iostream>
using namespace std;

#ifndef LSTACK
#define LSTACK

typedef int StackElement;

class Stack
{
public:
/***** Function Members *****/
/***** Constructors *****/
Stack();

Stack(const Stack & original); //copy constructor

~Stack();/***** Destructor *****/

Stack & operator= (const Stack & original); //assignment

bool empty() const;

void push(const StackElement & value);

void display(ostream & out) const;//Display values.

StackElement top() const;

void pop(); // Remove the value from the top of the stack

private: /***** Data Members *****/

/*** Node class ***/


class Node
{
public:
StackElement data;
Node * next;
//--- Node constructor
Node(StackElement value, Node * link = 0)
/*------------------------------------------------------
Precondition: value is received
Postcondition: A Node has been constructed with value
in its data part and itb next part set to link
(default 0).
------------------------------------------------------*/
{ data = value; next = link; }

6
};

typedef Node * NodePointer;

/***** Data Members *****/


NodePointer myTop; // pointer to top of stack

}; // end of class declaration 

//--- LStack.cpp -------------------------------------------------

#include <iostream>
#include <new>
using namespace std;

#include "LStack.h"

//--- Definition of Stack constructor


Stack::Stack() : myTop(0) {}

//--- Definition of Stack copy constructor


Stack::Stack(const Stack & original)
{
myTop = 0;
if (!original.empty())
{
// Copy first node
myTop = new Stack::Node(original.top());

// Set pointers to run through the stack's linked lists


Stack::NodePointer lastPtr = myTop,
origPtr = original.myTop->next;

while (origPtr != 0)
{
lastPtr->next = new Stack::Node(origPtr->data);
lastPtr = lastPtr->next;
origPtr = origPtr->next;
}
}
}

//--- Definition of Stack destructor


Stack::~Stack()
{
// Set pointers to run through the stack
Stack::NodePointer currPtr = myTop, // node to be deallocated
nextPtr; // its successor
while (currPtr != 0)
{
nextPtr = currPtr->next;

7
delete currPtr;
currPtr = nextPtr;
}
}

//--- Definition of assignment operator


Stack & Stack::operator=(const Stack & original)
{
myTop = 0;
if (original.empty()) return *this;

if (this != &original) // check that not st = st


{
this->~Stack(); // destroy current linked list

// Copy first node


myTop = new Stack::Node(original.top());

// Set pointers to run through the stacks' linked lists


Stack::NodePointer lastPtr = myTop,
origPtr = original.myTop->next;

while (origPtr != 0)
{
lastPtr->next = new Stack::Node(origPtr->data);
lastPtr = lastPtr->next;
origPtr = origPtr->next;
}
}
return *this;
}

//--- Definition of empty()


bool Stack::empty() const
{
return (myTop == 0);
}

//--- Definition of push()


void Stack::push(const StackElement & value)
{
myTop = new Stack::Node(value, myTop);
}

//--- Definition of display()


void Stack::display(ostream & out) const
{
Stack::NodePointer ptr;
for (ptr = myTop; ptr != 0; ptr = ptr->next)
out << ptr->data << endl;
}

//--- Definition of top()


StackElement Stack::top() const
{
if (!empty())

8
return (myTop->data);
else
{
cerr << "*** Stack is empty "
" -- returning garbage ***\n";
return *(new StackElement); // "Garbage" value
}
}

//--- Definition of pop()


void Stack::pop()
{
if (!empty())
{
Stack::NodePointer ptr = myTop;
myTop = myTop->next;
delete ptr;
}
else
cerr << "*** Stack is empty -- can't remove a value ***\n";
}

// definition of print function


void print(Stack st)
{ st.display(cout); }

int main()
{
Stack s;
cout << "Stack created. Empty? " << boolalpha << s.empty() << endl;

cout << "How many elements to add to the stack? ";


int numItems, val;
cin >> numItems;
for (int i = 1; i <= numItems; i++) {
cout << "Enter value: ";
cin>> val;
cout << endl;
s.push(val);
}

cout << "\n Contents of stack s \n";


print(s);
cout << endl;

Stack t, u;
t = u = s;
cout << "Copying contents of stacks to stack t and u after t = u = s:\n";
cout << "u:\n"; print(u); cout << endl;
cout << "t:\n"; print(t); cout << endl;

cout << "Top value in t: " << t.top() << endl;

9
while (!t.empty())
{
cout << "Popping t: " << t.top() << endl;
t.pop();
}
cout << "Stack t empty? " << t.empty() << endl;
cout << "\nNow try to retrieve top value from t." << endl;
cout << "Top value in t: " << t.top() << endl;
cout << "\nTrying to pop t: " << endl;
t.pop();
}

OUTPUT:

Stack created. Empty? true


How many elements to add to the stack? 3
Enter value: 3

Enter value: 1

Enter value: 5

Contents of stack s
5
1
3

Copying contents of stacks to stack t and u after t = u =


u:
5
1
3

t:
5
1
3

Top value in t: 5
Popping t: 5
Popping t: 1
Popping t: 3
Stack t empty? true

Now try to retrieve top value from t.


*** Stack is empty -- returning garbage ***
Top value in t: -842150451

Trying to pop t:
*** Stack is empty -- can't remove a value ***
Press any key to continue

10
Applications of Stack

• Consider events when a function begins execution


• Activation record (or stack frame) is created
• Stores the current environment for that function.

• Contents

Run Time Stack

• Functions may call other functions


– interrupt their own execution
• Must store the activation records to be recovered
– system then reset when first function resumes execution
• This algorithm must have LIFO behavior
• Structure used is the run-time stack

Use of Run Time Stack


• When a function is called …
• Copy of activation record pushed onto run-time stack
• Arguments copied into parameter spaces
• Control transferred to starting address of body of function

• When function terminates

11
• Run-time stack popped
• Removes activation record of terminated function
• exposes activation record of previously executing function
• Activation record used to restore environment of interrupted function
• Interrupted function resumes execution

Application of Stacks
Consider the arithmetic statement in the assignment statement:
x=a*b+c
Compiler must generate
machine instructions
1. LOAD a
2. MULT b
3. ADD c
4. STORE x

Postfix Notation
• Most compilers convert an expression in infix notation to postfix
– the operators are written after the operands
• So a * b + c becomes a b * c +
• Advantage:
– expressions can be written without parentheses

INFIX POSTFIX PREFIX

A+B AB+ +AB


A*B+C AB*C+ +*ABC
A * (B + C) ABC+* *A+BC
A - (B - (C - D)) ABCD---- -A–B–CD
A-B-C–D AB -C-D - ---ABCD
((A+B)*C)-(D/E)) -*+ABC/DE AB+C*DE/-
(A*B+C*D) – (A/B –(D+E)) ? ?

12
Evaluating a Postfix notation
By hand" (Underlining technique):
1. Scan the expression from left to right to find an operator.
2. Locate ("underline") the last two preceding operands
and combine them using this operator.
3. Repeat until the end of the expression is reached.

Example:
234+56--*
234+56--*
2756--*
2756--*
 2 7 -1 - *
 2 7 -1 - *
 28*
 16

By using a stack algorithm

1. Initialize an empty stack


2. Repeat the following until the end of the expression is encountered
a) Get the next token (const, var, operator) in the expression
b) Operand – push onto stack
Operator – do the following
i. Pop 2 values from stack
ii. Apply operator to the two values
iii. Push resulting value back onto stack
3. When end of expression encountered, value of expression is the (only) number
left in stack
Evaluation of Postfix notation

13
How do we convert Infix to Postfix

INFIX TO POSTFIX CONVERSION ALGORITHM:


Initially String is CR and PE = “” (NULL STRING, empty)
1- If CR[I] is an operand, append it to the string PE
2- If CR[I] is ‘(‘ , push it onto stack
3- If CR[I] is ‘)’, pop operators from stack, until a ‘(‘ is encountered
4- I) If CR[I] is an operator, pop operators which has >= precedence and append them to
PE until a) if the popped element is ‘(‘
or b) if the popped operator has lower precedence than CR[I]

14
or c) stack is empty
II) Push the operator seen (CR[I]) onto stack Top
5- If end of CR is reached, pop the elements out of the stack.

Example:

CR = A- (B+ C* D)/E
CR A - C B + ( * D ) / E
S [] - -( -( -(+ -(+ -(+* -(+* - -/ -
PE A A A AB AB ABC ABC ABCD ABCD*+ ABCD*+/ ABCD*+/-

Assignment:

convert infix to postfix.

15

Vous aimerez peut-être aussi