Stacks. Objective After this lecture you will be able to: Describe a stack Describe the representation of stack using linear array Describe the representation of stack using linear linked list Implementation of various operations on stack Describe some applications of stacks. Stack.
Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.
After this lecture you will be able to:
The following figure illustrate a stack, which can accommodate maximum of 10 elementsfigure shows stack after pushing elements 8,10,12,5,6
9
8
7
6
5
top
4
6
5
3
2
12
1
10
0
8
9
8
7
6
5
4
3
top
2
12
1
10
0
8
9
8
7
top
6
55
5
9
4
6
5
3
2
12
1
10
0
8
Suppose elements of the stack are integer type and stack can store maximum 10 elements..
#define MAX 10
typedef struct
{
int top;
int elements[MAX];
}stack;
stack s;
typedef enum {false, true } Boolean;
This statement defined new data type named Boolean which can take value false or true.
0 1 2 3 4 5 6 7 8 9
4
top
0 1 2 3 4 5 6 7 8 9
2
top
0 1 2 3 4 5 6 7 8 9
6
top
Void createstack( stack *ps)
{
ps=1;
}
Boolean isempty(stack *ps)
{
if(ps>top==1)
return true;
else
return false;
}
or
Boolean is empty(stack *ps)
{
return ((ps>top==1)?true:false);
}
Boolean isfull(stack *ps)
{
if(ps>top==MAX1)
return true;
else
return false;
}
or
Boolean is empty(stack *ps)
{
return ((ps>top==MAX1)?true:false);
}
Before the push operation, if the stack is empty, then the value of the top will be 1and if the stack is not empty then the value of the top will be the index of the element currently on the top.
Therefore we place the value onto the stack, the value of top is incremented so that it points to the new top of stack, where incoming element is placed.
Void push(stack *ps, int value)
{
ps>top++;
ps>elements[ps>top]=value;
}
The element on the top of the stack is assigned to a local variable, which later on will be returned via the return statement.
After assigning the top element to a local variable, the variable top is decremented so that it points to a new top
Int pop(stack *ps)
{
int temp;
temp=ps>elements[ps>top];
ps>top;
return temp;
}
There may be instances where we want to access the top element of the stack without removing it from the stack.
Int peek( stack *ps)
{
return(ps>elements[ps>top]);
}
A stack represented using a linked list is also known as linked stack.
The array based representation of stack suffers from following limitations.
However stack is an abstract data structure can not be full. Hence, abstractly, it is always possible to push an element onto stack. Therefore stack as an array prohibits the growth of the stack beyond the finite number of elements.
The linked list representation allows a stack to grow to a limit of the computer’s memory.
Typedef struct nodetype
{
int info;
struct nodetype *next;
}stack;
Stack *top;
Here I have defined my own data type named stack, which is a self referential structure and whose first element info hold the element of the stack and the second element next hold the address of the element under it in the stack.
The last line declares a pointer variable top of type stack.
top
6
5
12
10
8 X
top
6
5
12 X
top
55
9
6
5
12
10
8 X
Before we can use a stack, it is to be initialized. To initialize a stack, we will create an empty linked list.
The empty linked list is created by setting pointer variable top to value NULL.
Void createstack(stack **top)
{
*top=NULL;
}
Boolean isempty(stack *top)
{
if(top==NULL)
return true;
else
return false;
}
or
Boolean is empty(stack *top)
{
return ((top==NULL)?true:false);
}
Since stack represented using a linked list can grow to a limit of computers memory, there overflow condition never occurs. Hence this operation is not implemented for linked list.
To push a new element onto the stack, the element is inserted in the beginning of the linked list.
void push(stack **top, int value)
{
stack *ptr;
ptr=(stack*)malloc(sizeof(stack));
if(ptr==NULL)
{
printf(“\n unable to allocate memory for new node…”);
printf(“\npress any key to exit..”);
getch();
return;
}
ptr>info=value;
ptr>next=*top;
*top=ptr;
}
To pop an element from the stack, the element is removed from the beginning of the linked list.
Int pop(stack **top)
{
int temp;
stack *ptr;
temp=(*top)>info;
ptr=*top;
*top=(*top)>next;
free(ptr);
return temp;
}
Int peek(stack *top)
{
return(top>info)
}
Because the stack is implemented using linked lists, therefore it is programmers job to write the code to release the memory occupied by the stack.
Void disposestack(stack **top)
{
stack *ptr;
while(*top!=NULL)
{
ptr=*top;
*top=(*top)>next;
free(ptr);
}
}
In addition to above stack are used to solve the various problems….
For an input expression, it verifies that for each left parenthesis, braces or racket, there is a corresponding closing symbol and the symbols are appropriately nested.
Inside parenthesis there can be any valid arithmetic expression.
parenthesisChecker(exp)
Begin
Read: exp
Create empty stack
For each character c in exp
if(current character is left symbol) then
push the character onto stack
else if(current character is right symbol) then
if(stack is empty) then
print: “Error No matching open symbol”
exit
else
pop a symbol s from the stack
if( s doesn’t correspond to c) then
print: “Error incorrect nesting of symbol”
exit
endif
endif
endif
Endfor
If(stack is not empty) then
print:”Error missing closing symbol”
Else
print: input expression is ok”
End
In this notation, the operator symbol is placed between its two operands.
In this notation we must distinguish between
(A+B)/C and A+(B/C)
In this notation, named after the polish mathematician Jan Lukasiewiez, the operator symbol is placed before its two operands.
In order to translate an arithmetic expression in infix notation to polish notation, we do step by step using rackets ([]) to indicate the partial translations.
(AB/C)*(A*KL)
The partial translation may look like:
(A[/BC])*([*AK]L)
[A/BC]*[*AKL]
*A/BC*AKL
The fundamental property of polish notation is that the order in which the operations to perform is completely determined by the position of the operators and operands in the expression.
Accordingly one never needs parenthesis when writing expression in polish notation.
In this notation the operator symbol is placed after its two operands.
Consider the following expression in infix notation:
(AB/C)*(A/KL)
The partial translation may look like:]
(A[BC/])*([AK/]L)
[ABC/]*[AK/L]
ABC/AK/L*
Generally we use infix notation, where one can not tell the order in which the operator should be applied by looking at the expression.
The expression in postfix notation is very easy to evaluate, as the operands appear before the operator, there is no need of operator precedence or parentheses for operation.
In order to evaluate a postfix expression it is scanned from left to right.
As operands are encountered, they are pushed on a stack.
When an operator encountered, pop top one or two operands depending on the operator, perform the operation and place the result back on the stack.
Consider the following infix expression q:
(75)*(9/2)
Evaluate postfixnotation(p,result)
Begin
Create empty stack
while(not end of exp p) do
if(element is operand) then
push element onto stack
else
pop two elements and let first one is a and the second one is b
evalute [email protected], let its value be c, where @ is operator
push c onto stack
endif
endwhile
pop stack and assign this value to parameter result
end
Consider the following postfix expression p:
7 5 – 9 2 / *
(example: files, strings)
Very useful for finding palindromes.
Consider the following pseudocode:
1)read (data)
2)loop (data not EOF and stack not full)
1) push (data)
2) read (data)
3)Loop (while stack notEmpty)
1) pop (data)
2) print (data)
1) digit = number modulo 2
2) print (digit)
3) number = number / 2
// from Data Structures by Gilbert and Forouzan
The problem with this code is that it will print the binary
number backwards. (ex: 19 becomes 11001000 instead of 00010011. )
To remedy this problem, instead of printing the digit right away, we can
push it onto the stack. Then after the number is done being converted, we
pop the digit out of the stack and print it.
If we encounter a right parenthesis, pop from stack until we get
matching left parenthesis. Do not output parenthesis.
A + B * C  D / E
InfixStack(bot>top)Postfix
a) A + B * C  D / E
b) + B * C  D / EA
c) B * C  D / E+ A
d) * C  D / E+A B
e) C  D / E+ *A B
f)  D / E+ *A B C
g) D / E+ A B C *
h) / E+ A B C * D
i) E+  /A B C * D
j)+  /A B C * D E
k)A B C * D E /  +
A * B  ( C + D ) + E
InfixStack(bot>top)Postfix
Operand: push
Operator: pop 2 operands, do the math, pop result
back onto stack
1 2 3 + *
PostfixStack( bot > top )
compiler
user
Postfix: no parentheses, no precedence
Infix to Postfix
#define MAX_STACK_SIZE 100 /* maximum stack size */#define MAX_EXPR_SIZE 100 /* max size of expression */typedef enum{lparan, rparen, plus, minus, times, divide, mod, eos, operand} precedence;int stack[MAX_STACK_SIZE]; /* global stack */char expr[MAX_EXPR_SIZE]; /* input string */
Assumptions:
operators: +, , *, /, %
operands: single digit integer
Evaluation of Postfix Expressions
int eval(void){/* evaluate a postfix expression, expr, maintained as a global variable, ‘\0’ is the the end of the expression. The stack and top of the stack are global variables. get_token is used to return the token type and the character symbol. Operands are assumed to be single character digits */ precedence token; char symbol; int op1, op2; int n = 0; /* counter for the expression string */ int top = 1; token = get_token(&symbol, &n); while (token != eos) { if (token == operand) push(&top, symbol’0’); /* stack insert */
else { /* remove two operands, perform operation, and return result to the stack */ op2 = pop(&top); /* stack delete */ op1 = pop(&top); switch(token) { case plus: push(&top, op1+op2); break; case minus: push(&top, op1op2); break; case times: push(&top, op1*op2); break; case divide: push(&top, op1/op2); break; case mod: push(&top, op1%op2); } } token = get_token (&symbol, &n); } return pop(&top); /* return result */}
precedence get_token(char *symbol, int *n){/* get the next token, symbol is the character representation, which is returned, the token is represented by its enumerated value, which is returned in the function name */ *symbol =expr[(*n)++]; switch (*symbol) { case ‘(‘ : return lparen; case ’)’ : return rparen; case ‘+’: return plus; case ‘’ : return minus;
case ‘/’ : return divide; case ‘*’ : return times; case ‘%’ : return mod; case ‘\0‘ : return eos; default : return operand; /* no error checking, default is operand */ }}
(1)Fully parenthesized expression
a / b  c + d * e  a * c >
((((a / b)  c) + (d * e)) – (a * c))
(2)All operators replace their corresponding right
parentheses.
((((a / b)  c) + (d * e)) – (a * c))
(3)
Delete all parentheses.
ab/cde*+ac*
two passes

*
*
/
+

The orders of operands in infix and postfix are the same.
a + b * c, * > +
Rules
(1)Operators are taken out of the stack as long as their
instack precedence is higher than or equal to the
incoming precedence of the new operator.
(2)( has low instack precedence, and high incoming
precedence.
()+*/%eos
isp0 1912 121313130
icp201912121313130
precedence stack[MAX_STACK_SIZE];/* isp and icp arrays  index is value of precedencelparen, rparen, plus, minus, times, divide, mod, eos */static int isp [ ] = {0, 19, 12, 12, 13, 13, 13, 0};static int icp [ ] = {20, 19, 12, 12, 13, 13, 13, 0};
isp: instack precedence
icp: incoming precedence
Infix to Postfix
void postfix(void){/* output the postfix of the expression. The expression string, the stack, and top are global */ char symbol; precedence token; int n = 0; int top = 0; /* place eos on stack */ stack[0] = eos; for (token = get _token(&symbol, &n); token != eos; token = get_token(&symbol, &n)) { if (token == operand) printf (“%c”, symbol); else if (token == rparen ){
Infix to Postfix (cont’d)
/*unstack tokens until left parenthesis */ while (stack[top] != lparen) print_token(delete(&top)); pop(&top); /*discard the left parenthesis */ } else{ /* remove and print symbols whose isp is greater than or equal to the current token’s icp */ while(isp[stack[top]] >= icp[token] ) print_token(delete(&top)); push(&top, token); } } while ((token = pop(&top)) != eos) print_token(token); print(“\n”);}