3.1-All About Stacks
3.1-All About Stacks
• Applications of Stack
• Reverse a sequence of number using stack
• Keep track of function calls in a program
• Testing the correctness of a mathematical expression
• Converting a mathematical expression from infix to postfix and prefix notations
• Solving a mathematical expression in postfix form
2
What is a Stack?
• Definition:
• Conceptually, a stack is a data structure that allows adding and
removing elements in a particular order
3
Stack
• Stack is a linear data structure in which input and output operations
are constrained at only at the top end.
• Insertion or removal of an item is allowed only at the top end.
• Only the element at the top end can be accessed
4
Stack
• Stack is said to have “First In, Last Out" (FILO) or “Last In, First Out”
(LIFO) behaviour meaning that the first item added to a stack will be
the last item removed from a stack
• Example:
• Which is the first coin to pick up from
• the stack of gold coins?
5
Basics of stack
• Size: The number of elements on the stack
• Top: Points to the top most element on the stack. This refers to NULL
if stack is empty or size = 0
6
Stack Operations
• Primarily two operations performed on one end only
7
Stack Operations
• Push Concerns
• What if when the stack is full?
• If the push operation is called when a stack is already full, the condition is called “stack overflow”
• Pop Concerns
• What if the stack is empty
• If the pop operation is called when a stack is already empty, the condition is called “stack underflow”
Solution:
• Before any push, check if the stack is already filled or not
• If it is filled then generate error message e.g., Stack Overflow
• Before pop, check if stack is not already empty
• If it is empty then generate error message e.g., Stack Underflow
8
Stack Operations
push(item) // Push an item onto the stack
• Computer Science
• Compilers use stacks to evaluate expressions & syntax parsing
• Program execution stack
• Undo operations
• Expression conversion
• Infix to post-, pre-fix and vice versa
• Tower of Hanoi
• And many more …
10
Choice of implementation
• Array based: Stack Maximum stack size is known ahead of time
11
Array based Stack
12
Array based Stack
• When using an array to implement a stack
• The array's first element should represent the bottom of the stack
• The last occupied location in the array represents the stack's top
13
Array based stack
• Allocate an array of some size (pre-defined)
• Maximum N elements in stack
15
Linked List based Stack
16
Linked List based implementation
• How can we implement Stack using linked lists?
• LIFO
• Push = Insert at head
• Pop = Remove at head
• IsEmpty = Empty List
• Peek()/Top() = reading element at the top without popping it out.
• Clear = Destroy List
17
Linked List based implementation
class node class stack
{ {
public: int size;
int value; node* top;
node* next; public:
}; //class node stack() {
size=0;
top=NULL;
} //default constructor
void push(int);
bool pop();
bool isEmpty();
};
18
Linked List based implementation
void stack::push(int el) int stack::pop()
{ { int d;
node *temp; if(isEmpty()) {
temp =new node; cout<<"\nStack is Empty\n";
if (top==NULL) { return -9999;
temp->next =NULL; }
} else {
else { Node *temp = top;
temp->next =top; top=top->next;
} d=temp->value;
temp->value=el; delete temp;
top=temp; size--;
size++; }
} return d;
} 19
Linked List based implementation
bool stack::isEmpty() void main ()
{ {
if(getStackSize()==0) ...
return true; stack();
stack.push(5);
...
return false; }
}
20
Applications of Stacks
21
Application: Recursive
Function Implementation
22
Function calls & recursive
implementation
• The state of each function, including main(), is characterized
• by the contents of all local variables,
• by the values of the function’s parameters, and
• by the return address indicating where to restart in the calling function
• The data area containing all this information is called an activation record or a stack
frame and is allocated on the run-time stack
• exists for as long as a function owning it is executing
• This record is a private pool of information for the function, a repository that stores all
information necessary for its proper execution and how to return to where it was called
from
23
Activation Record / Stack Frame
• If a function is called either by
main() or by another function,
then its stack frame is created on
the run-time stack
It helps the program know where to return after the current function has finished
executing, and it connects different activation records on the call stack, helping 25
Evaluating Exponents Recursively
double power (double x, unsigned int n) /* 102 */
{
if (n == 0) /* 103 */
return 1.0; /* 104 */
else
return x * power(x,n-1); /* 105 */
}
int main()
{ ...
y = power(5.6,2); /* 136 */
...
} 26
Evaluating Exponents Recursively
double power (double x, unsigned int n) /* 102 */
{
if (n == 0) /* 103 */
return 1.0; /* 104 */
else Trace of the recursive
calls
return x * power(x,n-1); /* 105 */
}
int main()
{ ...
y = power(5.6,2); /* 136 */
...
}
27
First, the value of the second argument, i.e., 2, is checked,
and power() tries to return the value of 5.6 * power(5.6,1)
36
Algebraic expression
• An algebraic expression is a legal combination of operands and the
operators
• Operand is the quantity (unit of data) on which a mathematical
operation is performed
• E.g., operand may be a variable like x, y, z or a constant like 5, 4,0,9,1 etc.
• Operator is a symbol which signifies a mathematical or logical
operation between the operands
• Example of familiar operators include +,-,*, /, ^
• Considering these definitions of operands and operators, an example
of expression may be x+y*z
37
Stacks in problem solving
• Consider a mathematical expression that includes several sets of
nested parenthesis, e.g.,
( x + (y – (a +b)) )
• We want to ensure that parenthesis are nested correctly and the
expression is valid
Validation
• There is an equal number of right and left parentheses
• Every right parenthesis is preceded by a matching left parenthesis
(A+B) * C Valid
A + B) Invalid
(A+B] Invalid 38
Rules
• Each left parentheses is the opening scope while each right
parenthesis is a closing scope
• Parentheses count = 0 at the end means that no scopes have been left
open and left and right parentheses exactly match
((A+B) (A*B)
122221 11110
39
Parsing parenthesis
• Let us change the problem slightly
• Three different kinds of scope delimiters exist
e.g., { x + (y – [a +b]) }
• It is necessary to keep track of not only the count of scope but also the types
40
Stacks in validating expression
• Whenever a scope opener is encountered
• it is pushed into the stack
• Whenever a scope ender is encountered,
• The stack is examined
• If the stack is empty, the scope ender does not have a matching opener and
string is invalid
• If stack is not empty, we pop an item and check if it corresponds to scope
ender
• If match occurs we continue,
• otherwise the expression is invalid
• At the end of the string the stack must be empty
41
Valid = true
S = the empty stack // array of chars say char s[100]
While (we have not read the entire string) {
read the next symbol (symb) of the string;
Pseudo code
if (symb == ‘(‘ || symb == ‘[‘ || symb == ‘{‘)
push (s, symb);
if (symb == ‘)‘ || symb == ‘]‘ || symb == ‘}‘)
if (IsEmpty(s))
valid = false;
else {
I = pop (s);
if ( I is not the matching opener of symb)
valid = false;
}// end of else
} //end while
If (valid)
cout << “Valid String” << endl;
Else
cout << “not a valid string” 42
Stacks in validating expression
{ x + (y – [a +b]) }
( ( (
{ { { { {
43
1 2 3 4 5 6 7
Application: Infix to Postfix
conversion
44
Operator Priorities
• How do you figure out the operands of an operator?
• a+b*c
• a*b+c/d
45
Tie breaker
• When an operand lies between two operators that have the same
priority, the operand is associated with the operator on the left
• a+b-c
• a*b/c/d
46
Infix, Prefix & Postfix expressions
• INFIX: Expressions in which operands surround the operator,
• e.g., x+y, 6*3 … etc.
• INFIX notations are not as simple as they seem especially while evaluating
them
• To evaluate an infix expression we need to consider operators’ Priority and
Associative property
• E.g., expression 3+5*4 can either be evaluated as 32 i.e., (3+5)*4 or 23
i.e., 3+(5*4)
• To solve this problem Precedence or Priority of the operators were
defined to govern the evaluation order i.e., operator with higher
precedence is applied before an operator with lower precedence 48
Prefix & Postfix notations, why to
use?
• Compilers need to generate assembly code in which one operation is
executed at a time and the result is retained for other operations
49
Expression tree
Prefix
Infix
Postfix
50
Order of Precedence
• Following is the order of precedence for arithmetic operators ( From
highest to lowest )
51
Examples of Infix to Post- & Prefix
52
Infix to Postfix
Example 4:
A+B*C
A+(B*C) Parentheses for emphasis
A+(BC*) Convert the multiplication, Let D=BC*
A+D Convert the addition
AD+
ABC*+ Postfix Form
53
More examples
54
Infix to postfix conversion
Example 5
A+B-C =
[AB+]-C
AB+C-
Example 6
(A+B)*(C-D)
= [AB+]*(C-D)
= [AB+]*[CD-]
= AB+CD-*
55
Infix to postfix conversion
Example 7
A^B*C-D+E/F/(G+H)
= A^B*C-D+E/F/[GH+]
= [AB^]*C-D+E/F/[GH+]
= [AB^C*]-D+E/F/[GH+]
= [AB^C*]-D+[EF/]/[GH+]
= [AB^C*]-D+[EF/GH+/]
= [AB^C*D-]+[EF/GH+/]
= AB^C*D-EF/GH+/+
56
Infix to postfix conversion
Example 8
((A+B)*C-(D-E))^(F+G)
=([AB+]*C-[DE-])^[FG+]
=([AB+C*]-[DE-])^[FG+]
=[AB+C*DE--]^[FG+]
=AB+C*DE—FG+^
57
Infix to postfix conversion
Example 9
A-B/(C*D^E)
=A-B/(C*[DE^])
=A-B/[CDE^*]
=A-[BCDE^*/]
=ABCDE^*/-
58
Applications: Infix to
Postfix Conversion using
Stack
59
Infix to Postfix conversion algorithm
• Create an empty stack for keeping operators
• Create an empty list for output
• Scan each element of input expression from left to right
• If the element is an operand, append it to the end of the postfix string
• If the element is a left parenthesis, push it on the stack
• If the element is a right parenthesis, apply pop operation to the stack until the corresponding left
parenthesis is removed & append each operator to the end of the postfix string; when the left
parenthesis pops off the stack, discard it and the right parenthesis.
• If the current element is an operator, *, /, +, or -, push it on the stack if its priority is higher than the
symbol at the top of the stack. However, first remove any operators already on the stack that have
higher or equal precedence and append them to the postfix string.
• Note: When, left parenthesis appears on the top of the stack, it has the lowest precedence in
comparison to any other operator that is the current element.
• When the input expression has been completely processed, check the stack. Any operators still on the stack
60
can be removed and appended to the end of the postfix string.
Source: https://prepinsta.com/data-structures/infix-to-postfix-conversion/
61
Source: https://prepinsta.com/wp-content/uploads/2020/07/Infix-to-postfix-conversion.webp
62
Precendence Function
• Precedence Function : prcd(op1,op2)
• Op1 & Op2 represent operators +,-,*,/
• Assume we pass current operator as op1, and the operator at stack top as
op2.
• If op1 has higher precedence than op2 , the prcd(op1,op2) returns true. For
example prcd(‘*’,’+’) and prcd(‘/’,’+’) is true.
63
Algorithm to Convert an Expression
from Infix to Postfix Form
Opstk=the empty stack;
while (not end of input){
symb= next input character ; push(opstk , symb );
if (symb is an operand) } //end of else
add symb to the postfix string ;
else { } // end of while
while (!empty(opstk)&& prcd(symb,
stacktop(opstk))) { // output remaining operators
topsymb = pop (opstk) ; while (!empty(opstk)) {
add topsymb to the postfix string ; topsymb = pop(opstk) ;
} //end of while add topsymb to the postfix string ;
} //end of while 64
Suppose we want to convert 2*3/(2-1)+5*3 into Postfix form,
Expression Stack Output
2 Empty 2
* * 2
3 * 23
/ / 23*
( /( 23*
2 /( 23*2
- /(- 23*2
1 /(- 23*21
) / 23*21-
+ + 23*21-/
5 + 23*21-/5
* +* 23*21-/5
3 +* 23*21-/53
Empty 23*21-/53*+
65
Applications: Evaluating a
Postfix expression using
Stack
66
Evaluating Postfix expression
• Each operator in a postfix string refers to the previous two operands
in the string
68
Algorithm to evaluate Postfix
expression
WHILE more input items exist
{
If symb is an operand
then push (stk,symb) // stk is the stack used
else //symbol is an operator
{
Opnd1=pop(stk);
Opnd2=pop(stk);
Value = result of applying symb to opnd1 & opnd2
Push(stk,value);
} //End of else
} // end while
Result = pop (stk); 69
Algorithm to evaluate Postfix
expression
70
Question
• Evaluate following Postfix expression:
623+-382/+*2^3+
Final answer is
a) 49
b) 51
c) 52
d) 7
e) None of these
71
Applications: Adding very
large integers
72
Adding very large numbers
• Consider adding very large numbers
• Since the largest magnitude of integers is limited (32 bits), so we are not able to
perform following:
18,274,364,583,929,273,748,459,595,684,373
+
8,129,498,165,026,350,236
because integer variables cannot hold such large values
• The problem can be solved if we
• treat these numbers as strings of numerals,
• store the numbers corresponding to these numerals on two stacks, and
• then perform addition by popping numbers from the stacks
73
74
Conclusion
• Stack is a LIFO or FILO data structure due to input and output operations constrained
only at the top end.
• Practical applications
• Stacks in validating expressions
• Infix to Postfix conversion & evaluation
• Postfix/Prefix forms do not rely on operator priorities, a tie breaker, or delimiters
• Easier evaluation of expressions
• Unambiguous expression tree
• Algorithms implementing stack
• To convert any Infix expression into its corresponding postfix or prefix expression
• To evaluate any postfix expression
• Adding very large integer numbers
75
CS250: Data Structures and Algorithms
Thank you