Unit - 2
Stacks and Queues
A stack is an Abstract Data Type (ADT), commonly used in most programming languages. It is named stack as it behaves like a real-world stack, for example – a deck of cards or a pile of plates, etc.
Stack Example
A real-world stack allows operations at one end only. For example, we can place or remove a card or plate from the top of the stack only. Likewise, Stack ADT allows all data operations at one end only. At any given time, we can only access the top element of a stack.
This feature makes it LIFO data structure. LIFO stands for Last-in-first-out. Here, the element which is placed (inserted or added) last, is accessed first. In stack terminology, insertion operation is called PUSH operation and removal operation is called POP operation.
Stack Representation
A stack can be implemented by means of Array, Structure, Pointer, and Linked List. Stack can either be a fixed size one or it may have a sense of dynamic resizing. In stack we implement stack using arrays, which makes it a fixed size stack implementation.
Basic Operations
Stack operations may involve initializing the stack, using it and then de-initializing it. Apart from these basic stuffs, a stack is used for the following two primary operations −
Push() − Pushing (storing) an element on the stack.
Pop() − Removing (accessing) an element from the stack.
Stack Push Operation
If the linked list is used to implement the stack, then in step 3, we need to allocate space dynamically.
Algorithm for PUSH Operation
A simple algorithm for Push operation can be derived as follows −
Begin procedure push: stack, data
if stack is full
return null
endif
top ← top + 1
stack[top] ← data
End procedure
Implementation of this algorithm in C, is very easy.
See the following code −
Example
Void push(int data) {
if(!isFull()) {
top = top + 1;
stack[top] = data;
} else {
printf("Could not insert data, Stack is full.\n");
}
}
Pop Operation
Accessing the content while removing it from the stack, is known as a Pop Operation. In an array implementation of pop() operation, the data element is not actually removed, instead top is decremented to a lower position in the stack to point to the next value. But in linked-list implementation, pop() actually removes data element and deallocates memory space.
A Pop operation may involve the following steps −
Step 1 − Checks if the stack is empty.
Step 2 − If the stack is empty, produces an error and exit.
Step 3 − If the stack is not empty, accesses the data element at which top is pointing.
Step 4 − Decreases the value of top by 1.
Step 5 − Returns success.
Stack Pop Operation
Algorithm for Pop Operation
A simple algorithm for Pop operation can be derived as follows −
Begin procedure pop: stack
if stack is empty
return null
endif
data ← stack[top]
top ← top - 1
return data
End procedure
Implementation of this algorithm in C, is as follows −
Example
Int pop(int data) {
if(!isempty()) {
data = stack[top];
top = top - 1;
return data;
} else {
printf("Could not retrieve data, Stack is empty.\n");
}
}
We need an effective mathematical theory to measure complexity and categorize the different implementations in terms of efficiency. The theory should be simple enough to allow us to study even the more complicated problems but at the same time it should be realistic. It should also be broad and unifying, allowing us to study and compare seemingly different cases.
Complexity functions that encounter include the following:
- O(1) – Constant
- O(logn) – Logarithmic
- O(n) – Linear
- O(nlogn) – (Linearithmic)
- O(n2 ) – Quadratic
There are many real-life examples of a stack. Consider the simple example of plates stacked over one another in a canteen. The plate which is at the top is the first one to be removed, i.e. the plate which has been placed at the bottommost position remains in the stack for the longest period of time. So, it can be simply seen to follow LIFO/FILO order.
Operations on Stack
There are three fundamental operations on stack.
Push: Insert element to the stack
Pop: Delete element from stack
Peek: Returns element at the top of stack
We will see these operations with respect to an example.
Here we assume stack size is 3.
Initially stack is empty. If pop operation is called on empty stack then stack underflow occurs.
----- (empty stack)
Push element ‘7’ to the stack. Then stack becomes
| 7 | <-- top
-----
Push element ‘2’ to the stack. So new top of stack is 2.
| 2 | <-- top
| 7 |
-----
Push element ‘10’ to the stack. Now top of stack becomes 10.
|10 | <-- top
| 2 |
| 7 |
-----
Now the stack becomes full as we are assuming stack size is 3. If we insert one more element onto stack then stack overflow occurs.
Pop element from stack. Element 10 is popped out. Hence new top is 2.
| 2 | <-- top
| 7 |
-----
Since Stack is LIFO data structure element inserted most recently will be popped out first.
Pop element 2 from stack. Hence new top is 7.
| 7 | <-- top
-----
Pop element 7 from stack. Now stack becomes empty.
----- (empty stack)
Array Implementation of Stack
Array implementation of stack is efficient if we know maximum size of stack.
Our stack must be able to store any type of data i.e.int, char, float or any other primitive data type.
Stack which is used to hold integer values must be able to hold float and character values.
For this we will not explicitly recode specific version of stack for each data type.
C++ provides this feature through class templates. Thus we implement stack ADT in C++ using class templates.
When we create class template, it can perform operations on any type of data.
The compiler will automatically generate correct type of object, depending on the type we specify when object is created.
Thus a stack ADT can be written as follows.
First we create node structure template.
Template<class TYPE>
Struct Node
{
Type value;
};
Template<class TYPE>// class template
Class stack
{
Private:
Node<TYPE> *P; // pointer to structure
Int count;// total no. Of elements present in stack
Int max;// total no. Of elements allowed in stack
Int top; // index of top of stack
Public:
Stack(int size=100); // constructor to create a stack
~stack();// destructor to destroy stack
Bool push(TYPE in);// function to insert element in stack
Bool pop(TYPE &out);// function to delete element in stack
Bool peek(TYPE& out);//return top element of stack
Bool isempty();//check if stack is empty
Bool isfull();//check if stack is full
Int stackcount();// returns no. Of elements currently in stack
};
Now we will see algorithms for these operations on stack in detail.
Create stack: stack()
Stack is created using constructor.
Steps
| Algorithm: stack(int size) | Description |
1 | Template<class TYPE> Stack<TYPE>::stack(int size) {
| Design constructor which takes stack size as an argument |
2 | Max=size;
| Assign size to max. Value of size can be passed or default size of 100 is assumed. |
3 | P=new Node<TYPE>[max]; | Allocate memory to P
|
4 | If(!P) { Cout<<”Memory overflow”; Abort(); }
| Check if memory is available. If memory is not available, abort and print “memory overflow “. |
5 | Count=0; Top=-1; }
| Initially stack is empty. So count is 0 and stack top is -1.
|
2. Insert element in Stack: push()
Steps
| Algorithm: bool push(TYPE in)
| Description |
1 | Template<class TYPE> Bool stack<TYPE>::push(TYPE in) {
| Design function push which inserts element ‘in’ to stack |
2 | If(count>=max) Return false | Compare current total no. Of elements with maximum stack size. If stack is full then return false to indicate element cannot be inserted. |
3 | P[top].value=in
| If stack is not full copy data to top of stack
|
4 | Count++; Top++; Return true } | Increment count and top. Return true to indicate element is successfully inserted in stack. |
3. Remove element from stack: pop()
Steps
| Algorithm: bool pop(TYPE& out) | Description |
1 | Template<class TYPE> Bool stack<TYPE>::pop(TYPE& out) {
| Design function pop which deletes element on the top of stack. Out is a reference variable to receive element to be popped out. |
2 | Bool flag; If(count==0) Flag=false; | If stack is empty then set flag to false |
3 | Else { Out=P[top].value;
| If stack has elements, copy element at top of stack to variable out. |
4 | Top--; Count--; Flag=true; }
| Decrement count and top. Set flag to true to indicate pop is successful. |
5 | Return flag; } | Return flag |
4. Find top of stack(tos): peek
Steps
| Algorithm: bool peek(TYPE& out) | Description |
1 | Template<class TYPE> Bool stack<TYPE>::peek(TYPE& out) {
| Design function peek which returns element on the top of stack without modifying stack. Out is a reference variable to receive element at the top of stack. |
2 | Bool flag; If(count==0) Flag=false; | If stack is empty then set flag to false |
3 | Else { Out=P[top].value;
| If stack has elements, copy element at top of stack to variable out. |
4 | Flag=true; }
| Set flag to true. |
5 | Return flag; } | Return flag |
5. Check if the stack is empty: isEmpty()
Steps
| Algorithm: bool isEmpty() | Description |
1 | Template<class TYPE> Bool stack<TYPE>::isEmpty() {
| Design function isEmpty() which returns true if stack is empty and false otherwise. |
2 | Bool flag; If(count==0) Flag=true; | If stack is empty then set flag to true |
3 | Else Flag=false;
| If stack has elements set flag to false. |
4 | Return flag; } | Return flag |
6. Check if the stack is full: isFull()
Steps
| Algorithm: bool isFull() | Description |
1 | Template<class TYPE> Bool stack<TYPE>::isFull() {
| Design function isFull() which returns true if stack is full and false otherwise. |
2 | Bool flag; If(count==max) Flag=true; | Compare count with maximum number of elements allocated for a stack. If they are equal set flag to true. |
3 | Else Flag=false;
| If count is not equal to max set flag to false. |
4 | Return flag; } | Return flag |
7.Find total number of elements in stack: stackcount()
Steps
| Algorithm: int stackcount() | Description |
1 | Template<class TYPE> Int stack<TYPE>::stackcount() {
| Design function stackcount() which returns total number of elements present in stack. |
2 | Return count; } | ‘count’ specifies total number of elements present in stack so return count |
Destroy stack:~stack()
Stack is destroyed using destructor.
Steps
| Algorithm: ~stack() | Description |
1 | Template<class TYPE> Stack<TYPE>::~stack() {
| Design destructor to destroy stack |
2 | Delete[] P P=NULL; Count=0; Max=0; Top=-1; } | Release memory of P. Set variables count,max to 0 and top to -1. |
Program in C++ to perform various operations on stack.
#include<iostream.h>
# define int MAX 100
Template< class TYPE >//class template
Class Stack {
int count;//number of elements present in stack
TYPE A[Max];// Array of size MAX
TYPE out;
int top;// index of top of stack
Public:
Stack(int MAX);
~Stack();
bool push(TYPE);
TYPE pop();
bool isEmpty();
bool isFull();
int stackcount();
void display();
};
Template< class TYPE >//constructor to create stack
Stack< TYPE >::Stack(int MAX)
{
count=0;
top = -1;
}
Template< class TYPE >//destructor to remove stack
Stack< TYPE >::~Stack()
{ delete[] A;
count=0;
MAX=0;
top=-1;
}
Template< class TYPE>// function to push elements in stack
Void Stack< TYPE >::push(TYPE in)
{
If(count>=MAX)
Cout<<”stack overflow”
Count++;
Top++;
A[ top ] = in; //copy data to top of stack
}
Template< class TYPE > // Function to pop elements from stack
TYPE Stack< TYPE >::pop()
{ return A[ top-- ];
count--;
}
Template< class TYPE>//Function to check if stack is full
Int Stack< TYPE>::isFull()
{
Return (count == Max);
}
Template< class TYPE>//Function to check if stack is empty
Int Stack< TYPE>::isEmpty()
{
Return (count == 0);
}
Template< class TYPE>
Int Stack< TYPE>::stackcount()
{
Return count;
}
Template< class TYPE> //Function to display stack elements
Void Stack<TYPE>::display()
{
If(top<0)
Cout<<”stack empty”;
For(int i=top;i>=0;i--)
Cout<<A[i]<<” ”;
}
Void main()
{
Int choice,data;
Stack<int> S;//create stack of integers
While(1)
{
Cout<<”Enter choice for operation”;
Cout<<”\t1.PUSH”<<endl;
Cout<<”\t2.POP”<<endl;
Cout<<”\t3.ISFULL”<<endl;
Cout<<”\t4.ISEMPTY”<<endl;
Cout<<”\t5.Stackcount”<<endl;
Cout<<”\t6.Display”<<endl;
Cin>>choice;
Switch(choice)
{
Case 1:
Cout<<”Enter element to be pushed”;
Cin>>data
S.push(data);
Break;
Case 2:
Out=S.pop();
Cout<<”Popped element is”<<out;
Break;
Case 3:
Int flag=S.isFull();
If(flag=1)
Cout<<”stack is full”;
Else
Cout<<”stack is not full”;
Break;
Case 4:
Int flag=S.isEmpty();
If(flag=1)
Cout<<”stack is empty”;
Else
Cout<<”stack is not empty”;
Break;
Case 5:int c=S.stackcount();
Cout<<”Stack count is”<<c;
Break;
Case 6: S.display();
Break;
}//end of switch
}//end of while
}//end of program
Applications of Stack – Well form-ness of Parenthesis, Infix to Postfix Conversion and Postfix Evaluation
Applications of Stacks
Applications of stacks are as follows.
- Reversing data
- Parsing
- Expression evaluation
- Expression conversion
Reversing data
Data reversing is a technique of reordering data elements so that first element becomes last, second element becomes last but one and so on. Consider array A
Fig. Original Array
After reversing array becomes
Algorithm to reverse list of integers is as follows.
Steps
| Algorithm(Reverse) | Description |
1 | Create Stack | Create an empty stack |
2 | Read number | Accept integer from user |
3
3.1 3.2 | Loop(!fullstack(stack)) { Push(stack.number) Read number } | Accept integers from user to fill the stack till it is not full. |
4
4.1 4.2 | Loop(!emptystack(stack)) { Pop(stack.out) Print(out) } | Pop elements from stack till stack is not empty. Print popped element to user. |
Another application of reversing data is conversion of decimal number to binary number. Algorithm for conversion of decimal to binary number is as follows.
Steps
| Algorithm(DecimaltoBinary) | Description |
1 | Create Stack | Create an empty stack |
2 | Read decimal number | Accept decimal number from user |
3
3.1 3.2 3.3
3.3.1 | Loop(number>0) { d=number%2 Flag=push(stack.d) If(flag==false) { Print stack overflow } Number=number/2 } | Convert the number to binary and push to stack. When stack becomes full print “stack overflow.” |
4
4.1 4.2 | Loop(!emptystack(stack)) { Pop(stack.d) Print(d) } | Pop elements from stack till stack is not empty. Print popped element to user |
***Program to convert decimal number to binary number****
#include <iostream>
#include <stdio.h>
#include <conio.h>
Using namespace std;
Struct Node
{
int value;
Node *next;
}*top = NULL, *P = NULL, *temp = NULL;
Int x;
Void push(int P)
{
temp = new Node;
temp->value = P;
temp->next = NULL;
if (top == NULL)
{
top = temp;
}
else
{
temp->next = top;
top = temp;
}
}
Int pop()
{
if (top == NULL)
{
cout<<"underflow\n";
}
else
{
P = top;
top = top->next;
x = P->value;
delete(P);
return(x);
}
}
Void main()
{
int num, a;
cout<<"enter the decimal number\n";
cin>>num;
while (num > 0)
{
a = num % 2;
num = num / 2;
push(a);
}
P = top;
cout<<"resultant binary no:";
while(1)
{
if (top != NULL)
cout<<pop()<<"\t";
Else
break;
}
getch();
}
Parsing
Parsing breaks data into independent parts for processing.
For example a program parsing is breaking program into independent parts like keywords, identifiers, tokens and operators if any.
While writing any algebraic expression all of the parentheses should be properly paired. Unmatched parentheses in an algebraic expression pop errors such as missing of opening and closing parentheses.
We can use stacks for parsing so that all of the parentheses are paired properly.
Algorithm for parsing using stack is as follows.
Steps
| Algorithm(Parsing) | Description |
1
1.1 1.2
1.2.1 1.3
1.3.1
1.3.1.1
1.3.1.2 | While(1) { Read character If(character is an opening parenthesis) { Push(stack.character) Else { If(character is an closing parenthesis) { If(emptystack) Print(“Closing parenthesis not matched”) Else Pop(stack.token) } } } }
|
Accept character from user If character is an opening parenthesis then push character in stack
If character is an closing parenthesis and if stack is empty then Closing parenthesis not matched If character is an closing parenthesis and if stack is not empty then pop its matching opening parenthesis from stack |
2 | If(!emptystack(stack)) Print(“opening parenthesis not matched”); | If stack is not empty then opening parentheses not matched. |
Expression Evaluation
An expression can be represented in one of the following forms.
Infix: Infix expression has operator between operands. Eg. A + B
Prefix: Prefix expression has operator before operands. Eg. + A B
Postfix: Postfix expression has operator after operands. Eg. A B +
Evaluation of an Infix Expression:
Infix expressions are always evaluated from left to right. While evaluating it we must take care of operator precedence.
Following table shows priority of operators in C++.
According to above table – and ! have highest priority and logical OR has least priority. If an expression consists of operators with same priority(*,/,%)then evaluation is performed from left to right. If expression consists of parentheses then they are given top priority. Innermost parentheses are evaluated first.
Eg. Evaluate following infix expression
A / B – C + D * E. Given A=4,B=2,C=1,D=5,E=6
Considering above rules infix expression becomes.
((A / B) – C) + (D * E) Putting values in it
((4/2)-1)+(5*6)
(2-1)+(5*6)
1+30
31(Output)
Evaluation of prefix expression
Prefix expression has operator before operands. Prefix expression is always evaluated from right to left.
Eg. + 1 * 2 3
Evaluating from right to left, first operator we come across is ‘*’.so evaluate 2*3.so now expression becomes
+1 6
Again start evaluating from right to left. Next operator is +.
Add 1 and 6. So final output is 7.
Evaluation of prefix expression using Stack
Steps for Evaluation of prefix expression using Stack are as follows.
Accept prefix expression from user
Scan the expression from right to left
If token is an operand then push it in a stack.
If token is an operator then pop corresponding operands and perform operation.
Push result in stack.
Move to next token
Repeat steps 3 to 6 till the end of prefix expression.
Eg. -*+5 3 1 6
Prefix Input |
Stack |
Operand 1 |
Operand 2 |
Output |
Description |
-* 5 3 + 1 6
|
| - | - | - | Initially stack is empty. Evaluate expression from right to left. |
-* 5 3 + 1
|
| - | - | - | First token is an operand hence push operand 6 in stack |
-* 5 3 +
|
| - | - | - | Next token is again operand hence push operand 1 in stack |
-* 5 3 |
|
1 |
6 |
7 |
Next token is operator +, hence pop 1 and 6 and perform addition. Result is 7 .Push it in to stack
|
-* 5 |
| - | - | - | Next token is 3. Push it into stack.
|
-*
|
| - | - | - | Next token is 5. Push it into stack.
|
- |
| 5 | 3 | 15 | Next token is operator *, hence pop 5 and 3 and perform multiplication. Result is 15 .Push it in to stack
|
|
| 15 | 7 | 8 | Next token is operator -, hence pop 15 and 7 and perform subtraction. Result is 8 .Push it in to stack
|
Eg. 2: Evaluate the following prefix expression using stack for A= 16, B= 2, C=3, D=10, and E=4.Prefix Expression is
-+/A^BC*DE*AC
Prefix Input |
Stack |
Op 1 |
Op 2 |
Output |
Description |
-+/A^BC*DE*AC |
| - | - | - | Initially stack is empty. Evaluate expression from right to left. |
-+/A^BC*DE*A
|
| - | - | - | First token is an operand C hence push operand 3 in stack
|
-+/A^BC*DE* |
| - | - | - | Next token is an operand A hence push operand 16 in stack |
-+/A^BC*DE |
|
16 |
3 |
48 |
Next token is operator *, hence pop 3 and 16 and perform multipliaction. Result is 48 .Push it in to stack
|
-+/A^BC*D |
| - | - | - | Next token is E. Push it into stack.
|
-+/A^BC* |
| - | - | - | Next token is D. Push it into stack.
|
-+/A^BC |
| 10 | 4 | 40 | Next token is operator *, hence pop 4 and 10 and perform multiplication. Result is 40 .Push it in to stack
|
-+/A^B |
| - | - | - |
Next token is C. Push it into stack
|
-+/A^ |
| - | - | - |
Next token is B. Push it into stack
|
-+/A
|
| 2 | 3 | 8 | Next token is operator ^, hence pop 2 and 3 and perform ^. Result is 8 .Push it into stack.
|
-+/
|
| - | - | - | Next token is A. Push it into stack
|
-+ |
| 16 | 8 | 2 | Next token is operator /, hence pop 16 and 8 and perform /. Result of 16/8 is 2 .Push it into stack.
|
- |
| 2 | 40 | 42 | Next token is operator +, hence pop 40 and 2 and perform +. Result of 40+2 is 42 .Push it into stack. |
|
|
42 |
48 |
-6 |
Next token is operator -, hence pop 42 and 48 and perform - . Result of 42-48 is -6 .Push it into stack. |
Hence final result is -6.
*****program for prefix expression evaluation.***
#include <iostream.h>
#include <conio.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
Template <class TYPE>//class template
Class stack
{
Private:
TYPE *a;
int top,max;
Public:
stack()
{
max = 50;
a = new TYPE[max];
top = 0;
}
stack(int n)
{
max = n + 1;
a = new TYPE[max];
top= 0;
}
~stack()
{
delete a;
}
friend void push(stack &,TYPE);// member functions for stack
friend TYPE pop(stack &);
friend int isEmpty(stack);
};
Template <class TYPE>
Void push(stack <TYPE> &s, TYPE x)
{
if(s.top != s.max)
{
s.top++;
s.a[s.top] = x;
}
Else
cout << "\nStack Overflow.";
}
Template <class TYPE>
TYPE pop(stack <TYPE> &s)
{
TYPE temp;
if(s.top != 0)
{
temp = s.a[s.top];
s.top--;
return temp;
}
Else
{
Temp = -999;
return temp;
}
}
Template <class TYPE>
Int isEmpty(stack <TYPE> s)
{
if(s.top == 0)
Return 1;
Else
return 0;
}
Int main()
{
Char prefix[30],b[2];
Int i = 0;
Float e;
cout << "Enter a Prefix Expression,\n";
prefix[i - 1] ='\0';
While(prefix[i-1] != '\n')
prefix[i++] = getchar();// prefix expression
Stack <float> O(50); //call constructor to create stack
Float value,operand1,operand2;
Int j = i - 2,pos,k;
while(j >= 0)
{
pos = 0;
if(prefix[j] >= '0' && prefix[j] <= '9')
{
b[0] = prefix[j]; // Save Prefix[j] to b
i = j - 1;
k = 1;
if(prefix[j-1] != ' ') //Check for next character, If not Space
{
while(prefix[i] != ' ') //While space is not found
{
b[k++] = prefix[i--]; //Save Prefix[i] to b
pos++; //Increase Position
}
pos += 2;//At Last Increase Position by 2 to Skip Space
}
else //If a Single Character
pos = 2; //Skip Space
b[k] = '\0'; //End String temp
strrev(b);
x = atof(b); //Convert string b to float and store to x
push(O,x); //Push to stack
}
else if(prefix[j] == '+' || prefix[j] == '-' || prefix[j] == '*' || prefix[j] == '/' || prefix[j] == '^' ) // check for operators
{
operand1 = pop(O);
if(operand1 == -999)
break;
if(prefix[j] == '+' || prefix[j] == '-' || prefix[j] == '*' || prefix[j] == '/' || prefix[j] == '^')
{
operand2 = pop(O);
if(operand2 == -999)
break;
}
if(prefix[j] == '+')
value = operand1 + operand2;
if(prefix[j] == '-')
value = operand1 - operand2;
if(prefix[j] == '*')
value = operand1 * operand2;
if(prefix[j] == '/')
{
if(operand2 != 0)
value = operand1 / float(operand2); //Cast one operand to float
else
{
cout << "\nError ! Cannot Divide by Zero";
getch();
return 0;
}
}
if(prefix[j] == '^')
value = pow(operand1,operand2);
push(O,value);
pos = 2;
}
else
{
cout << "\nError : Illegal Character";
getch();
return 0;
}
j -= pos;
}
Float output = pop(O);
if(output == -999 || !isEmpty(O)) //If Underflow Condition or stack is not empty,
{
cout << "\nError : The Given Prefix Expression is Not Valid.";
getch();
return 0;
}
Else
cout << "\nOutput = " << Output;
getch();
Return 0;
}
Evaluation of Postfix expression
Postfix expression has operator after operands. Postfix expression is evaluated from left to right.
Eg.6 4 2 * +
Evaluating from left to right first operator we come across is ‘*’.so evaluate 4*2.so now expression becomes
6 8 +. Again start evaluating from left to right. Next operator is +. Add 6 and 8. So final output is 14.
Evaluation of postfix expression using Stack
Steps for Evaluation of postfix expression using Stack are as follows.
Accept postfix expression from user
Scan the expression from left to right
If token is an operand then push it in a stack.
If token is an operator then pop corresponding operands and perform operation.
Store result in stack.
Move to next token
Repeat steps 3 to 6 till the end of postfix expression.
Eg. : 623+-382/+*2^3+
Postfix Input
| Stack | Op1 | Op2 | Output | Description |
623+-382/+*2^3+
|
| - | - | - | Initially stack is empty. Evaluate expression from left to right. |
23+-382/+*2^3+
|
| - | - | - | First token is an operand 6. Push it into stack. |
3+-382/+*2^3+
|
| - | - | - | Next token is an operand 2. Push it into stack.
|
+-382/+*2^3+ |
| - | - | - | Next token is an operand 3. Push it into stack.
|
-382/+*2^3+
|
| 2 | 3 | 5 | Next token is operator +, hence pop 2 and 3 and perform +. Result of 2+3 is 5 .Push it into stack. |
382/+*2^3+
|
| 6 | 5 | 1 | Next token is operator -, hence pop 5 and 6 and perform -. Result of 6-5 is 1 .Push it into stack.
|
82/+*2^3+
|
| - | - | - | Next token is an operand 3. Push it into stack.
|
2/+*2^3+
|
| - | - | - | Next token is an operand 8. Push it into stack.
|
/+*2^3+
|
| - | - | - |
Next token is an operand 2. Push it into stack.
|
+*2^3+
|
| 8 | 2 | 4 | Next token is operator /, hence pop 2 and 8 and perform /. Result of 8/2 is 4 .Push it into stack.
|
*2^3+
|
| 3 | 4 | 7 | Next token is operator +, hence pop 4 and 3 and perform +. Result of 3+4 is 7 .Push it into stack.
|
2^3+
|
| 1 | 7 | 7 | Next token is operator *, hence pop 7 and 1 and perform *. Result of 1*7 is 7 .Push it into stack.
|
^3+ |
| - | - | - | Next token is an operand 2. Push it into stack.
|
3+
|
| 7 | 2 | 49 | Next token is operator ^, hence pop 2 and 7 and perform ^. Result of 7^2 is 49 .Push it into stack.
|
+ |
| - | - | - | Next token is an operand 3. Push it into stack.
|
|
|
49
|
3 |
52 | Next token is operator +, hence pop 3 and 49 and perform +. Result of 49+3 is 52 .Push it into stack.
|
Hence final result is 52.
Eg: Evaluate the following postfix expression and show stack after every step in tabular form. Given A= 5, B= 6, C=2, D=12, and E=4.POSTfix Expression is
ABC+*DE\-
Postfix Input
| Stack | Op1 | Op2 | Output | Description |
ABC+*DE\- |
| - | - | - | Initially stack is Empty. Evaluate expression from left to right. |
BC+*DE\- |
| - | - | - | First token is an operand A i.e.5. Push it into stack.
|
C+*DE\- |
| - | - | - | Next token is an operand B i.e.6. Push it into stack.
|
+*DE\-
|
| - | - | - | Next token is an operand C i.e.2. Push it into stack.
|
*DE\-
|
| 6 | 2 | 8 | Next token is operator +, hence pop 2 and 6 and perform +. Result of 6+2 is 8 .Push it into stack.
|
DE\- |
| 5 | 8 | 40 | Next token is operator *, hence pop 8 and 5 and perform *. Result of 8*5 is 40 .Push it into stack.
|
E\-
|
| - | - | - | Next token is an operand D i.e.12. Push it into stack.
|
\-
|
| - | - | - | Next token is an operand E i.e.4. Push it into stack.
|
- |
| 12 | 4 | 3 | Next token is operator \, hence pop 4 and 12 and perform \. Result of 12\4 is 3 .Push it into stack.
|
|
| 40 | 3 | 37 | Next token is operator -, hence pop 3 and 40 and perform -. Result of 40-3 is 37 .Push it into stack.
|
Hence final output is 37.
*******Program to evaluate Postfix expression********
#include <iostream.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
# define int MAX = 50 ;
Class stack
{
Private :
Int A[MAX] ;
Int top, y ;
Char *s ;
Public :
Stack( ) ;
Void exprn ( char *str ) ;
Void push ( int x ) ;
Int pop( ) ;
Void calculate( ) ;
Void display( ) ;
} ;
Stack :: stack( )
{
Top = -1 ;
}
Void stack :: exprn ( char *str )
{
s = str ;
}
Void stack :: push ( int x )
{
If ( top == MAX - 1 )
Cout << endl << "Stack is full" ;
Else
{
Top++ ;
A[top] = x ;
}
}
Int stack :: pop( )
{
If ( top == -1 )
{
Cout << endl << "Stack is empty" ;
Return NULL ;
}
Int data = A[top] ;
Top-- ;
Return data ;
}
Void stack :: calculate( )
{
Int n1, n2, n3 ;
While ( *s )
{
If ( *s == ' ' || *s == '\t' )
{
s++ ;
Continue ;
}
If ( isdigit ( *s ) )
{
y = *s - '0' ;
Push ( y ) ;
}
Else
{
n1 = pop( ) ;
n2 = pop( ) ;
Switch ( *s )
{
Case '+' :
n3 = n2 + n1 ;
Break ;
Case '-' :
n3 = n2 - n1 ;
Break ;
Case '/' :
n3 = n2 / n1 ;
Break ;
Case '*' :
n3 = n2 * n1 ;
Break ;
Case '%' :
n3 = n2 % n1 ;
Break ;
Case '^' :
n3 = pow ( n2 , n1 ) ;
Break ;
Default :
Cout << "Unknown operator" ;
Exit ( 1 ) ;
}
Push ( n3 ) ;
}
s++ ;
}
}
Void stack :: display( )
{
y = pop ( ) ;
Cout << "Result is: " << y ;
}
Void main( )
{
Char C[MAX] ;
Cout << "\nEnter postfix expression to be evaluated : " ;
Cin.getline ( C, MAX ) ;
Stack o ;
o.exprn ( C ) ;
o.calculate( ) ;
o.display( ) ;
}
Expression conversion
Expression conversion is of following types
- Infix to Postfix
- Infix to Prefix
- Postfix to Infix
- Postfix to prefix
- Prefix to Infix
- Prefix to Postfix
Infix to Postfix
Manual Transformation
Infix expression can be manually converted to postfix in following steps.
Fully parenthesize the infix expression considering operator precedence. There should be one set of parentheses for each operator.
Evaluate innermost expression first. Replace right parenthesis with corresponding operator.
Remove left parentheses.
Eg. X+Y/Z
Step 1: (X+(Y/Z))
Step 2: (X+(YZ/)
(X(YZ/+
Step 3: XYZ/+
Stack Transformation
Infix expression can be converted to postfix using stack in following steps.
Initialize an empty stack.
While not to end of infix expression
Scan the expression from left to right.
Get the input token in the infix expression.
If the token is
A left parenthesis then push it onto the stack
A right parenthesis then Pop and display stack elements until a left parenthesis is encountered.
Note: Do not display parenthesis. Parenthesis has least priority in stack but highest priority when in input expression.
An operator: If the stack is empty or input token has higher priority than the top stack, push onto the stack. Otherwise, pop and display the top stack element. Repeat the comparison of input token with the new top stack element.
An operand: Just display it.
When end of infix expression is reached, pop and display stack elements until the stack is empty.
Eg1. 4+5*9/1
Infix | Stack | Postfix | Description |
4+5*9/1 |
|
| Initially stack is empty. Scan expression from left to right. |
+5*9/1 |
| 4
| First token is an operand 4 so add to postfix expression. |
5*9/1 |
| 4 | Next token is operator + and stack is empty so push it into stack |
*9/1
|
| 45 | Next token is an operand 5 so add to postfix expression.
|
9/1
|
| 45 | Next token is operator *.Compare * with +. * has higher precedence over + so push it to stack. |
/1 |
| 459 | Next token is an operand 9 so add to postfix expression.
|
1 |
| 459* | Next token is operator /.Compare / with *. * has higher precedence over / so pop it from stack and push /.
|
|
| 459*1 | Next token is an operand 1 so add to postfix expression. |
|
| 459*1/+ | Pop remaining tokens from stack and add to postfix expression |
Hence Postfix expression is 459*1/+
Eg.2 Convert (2+4)*(5-6)/((1-2)*(9+2)) to Postfix expression.
Infix | Stack | Postfix |
(2+4)*(5-6)/((1-2)*(9+2)) |
|
|
2+4)*(5-6)/((1-2)*(9+2)) | ( |
|
+4)*(5-6)/((1-2)*(9+2)) | ( | 2 |
)*(5-6)/((1-2)*(9+2)) | (+ | 24 |
*(5-6)/((1-2)*(9+2)) |
| 24+ |
(5-6)/((1-2)*(9+2)) | * | 24+ |
5-6)/((1-2)*(9+2)) | *( | 24+ |
-6)/((1-2)*(9+2)) | *( | 24+5 |
6)/((1-2)*(9+2)) | *(- | 24+5 |
)/((1-2)*(9+2)) | *(- | 24+56 |
/((1-2)*(9+2)) | * | 24+56- |
((1-2)*(9+2)) | / | 24+56-* |
(1-2)*(9+2)) | /( | 24+56-* |
1-2)*(9+2)) | /(( | 24+56-* |
-2)*(9+2)) | /(( | 24+56-*1 |
2)*(9+2)) | /((- | 24+56-*1 |
)*(9+2)) | /((- | 24+56-*12 |
*(9+2)) | /( | 24+56-*12- |
(9+2)) | /(* | 24+56-*12- |
9+2)) | /(*( | 24+56-*12- |
+2)) | /(*( | 24+56-*12-9 |
2)) | /(*(+ | 24+56-*12-9 |
)) | /(*(+ | 24+56-*12-92 |
) | /(* | 24+56-*12-92+ |
| / | 24+56-*12-92+* |
|
| 24+56-*12-92+*/ |
Eg.3: Convert the following arithmetic expression into postfix
A+(B*C-(D/E-F)*G)*H
Infix | Stack | Postfix |
A+(B*C-(D/E-F)*G)*H
|
|
|
+(B*C-(D/E-F)*G)*H |
| A |
(B*C-(D/E-F)*G)*H | + | A |
B*C-(D/E-F)*G)*H | +( | A |
*C-(D/E-F)*G)*H | +( | AB |
C-(D/E-F)*G)*H | +(* | AB |
-(D/E-F)*G)*H | +(* | ABC |
(D/E-F)*G)*H | +(- | ABC* |
D/E-F)*G)*H | +(-( | ABC* |
/E-F)*G)*H | +(-( | ABC*D |
E-F)*G)*H | +(-(/ | ABC*D |
-F)*G)*H | +(-(/ | ABC*DE |
F)*G)*H | +(-(- | ABC*DE/ |
)*G)*H | +(-(- | ABC*DE/F |
*G)*H | +(- | ABC*DE/F- |
G)*H | +(-* | ABC*DE/F- |
)*H | +(-* | ABC*DE/F-G |
*H | + | ABC*DE/F-G*- |
H | +* | ABC*DE/F-G*-H |
| +* | ABC*DE/F-G*-H |
|
| ABC*DE/F-G*-H*+ |
Eg 4. Convert the following expression into postfix.
(A+B)*D+E/(F+A*D)+C
A*(B+C)/D-G
1. (A+B)*D+E/(F+A*D)+C
Infix | Stack | Postfix |
(A+B)*D+E/(F+A*D)+C
|
|
|
A+B)*D+E/(F+A*D)+C | ( |
|
+B)*D+E/(F+A*D)+C | ( | A |
B)*D+E/(F+A*D)+C | (+ | A |
)*D+E/(F+A*D)+C | (+ | AB |
*D+E/(F+A*D)+C |
| AB+ |
D+E/(F+A*D)+C | * | AB+ |
+E/(F+A*D)+C | * | AB+D |
E/(F+A*D)+C | + | AB+D* |
/(F+A*D)+C | + | AB+D*E |
(F+A*D)+C | +/ | AB+D*E |
F+A*D)+C | +/( | AB+D*E |
+A*D)+C | +/( | AB+D*EF |
A*D)+C | +/(+ | AB+D*EF |
*D)+C | +/(+ | AB+D*EFA |
D)+C | +/(+* | AB+D*EFA |
)+C | +/(+* | AB+D*EFAD |
+C | +/ | AB+D*EFAD*+ |
C | + | AB+D*EFAD*+/+ |
| + | AB+D*EFAD*+/+C |
|
| AB+D*EFAD*+/+C+ |
2. A*(B+C)/D-G
Infix | Stack | Postfix |
A*(B+C)/D-G |
|
|
*(B+C)/D-G |
| A |
(B+C)/D-G | * | A |
B+C)/D-G | *( | A |
+C)/D-G | *( | AB |
C)/D-G | *(+ | AB |
)/D-G | *(+ | ABC |
/D-G | * | ABC+ |
D-G | / | ABC+* |
-G | / | ABC+*D |
G | - | ABC+*D/ |
| - | ABC+*D/G |
|
| ABC+*D/G- |
Hence postfix expression is ABC+*D/G-
*********PROGRAM FOR INFIX TO POSTFIX****************
#include <iostream.h>
#include <string.h>
#include <ctype.h>
#define int MAX = 50 ;
Class stack
{
Private :
Char S[MAX], A[MAX] ;
Char *s, *t ;
Int top ;
Public :
Stack( ) ;
Void exprn ( char *str ) ;
Void push ( char c ) ;
Char pop( ) ;
Void convert( ) ;
Int priority ( char c ) ;
Void display( ) ;
} ;
Stack :: stack( )
{
Top = -1 ;
Strcpy ( S, "" ) ;
Strcpy ( A, "" ) ;
t = S ;
s = "" ;
}
Void stack :: exprn ( char *str )
{
s = str ;
}
Void stack :: push ( char c )
{
If ( top == MAX )
Cout << "\nStack is full\n" ;
Else
{
Top++ ;
A[top] = c ;
}
}
Char stack :: pop( )
{
If ( top == -1 )
{
Cout << "\nStack is empty\n" ;
Return -1 ;
}
Else
{
Char x = A[top] ;
Top-- ;
Return x ;
}
}
Void stack :: convert( )
{
While ( *s )
{
If ( *s == ' ' || *s == '\t' )
{
s++ ;
Continue ;
}
If ( isdigit ( *s ) || isalpha ( *s ) )
{
While ( isdigit ( *s ) || isalpha ( *s ) )
{
*t = *s ;
s++ ;
t++ ;
}
}
If ( *s == '(' )
{
Push ( *s ) ;
s++ ;
}
Char opr ;
If ( *s == '*' || *s == '+' || *s == '/' || *s == '%' || *s == '-' || *s == '^' )
{
If ( top != -1 )
{
Opr = pop( ) ;
While ( priority ( opr ) >= priority ( *s ) )
{
*t = opr ;
t++ ;
Opr = pop( ) ;
}
Push ( opr ) ;
Push ( *s ) ;
}
Else
Push ( *s ) ;
s++ ;
}
If ( *s == ')' )
{
Opr = pop( ) ;
While ( ( opr ) != '(' )
{
*t = opr ;
t++ ;
Opr = pop( ) ;
}
s++ ;
}
}
While ( top != -1 )
{
Char opr = pop( ) ;
*t = opr ;
t++ ;
}
*t = '\0' ;
}
Int stack :: priority ( char c )
{
If ( c == '^' )
Return 3 ;
If ( c == '*' || c == '/' || c == '%' )
Return 2 ;
Else
{
If ( c == '+' || c == '-' )
Return 1 ;
Else
Return 0 ;
}
}
Void stack :: display( )
{
Cout << S ;
}
Void main( )
{
Char Y[MAX] ;
Stack O ;
Cout << "\nEnter an expression in infix form: " ;
Cin.getline ( Y, MAX ) ;
O.exprn ( Y ) ;
O.convert( ) ;
Cout << "\nThe postfix expression is: " ;
O.display( ) ;
}
Infix to Prefix
Manual Transformation
Infix expression can be manually converted to prefix in following steps.
Fully parenthesize the infix expression considering operator precedence. There should be one set of parentheses per operator.
Evaluate innermost expression first. Replace left parenthesis with corresponding operator.
Remove right parentheses.
Eg. X+Y/Z
Step 1 :(X+(Y/Z))
Step 2:(X+/YZ))
+X/YZ))
Step 3 :+X/YZ
Stack Transformation
Infix expression can be converted to prefix using stack in following steps.
Reverse the given infix expression.
Convert every opening bracket( into closing bracket ) and vice versa.
Convert the resultant expression into postfix form by following algorithm.
Initialize an empty stack.
While not to end of infix expression
Scan the expression from left to right.
Get the input token in the infix expression.
If the token is
a) A left parenthesis then push it onto the stack
b) A right parenthesis then Pop and display stack elements until a left parenthesis is encountered.
Note: Do not display parenthesis. Parenthesis has least priority in stack but highest priority when in input expression.
c) An operator: If the stack is empty or input token has higher priority than the top stack, push onto the stack. Otherwise, pop and display the top stack element. Repeat the comparison of input token with the new top stack element.
d) An operand: Just display it.
When end of infix expression is reached, pop and display stack elements until the stack is empty.
Reverse the resultant expression.
Eg. (A-(B/C))*((D*E)-F)
Step 1: Reverse the given expression
Original expression is (A-(B/C))*((D*E)-F) By reversing we get )F-)E*D((*))C/B(-A(
Step 2: Convert every opening bracket( into closing bracket ) and vice versa.
(F-(E*D))*((C/B)-A)
Step 3: Convert the resultant expression in postfix form
Infix | Stack | Postfix |
(F-(E*D))*((C/B)-A) |
|
|
F-(E*D))*((C/B)-A) | ( |
|
-(E*D))*((C/B)-A) | ( | F |
(E*D))*((C/B)-A) | (- | F |
E*D))*((C/B)-A) | (-( | F |
*D))*((C/B)-A) | (-( | FE |
D))*((C/B)-A) | (-(* | FE |
))*((C/B)-A) | (-(* | FED |
)*((C/B)-A) | (- | FED* |
*((C/B)-A) |
| FED*- |
((C/B)-A) | * | FED*- |
(C/B)-A) | *( | FED*- |
C/B)-A) | *(( | FED*- |
/B)-A) | *(( | FED*-C |
B)-A) | *((/ | FED*-C |
)-A) | *((/ | FED*-CB |
-A) | *( | FED*-CB/ |
A) | *(- | FED*-CB/ |
) | *(- | FED*-CB/A |
| * | FED*-CB/A- |
|
| FED*-CB/A-* |
Step 4: Reverse the postfix expression
*-A/BC-*DEF
Hence the prefix expression is *-A/BC-*DEF
Eg.2 4*(2-(6*3+4)*2)+1
Step 1: Step 1: Reverse the given expression
Original expression is 4*(2-(6*3+4)*2)+1
By reversing we get 1+)2*)4+3*6(-2(*4
Step 2: Convert every opening bracket( into closing bracket ) and vice versa.
1+(2*(4+3*6)-2)*4
Step 3: Convert the resultant expression in postfix form
Infix | Stack | Postfix |
1+(2*(4+3*6)-2)*4
|
|
|
+(2*(4+3*6)-2)*4 |
| 1 |
(2*(4+3*6)-2)*4 | + | 1 |
2*(4+3*6)-2)*4 | +( | 1 |
*(4+3*6)-2)*4 | +( | 12 |
(4+3*6)-2)*4 | +(* | 12 |
4+3*6)-2)*4 | +(*( | 12 |
+3*6)-2)*4 | +(*( | 124 |
3*6)-2)*4 | +(*(+ | 124 |
*6)-2)*4 | +(*(+ | 1243 |
)-2)*4 | +(*(+* | 1243 |
-2)*4 | +(*(+* | 12436 |
2)*4 | +(* | 12436*+ |
)*4 | +(- | 12436*+* |
*4 | +(- | 12436*+*2 |
4 | + | 12436*+*2- |
| +* | 12436*+*2- |
| +* | 12436*+*2-4 |
|
| 12436*+*2-4*+ |
Step 4: Reverse the postfix expression
+*4-2*+*63421
Hence the prefix expression is +*4-2*+*63421
***program to convert infix to prefix**************
#include <iostream.h>
#include <string.h>
#include <ctype.h>
#define int MAX = 50 ;
Class stack
{
Private :
Char S[MAX], A[MAX] ;
Char *s, *t ;
Int top, len ;
Public :
Stack( ) ;
Void exprn ( char *str ) ;
Void push ( char c ) ;
Char pop( ) ;
Void convert( ) ;
Int priority ( char c ) ;
Void display( ) ;
} ;
Stack :: stack( )
{
Top = -1 ;
Strcpy ( S, "" ) ;
Strcpy ( A, "" ) ;
Len = 0 ;
}
Void stack:: exprn ( char *str )
{
s = str ;
Strrev ( s ) ;
Len = strlen ( s ) ;
* ( S + len ) = '\0' ;
t = S + ( len - 1 ) ;
}
Void stack :: push ( char c )
{
If ( top == MAX - 1 )
Cout << "\nStack is full\n" ;
Else
{
Top++ ;
A[top] = c ;
}
}
Char stack :: pop( )
{
If ( top == -1 )
{
Cout << "Stack is empty\n" ;
Return -1 ;
}
Else
{
Char x = A[top] ;
Top-- ;
Return x ;
}
}
Void stack:: convert( )
{
Char opr ;
While ( *s )
{
If ( *s == ' ' || *s == '\t' )
{
s++ ;
Continue ;
}
If ( isdigit ( *s ) || isalpha ( *s ) )
{
While ( isdigit ( *s ) || isalpha ( *s ) )
{
*t = *s ;
s++ ;
t-- ;
}
}
If ( *s == ')' )
{
Push ( *s ) ;
s++ ;
}
If ( *s == '*' || *s == '+' || *s == '/' ||
*s == '%' || *s == '-' || *s == '^' )
{
If ( top != -1 )
{
Opr = pop( ) ;
While ( priority ( opr ) > priority ( *s ) )
{
*t = opr ;
t-- ;
Opr = pop( ) ;
}
Push ( opr ) ;
Push ( *s ) ;
}
Else
Push ( *s ) ;
s++ ;
}
If ( *s == '(' )
{
Opr = pop( ) ;
While ( ( opr ) != ')' )
{
*t = opr ;
t-- ;
Opr = pop ( ) ;
}
s++ ;
}
}
While ( top != -1 )
{
Opr = pop( ) ;
*t = opr ;
t-- ;
}
t++ ;
}
Int stack :: priority ( char c )
{
If ( c == '^' )
Return 3 ;
If ( c == '*' || c == '/' || c == '%' )
Return 2 ;
Else
{
If ( c == '+' || c == '-' )
Return 1 ;
Else
Return 0 ;
}
}
Void stack :: display( )
{
While ( *t )
{
Cout << " " << *t ;
t++ ;
}
}
Void main( )
{
Char C[MAX] ;
Stack O ;
Cout << "\nEnter an expression in infix form: " ;
Cin.getline ( C, MAX ) ;
O.exprn( C ) ;
O.convert( ) ;
Cout << "The Prefix expression is: " ;
O.display( ) ;
}
Postfix to Infix
Steps to convert postfix to infix are as follows
Scan the postfix expression from left to right.
If token is an operand push it into stack.
If token is an operator pop recent two operands. Form new subexpression with this operator and operands in infix form(operator between two operands).Place parentheses for subexpression to ensure proper order of evaluation in final expression.
Note: We place parenthesis only if it is required(operator in subexpression has lower precedence than operator used to merge two subexpressions ).Otherwise proper order of evaluation is maintained without any additional parentheses.
Push resulting subexpression in stack.
Move to next token.
Repeat steps 2 to 5 till the end of postfix expression.
Eg1.ab*cd*+e*
Postfix Expression | Stack | Description |
Ab*cd*+e* | Empty | Initially stack is empty |
b*cd*+e* | a | First token is operand hence push it to stack. |
*cd*+e* | a, b | Next token is an operand. Push it into stack. |
Cd*+e* | (a*b) | Next token is an operator ‘*’.Pop two recent operands(a,b) and form subexpression(a*b) in infix form. Place parentheses for Resultant subexpression(a*b).Push it into stack. |
d*+e* | (a*b), c | Next token is an operand c. Push it into stack |
*+e* | (a*b), c,d | Next token is an operand d. Push it into stack |
*+e* | (a*b), (c*d) | Next token is an operator ‘*’.Pop two recent operands(c,d) and form subexpression in infix form. Place parentheses for Resultant subexpression(c*d).Push it into stack. |
+e* | ((a*b)+ (c*d)) | Next token is an operator ‘+’.Pop two recent operands(a*b)and(c*d). Form subexpression in infix form. Place parentheses for Resultant subexpression((a*b)(c*d)).Push it into stack. |
e* | (a*b)+(c*d),e | Next token is an operand e. Push it into stack |
* | ((a*b)+(c*d))*e | Next token is an operator ‘*’.Pop two recent operands((a*b)+(c*d))and e. Form subexpression in infix form ((a*b)+(c*d))*e. Push it into stack. |
| ((a*b)+(c*d))*e |
|
Hence resultant infix expression is ((a*b)+(c*d))*e
Eg.2: Convert the following postfix expression to infix using stack.
Abcde^^*-
Postfix Expression | Stack | Description |
Abcde^^*- | Empty | Initially token is empty |
Bcde^^*- | A | Next token is an operand a. Push it into stack. |
Cde^^*- | a,b | Next token is an operand b. Push it into stack. |
De^^*- | a,b,c | Next token is an operand c. Push it into stack. |
e^^*- | a,b,c,d | Next token is an operand d. Push it into stack. |
^^*- | a,b,c,d,e | Next token is an operand e. Push it into stack. |
^*- | a,b,c,(d^e) | Next token is an operator ‘^’.Pop two recent operands(d)and(e). Form subexpression in infix form. Place parentheses for Resultant subexpression(d^e).Push it into stack. |
*- | a,b,c^(d^e) | Next token is an operator ‘^’.Pop two recent operands(c)and(d^e). Form subexpression in infix form. Push it into stack. |
- | a, b*c^(d^e) | Next token is an operator ‘*’.Pop two recent operands.Form subexpression in infix form. Push it into stack. |
| a-b*c^(d^e) | Next token is an operator ‘-’.Pop two recent operands. Form subexpression in infix form. Push it into stack. |
Hence resultant expression is a-b*c^(d^e)
Postfix to prefix
Postfix expression can be converted to prefix using following steps.
Scan the postfix expression from left to right.
If token is an operand push it into stack.
If token is an operator pop recent two operands. Form new subexpression with this operator and operands in prefix form(operator before two operands).
Push resulting subexpression in stack.
Move to next token.
Repeat step 2 to 5 till the end of postfix expression.
Eg.1: Convert the following postfix expression to prefix using stack.
Abcde^^*-
Postfix Expression | Stack | Description |
Abcde^^*- | Empty | Initially stack is empty |
Bcde^^*- | a | Next token is an operand a. Push it into stack. |
Cde^^*- | a,b | Next token is an operand b. Push it into stack. |
De^^*- | a,b,c | Next token is an operand c. Push it into stack. |
e^^*- | a,b,c,d | Next token is an operand d. Push it into stack. |
^^*- | a,b,c,d,e | Next token is an operand e. Push it into stack. |
^*- | a,b,c,^de | Next token is an operator ‘^’.Pop two recent operands(d)and(e). Form subexpression in prefix form. Push it into stack. |
*- | a,b,^c^de | Next token is an operator ‘^’.Pop two recent operands(c)and(^de). Form subexpression in prefix form. Push it into stack. |
- | a, *b^c^de | Next token is an operator ‘*’.Pop two recent operands.Form subexpression in prefix form. Push it into stack. |
| -a*b^c^de | Next token is an operator ‘-’.Pop two recent operands. Form subexpression in prefix form. Push it into stack. |
Hence resultant prefix expression is -a*b^c^de
Prefix to Infix
Steps to convert prefix to infix are as follows
Scan the prefix expression from right to left.
If token is an operand push it into stack.
If token is an operator pop recent two operands. Form new subexpression with this operator and operands in infix form(operator between two operands).Place parentheses for subexpression to ensure proper order of evaluation in final expression.
Note: We place parenthesis only if it is required(operator in subexpression has lower precedence than operator used to merge two subexpressions ).Otherwise proper order of evaluation is maintained without any additional parentheses.
Push resulting subexpression in stack.
Move to next token.
Repeat step 2 to 5 till the end of prefix expression.
Eg1. +/+AB-CDE
Prefix Expression | Stack | Description |
+/+AB-CDE | Empty | Initially stack is empty |
+/+AB-CD | E | Next token is an operand E. Push it into stack. |
+/+AB-C | E,D | Next token is an operand D. Push it into stack. |
+/+AB- | E,D,C | Next token is an operand C. Push it into stack. |
+/+AB | E,(C-D) | Next token is an operator ‘-’.Pop two recent operands(C)and(D). Form subexpression in infix form. Push it into stack. |
+/+A | E,(C-D),B | Next token is an operand B. Push it into stack. |
+/+ | E,(C-D),B,A | Next token is an operand A. Push it into stack. |
+/ | E,(C-D),(A+B) | Next token is an operator ‘+’.Pop two recent operands(A)and(B). Form subexpression in infix form. Push it into stack. |
+ | E,(A+B)/(C-D) | Next token is an operator ‘/’.Pop two recent operands(A+B)and(C+D). Form subexpression in infix form. Push it into stack. |
| (A+B)/(C-D)+E | Next token is an operator ‘+’.Pop two recent operands(A+B)/(C-D) and E. Form subexpression in infix form. Push it into stack. |
Hence resultant infix expression is (A+B)/(C-D)+E
Prefix to Postfix
Steps to convert prefix to postfix are as follows
Scan the prefix expression from right to left.
If token is an operand push it into stack.
If token is an operator pop recent two operands. Form new subexpression with this operator and operands in postfix form(operator after two operands).
Push resulting subexpression in stack.
Move to next token.
Repeat step 2 to 5 till the end of prefix expression.
Eg1. +/+AB-CDE
Prefix Expression | Stack | Description |
+/+AB-CDE | Empty | Initially stack is empty |
+/+AB-CD | E | Next token is an operand E. Push it into stack. |
+/+AB-C | E,D | Next token is an operand D. Push it into stack. |
+/+AB- | E,D,C | Next token is an operand C. Push it into stack. |
+/+AB | E,CD- | Next token is an operator ‘-’.Pop two recent operands(C)and(D). Form subexpression in postfix form. Push it into stack. |
+/+A | E,CD-,B | Next token is an operand B. Push it into stack. |
+/+ | E,CD-,B,A | Next token is an operand A. Push it into stack. |
+/ | E,CD-,AB+ | Next token is an operator ‘+’.Pop two recent operands(A)and(B). Form subexpression in postfix form. Push it into stack. |
+ | E,AB+/CD- | Next token is an operator ‘/’.Pop two recent operands(AB+)and(CD+). Form subexpression in postfix form. Push it into stack. |
| AB+/CD-E+ | Next token is an operator ‘+’.Pop two recent operandsAB+/CD- and E. Form subexpression in postfix form. Push it into stack. |
Hence resultant postfix expression is AB+/CD-E+
Time Complexities of operations on stack:
Push(), pop(), isEmpty() and peek() all take O(1) time. We do not run any loop in any of these operations.
Applications of stack:
- Balancing of symbols
- Infix to Postfix /Prefix conversion
- Redo-undo features at many places like editors, photoshop.
- Forward and backward feature in web browsers
- Used in many algorithms like Tower of Hanoi, tree traversals, stock span problem, histogram problem.
- Other applications can be Backtracking, Knight tour problem, rat in a maze, N queen problem and sudoku solver
- In Graph Algorithms like Topological Sorting and Strongly Connected Components
A Queue is a linear list in which data is inserted at one end called as rear and deleted from other end called as front. Queue removes elements in the same order in which they were inserted i.e. element inserted first is removed first. Hence they are called as First-in-First out( FIFO) data structure.
Imagine a queue of people waiting for a bus. The person in the front of queue will get a first chance to board a bus. The person at the rear will be last one to board a bus. Same case is of checkout line in a grocery store or a cafeteria, list of jobs to be processed by computer or a list of calls on mobile phone.Fig.1 shows queue of alphabets. Alphabets are added at rear and removed from front end.
A Front | B | C | D | E | F Rear |
Fig. Queue of alphabets
We will see queue with respect to an example. Imagine queue of alphabets with size of three. Initially queue is empty.
Front |
|
Rear |
Now let us add an element in a queue. So queue becomes
Front |
| A Rear |
Add one more element ’B’ in a queue. Since element can only be inserted at rear, A progresses through queue and B is inserted at rear. Now queue becomes
Front | A | B Rear |
Adding one more element ‘C’ in queue
A Front | B | C Rear |
Now queue is full. If we try to insert one more element in queue then queue overflow occurs.
Now remove elements from queue. Element in queue is always removed from front end. Currently ‘A’ is at front end and hence will be removed first.
B Front | C |
Rear |
Removing ‘B’ and ‘C’ we get
Front |
|
Rear |
Now queue is empty. If we try to remove elements from queue, queue underflow occurs.
Operations on Queue:
- Bool enqueue(TYPE in): Insert elements at rear of queue.
- Bool dequeue(TYPE & out): Remove elements from front of queue.
- Bool Front(TYPE& out): Determines element at the front of queue.
- Bool Rear(TYPE& in): Determines element at the rear of queue.
- Int Count():Determines total number of elements present in queue.
- Bool isEmpty():Determines if queue is empty.
- Bool isFull():Determines if queue is full.
Template <class TYPE>
Struct Node//Node declaration
{
TYPE value;//data in a node
};
Template <class TYPE> //class template for queue
Class Queue
{
Private:
Node<TYPE> * P;//pointer to node
Int count;// number of elements present in queue
Int max; // maximum queue size
Int front; //index of element at front
Int rear // index of element at rear
Public:
Queue(int size=50);
~Queue();
Bool enqueue(TYPE in);
Bool dequeue(TYPE& out);
Bool QFront(TYPE& out);
Bool QRear(TYPE& out);
Int QCount();
Bool isEmpty();
Bool isFull();
};
We will see array implementation for
- Linear Queue
- Circular Queue
Template <class TYPE>
Struct Node//Node declaration
{
TYPE value;//data in a node
};
Template <class TYPE> //class template for queue
Class Queue
{
Private:
Node<TYPE> * P;//pointer to node
Int count;// number of elements present in queue
Int max; // maximum queue size
Int front; //index of element at front
Int rear // index of element at rear
Public:
Queue(int size=50);
~Queue();
Bool enqueue(TYPE in);
Bool dequeue(TYPE& out);
Bool QFront(TYPE& out);
Bool QRear(TYPE& out);
Int QCount();
Bool isEmpty();
Bool isFull();
};
We will see array implementation for
- Linear Queue
- Circular Queue
We assume queue of size 7. Intially Queue is empty. So
Count=0
Front=rear=-1;
Max=7
- Enqueue: Insert element in queue
Steps | Algorithm: bool enqueue(TYPE in) | Description
|
1 | Template<class TYPE> Bool Queue<TYPE>::enqueue(TYPE in) { | Design function to insert element ‘in’ to queue. This function returns true if element is inserted successfully. |
2 | If(count==max) Return false | If queue is full then return false to indicate element cannot be inserted. |
3 | Rear++; | If queue is not full increment rear. |
4 | If(rear==max-1) Rear=0; | If rear is last element wrap to the first element of queue. |
5 | P[rear].value=in; | Insert data at rear |
6 | If(count==0) Front=0 | If count is 0 it means queue is empty. Set front pointer to 0. |
7 | Count++;
| Increment count |
8 | Return true } | Return true to indicate successful insertion of an element in queue. |
Let us add element to circular queue. After adding an element’10’ in queue
Count =1
Front=rear=0
Max=7
Add one more element ‘2’ to queue.
Count=2
Front=0
rear=1
Dequeue: Removes element from front of queue.
A priority queue is an ADT where every element has a "priority" associated with it. This priority determines the order in which they exit the queue. The elements with highest priority are removed before elements with low priority. If two elements have the same priority, they are removed according to their order in the queue.
Consider the scenario of jobs sent to a printer. These jobs are usually placed in a queue, so job that is submitted first will be printed first. But every time this is not feasible as some of the jobs are more important though they are submitted later. So these important jobs should have precedence over other jobs which are submitted earlier. Such kind of application requires priority queue.
The common operations on priority queue are
- Insert: Inserts element in priority queue. It is similar to enqueue operation of Queue.
- Delete: finds and removes the element from priority queue. It is similar to dequeue operation of Queue. The element removed is of highest priority.
Array implementation of Priority Queue:
All the functions are same as that of normal queue except dequeue as here element is deleted according to priority. We will look at dequeue function.
Let us assume array Q[] of size n.
TYPE dequeue ()
{
int max = 0;
// finding the index of the element with the highest priority
for (int i=0; i<n-1; i++)
{
if (Q[i] > Q[max])
{
max = i;
}
}
TYPE maxnum = Q[max];
size--;
Q[max] = Queue[n];
return maxnum;
delete maxnum;
}
*******program for priority queue**********8
#include<iostream>
#include<conio.h>
#include<process.h>
Using namespace std;
template <class TYPE>
Struct Node//Node declaration
{
TYPE value;//data in a node
};
Class Queue
{
Private:
Node<TYPE> * P;//
Int count;// number of elements present in queue
Int max; // maximum queue size
Int front; //index of element at front
Int rear // index of element at rear
Public:
Queue(int size=50)
{ max = x;
Front=-1;
Rear=-1;
Count=0
P = new TYPE[max];
}
~Queue();
Bool enqueue(TYPE in);
TYPE dequeue();
Bool isEmpty();
Bool isFull();
};
Template <class TYPE>
Bool Queue<TYPE>:: isEmpty()
{
Return (count==0);
}
Template <class TYPE>
Bool Queue<TYPE>::isFull()
{
Return (rear==(max-1));
}
Template <class TYPE>
Bool Queue<TYPE>:: enqueue(TYPE in)
{
If(isFull())
Return false;
Rear++;
P[rear].value=in;
Return true;
If(count==0)
Front=0;
Count++;
Return true;
}
Template <class TYPE>
TYPE Queue<TYPE>::deQueue()
{
If(isEmpty())
Cout<<”Queue is empty”;
int m = 0;
// finding the index of the item with the highest priority
for (int i=0; i<max-1; i++)
{
if (P[i].value > P[m].value)
{
m = i;
}
}
TYPE maxnum = P[m];
count--;
P[m] = P[max];
return maxnum;
delete maxnum;
}
Template <class TYPE>
Void Queue<TYPE>:: display()
{
For(int i=front;i<=rear;i++)
{
Cout<<P[i]<<" <-- ";
}
Cout<<endl;
}
}
Void main(){
Queue<int> Q; //create queue of integers
Int ch;
Int x,flag;
Do{
Cout<<"\nEnter your choice:\n1.enqueue\n2.dequeue\n3.isfull\n4.isempty\5.display\n6.exit"<<endl;
Cin>>ch;
Switch(ch){
Case 1:
Cout<<”Enter element to be inserted”;
Cin>>x;
Flag=Q.enqueue(x)
If(flag==0)
Cout<<"The queue is full"<<endl;
Else
Cout<<”element is inserted ";
Break;
Case 2:
TYPE T;
T=Q.dequeue();
Cout<<”Deleted element is”<<T;
Break;
Case 3:
Flag=Q.isFull();
If(flag==1)
Cout<<Queue is full<<endl;
Else
Cout<<"queue is not full"<<endl;
Break;
Case 4:
Flag=Q.isEmpty();
If(flag==1)
Cout<<Queue is empty<<endl;
Else
Cout<<"queue is not empty"<<endl;
Case 5:
Q.display();
Break;
Case 6:exit(1);
}
}while(ch);
Getch();
}
Queue operations may involve initializing or defining the queue, utilizing it, and then completely erasing it from the memory. Here we shall try to understand the basic operations associated with queues −
Enqueue() − add (store) an item to the queue.
Dequeue() − remove (access) an item from the queue.
Few more functions are required to make the above-mentioned queue operation efficient. These are −
Peek() − Gets the element at the front of the queue without removing it.
Isfull() − Checks if the queue is full.
Isempty() − Checks if the queue is empty.
In queue, we always dequeue (or access) data, pointed by front pointer and while enqueing (or storing) data in the queue we take help of rear pointer.
Let's first learn about supportive functions of a queue −
Peek()
This function helps to see the data at the front of the queue. The algorithm of peek() function is as follows −
Algorithm
Begin procedure peek
return queue[front]
End procedure
Implementation of peek() function in C programming language −
Example
Int peek() {
return queue[front];
}
Isfull()
As we are using single dimension array to implement queue, we just check for the rear pointer to reach at MAXSIZE to determine that the queue is full. In case we maintain the queue in a circular linked-list, the algorithm will differ. Algorithm of isfull() function −
Algorithm
Begin procedure isfull
if rear equals to MAXSIZE
return true
else
return false
endif
End procedure
Implementation of isfull() function in C programming language −
Example
Bool isfull() {
if(rear == MAXSIZE - 1)
return true;
else
return false;
}
Isempty()
Algorithm of isempty() function −
Algorithm
Begin procedure isempty
if front is less than MIN OR front is greater than rear
return true
else
return false
endif
End procedure
If the value of front is less than MIN or 0, it tells that the queue is not yet initialized, hence empty.
Here's the C programming code −
Example
Bool isempty() {
if(front < 0 || front > rear)
return true;
else
return false;
}
Enqueue Operation
Queues maintain two data pointers, front and rear. Therefore, its operations are comparatively difficult to implement than that of stacks.
The following steps should be taken to enqueue (insert) data into a queue −
Step 1 − Check if the queue is full.
Step 2 − If the queue is full, produce overflow error and exit.
Step 3 − If the queue is not full, increment rear pointer to point the next empty space.
Step 4 − Add data element to the queue location, where the rear is pointing.
Step 5 − return success.
Insert Operation
Sometimes, we also check to see if a queue is initialized or not, to handle any unforeseen situations.
Algorithm for enqueue operation
Procedure enqueue(data)
if queue is full
return overflow
endif
rear ← rear + 1
queue[rear] ← data
return true
End procedure
Implementation of enqueue() in C programming language −
Example
Int enqueue(int data)
if(isfull())
return 0;
rear = rear + 1;
queue[rear] = data;
return 1;
End procedure
Dequeue Operation
Accessing data from the queue is a process of two tasks − access the data where front is pointing and remove the data after access. The following steps are taken to perform dequeue operation −
Step 1 − Check if the queue is empty.
Step 2 − If the queue is empty, produce underflow error and exit.
Step 3 − If the queue is not empty, access the data where front is pointing.
Step 4 − Increment front pointer to point to the next available data element.
Step 5 − Return success.
Remove Operation
Algorithm for dequeue operation
Procedure dequeue
if queue is empty
return underflow
end if
data = queue[front]
front ← front + 1
return true
End procedure
Implementation of dequeue() in C programming language −
Example
Int dequeue() {
if(isempty())
return 0;
int data = queue[front];
front = front + 1;
return data;
}
References:
1. Algorithms, Data Structures, and Problem Solving with C++”, Illustrated Edition by Mark Allen Weiss, Addison-Wesley Publishing Company.
2. “How to Solve it by Computer”, 2nd Impression by R.G. Dromey, Pearson Education.
3. “Fundamentals of Data Structures”, Illustrated Edition by Ellis Horowitz, Sartaj Sahni, Computer Science Press.