Stacks1 Stacks The unorganized person’s data structure.

34
stacks 1 Stacks Stacks The unorganized person’s data structure

Transcript of Stacks1 Stacks The unorganized person’s data structure.

stacks 1

StacksStacks

The unorganized person’s data structure

stacks 2

Stack characteristicsStack characteristics

• Entries are ordered in terms of access -- both insertion and removal take place at same spot (top of stack)

• Specialized type of container class; defining characteristic is insertion/removal order

• LIFO = last in, first out; entries are removed in reverse order of insertion

stacks 3

Stack operationsStack operations

• Push -- insert item on stack

• Pop -- remove item from stack

• Peek -- examine, but don’t remove item

stacks 4

Stack operationsStack operations

• Important to know if stack is empty -- attempt to remove an item from an empty stack is an underflowunderflow error

• Depending on implementation, may be necessary to check if stack is full -- attempt to add item to a full stack is an overflowoverflow error

stacks 5

Implementation of Stack ADTImplementation of Stack ADT

• Stacks can be array based (static or dynamic) or linked list based

• Invariant for static array implementation:– The number of items stored in the stack is

found in member variable used– Items are stored in member variable data, a

static array with the stack bottom at data[0] and the stack top at data[used - 1]

stacks 6

Stack class -- static array versionStack class -- static array versiontemplate <class Item>

class Stack

{

public:

enum {CAPACITY = 64};

Stack ( ); // default constructor

Item pop ( ); // removes top Item

Item peek ( ) const; // reveals top Item

. . .

stacks 7

Stack ADT continuedStack ADT continued

void push (const Item & entry); // adds Item to stack

size_t size ( ) const {return used;}

bool is_empty ( ) const {return used == 0;}

private:

Item data[CAPACITY]; // the stack itself

size_t used; // # of items stored in stack

};

stacks 8

Stack function implementations: Stack function implementations: constructorconstructor

// Postcondition: empty stack is created

template <class Item>

Stack<Item>::Stack( )

{

used = 0;

}

stacks 9

Pop functionPop function// Precondition: stack is not empty

// Postcondition: top item is removed

template <class Item>

Item Stack<Item>::pop ( )

{

assert (!is_empty( ));

used--;

return data[used];

}

stacks 10

Peek functionPeek function

// Precondition: stack is not empty

// Postcondition: top item is revealed

template <class Item>

Item Stack<Item>::peek ( ) const

{

assert (!is_empty( ));

return data[used - 1];

}

stacks 11

Push functionPush function

// Precondition: stack is not full

// Postcondition: an item is inserted on stack

template <class Item>

void Stack<Item>::push(const Item& entry)

{

assert (size() < CAPACITY);

data[used] = entry;

used++;

}

stacks 12

Stack application examplesStack application examples

• Compilers use stacks for a variety of purposes:– syntax analysis: matching brackets,

parentheses, etc.– activation records: structures associated with

functions, keeping track of local variables, return address, etc.

stacks 13

Example application: balanced Example application: balanced parenthesesparentheses

• Pseudocode algorithm:– scan string left to right– if ‘(‘ is encountered, push on stack– if ‘)’ is encountered, and stack is not empty,

pop one ‘(‘ -- if stack is empty, expression is unbalanced

– if stack is empty when entire string has been scanned and analyzed, expression is balanced

stacks 14

A program to test for balanced A program to test for balanced parenthesesparentheses

int main( ){ String user_input; // uses String data type defined in ch. 4 - based on array

cout << "Type a string with some parentheses and no white space:\n"; cin >> user_input;

if (balanced_parentheses(user_input)) cout << "Those parentheses are balanced.\n"; else cout << "Those parentheses are not balanced.\n";

cout << "That ends this balancing act.\n"; return EXIT_SUCCESS;}

stacks 15

balanced_parentheses functionbalanced_parentheses function

bool balanced_parentheses(const String& expression)// Library facilities used: assert.h, stack1.h, stdlib.h, mystring.h.{ // Meaningful names for constants const char LEFT_PARENTHESIS = '('; const char RIGHT_PARENTHESIS = ')';

Stack<char> store; // Stack to store the left parentheses as they occur size_t i; // An index into the String char next; // The next character from the String char discard; // A char popped off the stack and thrown away bool failed = false; // Becomes true if a needed parenthesis is not found. . .

stacks 16

balanced_parentheses continuedbalanced_parentheses continuedfor (i = 0; !failed && (i < expression.length( )); i++) { next = expression[i]; if (next == LEFT_PARENTHESIS) { if (store.size( ) < store.CAPACITY); store.push(next); } else if ((next == RIGHT_PARENTHESIS) && (!store.is_empty( ))) discard = store.pop( ); else if ((next == RIGHT_PARENTHESIS) && (store.is_empty( ))) failed = true; }

return (store.is_empty( ) && !failed);}

stacks 17

Stack ADT as linked listStack ADT as linked list

• Can make use of toolkit functions to simplify task

• Stack can grow & shrink as needed to accommodate data -- no fixed size

• Invariant:– stack items are stored in a linked list– member variable top is head pointer to list

stacks 18

Class definition for new StackClass definition for new Stack

template <class Item>

class Stack

{

public:

Stack( ) { top = NULL; }

Stack(const Stack& source);

~Stack( ) { list_clear(top); }

...

stacks 19

Stack definition continuedStack definition continued

void push(const Item& entry);

Item pop( );

void operator =(const Stack& source);

size_t size( ) const {return list_length(top);}

bool is_empty( ) const {return top == NULL;}

Item peek( ) const;

private:

Node<Item> *top; // Points to top of stack

};

stacks 20

Push functionPush function

template <class Item>

void Stack<Item>::push(const Item& entry)

{

list_head_insert(top, entry);

}

stacks 21

Pop functionPop function

template <class Item>

Item Stack<Item>::pop( )

{

assert(!is_empty( ));

Item answer = top->data;

list_head_remove(top);

return answer;

}

stacks 22

Peek functionPeek function

template <class Item>

Item Stack<Item>::peek( ) const

{

assert(!is_empty( ));

return top->data;

}

stacks 23

Copy constructorCopy constructor

template <class Item>

Stack<Item>::Stack(const Stack<Item>& source)

{

list_copy(source.top, top);

}

stacks 24

Assignment operatorAssignment operatortemplate <class Item>

void Stack<Item>::operator =(const Stack<Item>& source)

{

if (source.top== top) // Handle self-assignment

return;

list_clear(top);

list_copy(source.top, top);

}

stacks 25

A stack-based calculatorA stack-based calculator

• Input to program is a fully-parenthesized expression -- examples:((5.3 * 1.2) / 3.1)

(4 - 3)

• Two stacks are used -- one for operators, one for operands

• Right parenthesis is signal to pop the stacks and evaluate the expression

stacks 26

Algorithm for expression Algorithm for expression evaluationevaluation

• Evaluate leftmost, innermost expression; continue evaluating, left to right– Read each part of expression– Push numbers on operand stack, operators on

operator stack– When right parenthesis is encountered, pop the

stacks, evaluate, and push result on operand stack

stacks 27

Code for stack calculatorCode for stack calculator

int main( )

{

double answer;

cout << "Type a fully parenthesized arithmetic expression:" << endl;

answer = read_and_evaluate(cin);

cout << "That evaluates to " << answer << endl;

return EXIT_SUCCESS;

}

stacks 28

Code for stack calculatorCode for stack calculatordouble read_and_evaluate(istream& ins)

{

const char DECIMAL = '.';

const char RIGHT_PARENTHESIS = ')';

Stack<double> numbers;

Stack<char> operations;

double number;

char symbol;

...

stacks 29

Code for stack calculatorCode for stack calculator

while (!ins.eof( ) && ins.peek( ) != '\n')

{

if (isdigit(ins.peek( )) || (ins.peek( ) == DECIMAL))

{

ins >> number;

numbers.push(number);

} …

stacks 30

Code for stack calculatorCode for stack calculator

else if (strchr("+-*/", ins.peek( )) != NULL)

{

ins >> symbol;

operations.push(symbol);

}

stacks 31

Code for stack calculatorCode for stack calculator

else if (ins.peek( ) == RIGHT_PARENTHESIS)

{

cin.ignore( );

evaluate_stack_tops(numbers, operations);

}

else

cin.ignore( );

} // end of while loop

return numbers.pop( );

}

stacks 32

Code for stack calculatorCode for stack calculator

void evaluate_stack_tops(Stack<double>& numbers, Stack<char>& operations)

{

double operand1, operand2;

operand2 = numbers.pop( );

operand1 = numbers.pop( );

...

stacks 33

Code for stack calculatorCode for stack calculator

switch (operations.pop( ))

{

case '+':

numbers.push(operand1 + operand2);

break;

case '-':

numbers.push(operand1 - operand2);

break;

...

stacks 34

Code for stack calculatorCode for stack calculator

case '*':

numbers.push(operand1 * operand2);

break;

case '/':

numbers.push(operand1 / operand2);

break;

} // end switch statement

} // end function