Lab Solutions A-03
Lab Solutions A-03
Lab Solutions A-03
2.How do you differentiate linear and non- linear data structures, Also give some
examples of both data structures.
Linear Data Structures Non-Linear Data Structures
Each member element is connected to theNo set sequence of connecting all it’s
preceding and subsequent elements in a elements and each element can have
sequential order multiple paths to connect to other elements
Structure makes it possible to traverse in
Such data structures support multi-level
a single run and level storage and often cannot be traversed in
single run.
easy to implement Not easy to implement
computer memory is sequential for such more efficient in utilizing computer
data structures memory
Examples: Array, Stacks and Queue Example: Tree and Graphs
1. Let an array named LA consist of 4 elements 2,4,6 & 8. write down the code to
traverse (or print) all elements in the array
INPUT:
#include<iostream>
using namespace std;
void Traverse(int arr[],int size)
{
cout<<"Array is [";
for (int j=0;j<size;j++)
{
cout<<arr[j];
if(j==size-1)
{
cout<<"]"<<endl;
}
else if(j>=0 and j<size-1)
{
cout<<",";
}
}
}
int main()
{
int LA[4]={2,4,6,8};
Traverse(LA,4);
return 0;
}
OUTPUT:
Array is [2,4,6,8]
2. Use insertion algorithm to add an element (Give implementation)
i. 1 at index 0
ii. 5 at index 2
iii. 3 at index 4
INPUT:
#include<iostream>
using namespace std;
void Traverse(int arr[],int size)
{
cout<<"Array is [";
for (int j=0;j<size;j++)
{
cout<<arr[j];
if(j==size-1)
{
cout<<"]"<<endl;
}
else if(j>=0 and j<size-1)
{
cout<<",";
}
}
}
void Insertion(int arr[],int& no,int InsertingPosition,int
ElementToBeInserted)
{
int j=no-1;
while(j>=InsertingPosition)
{
arr[j+1]=arr[j];
j=j-1;
}
no=no+1;
arr[InsertingPosition]=ElementToBeInserted;
}
int main()
{
char choice;
int position,element;
int LA[4]={2,4,6,8};
int size=4;
Traverse(LA,size);
cout<<"Do you want to Insert another Element in the Array?Enter Y/N:";
cin>>choice;
while(choice=='Y' || choice=='y')
{
cout<<"Enter position to be inserted(0 to "<<size-1<<"):";
cin>>position;
cout<<"Enter element to be inserted(any integer):";
cin>>element;
if(position>=0 && position<=size-1)
{
Insertion(LA,size,position,element);
Traverse(LA,size);
}
else
{
cout<<"Enter a correct integer for position to be
inserted"<<endl;
}
cout<<endl;
cout<<"Do you want to Insert another Element in the Array?Enter
Y/N:";
cin>>choice;
}
return 0;
}
OUTPUT:
Array is [2,4,6,8]
Do you want to Insert another Element in the Array?Enter Y/N:y
Enter position to be inserted(0 to 3):0
Enter element to be inserted(any integer):1
Array is [1,2,4,6,8]
ALGORITHM:
1. Set j=N-1 k=index at which element
2. Repeat Steps 3 and 4 while j≥k will be inserted
3. array[j+1] =array[j] N=No of elements
4. j=j-1 ITEM=element that will be
5. array[k]=ITEM inserted
6. Set N=N+1
INPUT:
#include<iostream>
using namespace std;
OUTPUT:
Array is [1,2,5,4,3,6,8]
Enter position to be deleted(0 to 6):0
Array is [2,5,4,3,6,8]
Array is [1,2,5,4,3,6,8]
Enter position to be deleted(0 to 6):2
Array is [1,2,4,3,6,8]
Array is [1,2,5,4,3,6,8]
Enter position to be deleted(0 to 6):4
Array is [1,2,5,4,6,8]
5. If the size of given array is 4 then calculate the Time complexity of deletion algorithm
when ,
i. Delete element at the beginning of array
ii. Delete element at the end of array
iii.Delete element in the middle of array
ALGORITHM:
1. Set j=k k=index at which element will
2. Repeat Steps 3 and 4 while j<N-1 be deleted
3. array[j] =array[j+1] N=No of elements
4. j=j+1
5. Set N=N-1
}
void MakeList(int NoOfElements,int (&myArray)[])//correct way to pass
array by reference
{
int Element;
myArray[NoOfElements];
for(int i=0;i<NoOfElements;i++)
{
cout<<"Enter Element at index "<<i<<" :";
cin>>Element;
myArray[i]=Element;
}
}
void TraverseList(int Size,int arr[])
{
cout<<"List is [";
for (int j=0;j<Size;j++)
{
cout<<arr[j];
if(j==Size-1)
{
cout<<"]"<<endl;
}
else if(j>=0 and j<Size-1)
{
cout<<",";
}
}
int main()
{
int ElementNumber;
cout<<"Enter the number of elements in your list:";
cin>>ElementNumber;
cout<<endl;
int A[ElementNumber];
MakeList(ElementNumber,A);
cout<<endl;
char choice;
int ITEM;
cout<<"Do you want to start searching? (Y/N)";
cin>>choice;
while(choice=='y' || choice=='Y')
{
cout<<endl;
TraverseList(ElementNumber,A);
cout<<endl<<"Which element do you want to search for?";
cin>>ITEM;
LinearSearch(A,ElementNumber,ITEM);
cout<<endl<<"Do you want to continue searching ?(Y/N)";
cin>>choice;
}
return 0;
}
OUTPUT:
Enter the number of elements in your list:4
List is [2,4,6,8]
List is [2,4,6,8]
INPUT:
#include<iostream>
#include<cmath>
using namespace std;
for(int i=0;i<size;i++)
{
if(arr[i]==ElementToBeFound)
{
count++;
}
}
cout<<"Element "<<ElementToBeFound<<" occurs "<<count<<" times
"<<endl;
}
else
{
cout<<ElementToBeFound<<" is not present in the list!"<<endl;
}
}
void TraverseList(int size,int arr[])
{
cout<<"List is [ ";
for(int i=0;i<size;i++)
{
if(i==size-1)
{
cout<<arr[i]<<" ]"<<endl;
}
else
{
cout<<arr[i]<<" , ";
}
}
}
void Makelist(int size,int (&arr)[])
{
arr[size];
int element;
for(int i=0;i<size;i++)
{
cout<<"Enter element at index "<<i<<" : ";
cin>>element;
arr[i]=element;
}
}
int main()
{
int size,ITEM;
char choice;
cout<<"How many elements do you want in the list?";
cin>>size;
cout<<endl;
int A[size];
Makelist(size,A);
TraverseList(size,A);
cout<<endl;
cout<<"Do you want to start your search?";
cin>>choice;
while (choice=='y' || choice=='Y')
{
cout<<"Enter element you want to search:";
cin>>ITEM;
BinarySearch(size,A,ITEM);
cout<<endl<<"Do you want to continue your search?";
cin>>choice;
}
return 0;
}
OUTPUT:
How many elements do you want in the list?10
Binary Search
ALGORITHM:
1.[Initialize segment variables]
Set BEG=0,END=N-1 and MID=INT((BEG+END)/2)
2. Repeat Steps 3 and 4 while BEG ≤ END and DATA[MID]≠ITEM
3. If ITEM<DATA[MID] then
Set END=MID-1
Else N=Number of elements in Array/List
Set BEG=MID+1 ITEM=Element to be found
4. Set MID= INT((BEG+END)/2) BEG = Beginning Index
[End of Step 2 loop] END = Ending Index
5. If DATA[MID]=ITEM then MID = Middle Index
Set loc=MID DATA=Array
Else
Set loc=NULL
[End of If Structure]
6.Return loc
Worst Case Scenario
Element not present in the array OR Element present at index N-1
T(N)=C1log(N)
Big O notation is O(logN)
Please note that the base of the log is 2 due to every iteration being divided by 2
INPUT:
#include<iostream>
using namespace std;
void BubbleSort(int arr[],int sizeOfArray)
{
int flag=0;
for(int i=0;i<sizeOfArray-1;i++)
{
for(int j=0;j<sizeOfArray-1-i;j++)
{
if (arr[j]>arr[j+1])
{
int temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
flag=1;
}
}
if(flag==0)
{
break;
}
}
}
void Traverse(int arr[],int size)
{
cout<<" [";
for (int j=0;j<size;j++)
{
cout<<arr[j];
if(j==size-1)
{
cout<<"]"<<endl;
}
else if(j>=0 and j<size-1)
{
cout<<",";
}
}
}
void MakeArray(int (&arr)[],int size)
{
int Element;
arr[size];
for (int i=0;i<size;i++)
{
cout<<"Enter Element at index "<<i<<" : ";
cin>>Element;
arr[i]=Element;
}
}
int main()
{
int NumberOfElements;
cout<<"Enter number of elements of array:";
cin>>NumberOfElements;
int A[NumberOfElements];
MakeArray(A,NumberOfElements);
cout<<endl<<"Original Array : ";
Traverse(A,NumberOfElements);
BubbleSort(A,NumberOfElements);
cout<<endl<<"After Sorting : ";
Traverse(A,NumberOfElements);
return 0;
}
OUTPUT:
Enter number of elements of array:6
Enter Element at index 0 : 100
Enter Element at index 1 : 80
Enter Element at index 2 : 60
Enter Element at index 3 : 40
Enter Element at index 4 : 20
Enter Element at index 5 : 10
Generalization:
T(n)=T(n-k) + k(2n+2)
If k=n
T(n)=T(n-n) + n(2n+2)
T(n)=T(0) + 2n2+2n
T(n)= 2n2+2n
Hence Worst Case is O(n2)
INPUT:
#include<iostream>
#include<iostream>
using namespace std;
void BubbleSort_Recursive(int arr[],int endingIndex)
{
if(endingIndex==0)//if array has only one value
{
return; //do nothing
}
for(int i=0;i<endingIndex;i++)
{
if(arr[i]>arr[i+1])
{
int temp=arr[i];
arr[i]=arr[i+1];
arr[i+1]=temp;
}
}
BubbleSort_Recursive(arr,endingIndex-1);
}
void Traverse(int arr[],int SizeOfArray)
{
cout<<" [";
for(int i=0;i<SizeOfArray;i++)
{
if(i==SizeOfArray-1)
{
cout<<arr[i]<<" ]"<<endl;
}
else
{
cout<<arr[i]<<" , ";
}
}
}
void MakeArray(int (&arr)[],int size)
{
int Element;
arr[size];
for(int i=0;i<size;i++)
{
cout<<"Enter element for index "<<i<<" : ";
cin>>Element;
arr[i]=Element;
}
}
int main()
{
int size;
cout<<"Enter number of Elements in the Array:";
cin>>size;
int A[size];
MakeArray(A,size);
cout<<endl<<"Before Sorting : ";
Traverse(A,size);
BubbleSort_Recursive(A,size-1);//ending index is always one less
than size
cout<<endl<<"After Sorting : ";
Traverse(A,size);
return 0;
}
OUTPUT:
Enter number of Elements in the Array:6
Enter element for index 0 : 6
Enter element for index 1 : 7
Enter element for index 2 : 5
Enter element for index 3 : 3
Enter element for index 4 : 4
Enter element for index 5 : 9
Before Sorting : [6 , 7 , 5 , 3 , 4 , 9 ]
After Sorting : [3 , 4 , 5 , 6 , 7 , 9 ]
3. Select any other sorting algorithm and implement. Assume A[]={
9,7,5,11,12,2,14,3,10,6}
INPUT:
#include<iostream>
using namespace std;
void SelectionSort(int arr[],int size)
{
int MinimumValue,location;
for(int i=0;i<size-1;i++)
{
MinimumValue=arr[i];
location=i;
for(int j=i+1;j<size;j++)
{
if(arr[j]<MinimumValue)
{
MinimumValue=arr[j];
location=j;
}
}
//swap arr[i] and arr[location]after finding minimum value
int temp=arr[location];
arr[location]=arr[i];
arr[i]=temp;
}
}
void Traverse(int arr[],int size)
{
cout<<"[ ";
for(int i=0;i<size;i++)
{
if(i==size-1)
{
cout<<arr[i]<<" ]"<<endl;
}
else
{
cout<<arr[i]<<" , ";
}
}
}
void MakeArray(int (&arr)[],int size)
{
int Element;
arr[size];
for(int i=0;i<size;i++)
{
cout<<"Enter element for index "<<i<<" : ";
cin>>Element;
arr[i]=Element;
}
}
int main()
{
int size;
cout<<"Enter number of Elements in the Array:";
cin>>size;
int A[size];
MakeArray(A,size);
cout<<endl<<"Before Sorting : ";
Traverse(A,size);
SelectionSort(A,size);
cout<<endl<<"After Sorting : ";
Traverse(A,size);
return 0;
}
OUTPUT:
Enter number of Elements in the Array:10
Enter element for index 0 : 9
Enter element for index 1 : 7
Enter element for index 2 : 5
Enter element for index 3 : 11
Enter element for index 4 : 12
Enter element for index 5 : 2
Enter element for index 6 : 14
Enter element for index 7 : 3
Enter element for index 8 : 10
Enter element for index 9 : 6
Before Sorting : [ 9 , 7 , 5 , 11 , 12 , 2 , 14 , 3 , 10 , 6 ]
After Sorting : [ 2 , 3 , 5 , 6 , 7 , 9 , 10 , 11 , 12 , 14 ]
4. Analyze the two sorting algorithms (in 1 & 3) and determine
i) Best and Worst cases
ii)Calculate Worst and Best bounds
iii) Draw conclusion on the basis of their pros & cons.
i=2 2<2
WORST BOUND
For Bubble Sort,we will check conditions for both i and j loops hence
Worst Case would be O(n2)
For Selection Sort,we will check conditions for both i and j loops hence
Worst Case would be O(n2)
The Worst Bound for both Bubble Sort and Selection Sort is O(n2)
However, the best case for Bubble Sort is O(n) while O(n2) for Selection Sort.
Hence it is a better option to use Bubble Sort when the array/list is already sorted
In other cases , Selection Sort would be a better option as it has less number of
swaps comparative to Bubble Sort.
Lab 05 Stack Data Structure
1. Give implementations of Push & Pop Algorithms with underflow & Overflow exceptions
INPUT:
#include<bits/stdc++.h>
using namespace std;
class Stack
{
public:
int top;
int arr[SIZE];
Stack()//default constructor
{
top=-1;
for(int i=0;i<SIZE;i++)
{
arr[i]=0;
}
}
bool isEmpty()
{
if(top==-1)
{
return true;
}
else
{
return false;
}
}
bool isFull()
{
if(top==SIZE-1)
{
return true;
}
else
{
return false;
}
}
};
void Push(Stack& s1,int x)
{
if (s1.isFull())
{
cout<<"Stack Overflow"<<endl;
}
else
{
s1.top++;
s1.arr[s1.top]=x;
}
}
int Pop(Stack& s1)
{
if (s1.isEmpty())
{
cout<<"Stack Underflow"<<endl;
return 0;
}
else
{
int PoppedValue=s1.arr[s1.top];
s1.arr[s1.top]=0;
s1.top--;
return PoppedValue;
}
}
void Display(Stack& s1)
{
for(int i=SIZE-1;i>=0;i--)
{
cout<<" "<<s1.arr[i]<<" "<<endl;
}
}
int main()
{
Stack s1;
int option,value;
cout<<"Enter Option to Perform Operation:"<<endl;
cout<<"1.Push"<<endl;
cout<<"2.Pop"<<endl;
cout<<"3.Display"<<endl;
cout<<"4.Exit"<<endl;
cin>>option;
while(option!=4)
{
switch (option)
{
case 1:
cout<<"Push Operation Chosen"<<endl;
cout<<"Enter value to push:";
cin>>value;
Push(s1,value);
break;
case 2:
cout<<"Pop Operation Chosen"<<endl;
Pop(s1);
break;
case 3:
cout<<"Display Operation Chosen"<<endl;
Display(s1);
break;
case 4:
break;
default:
cout<<"Please Enter a valid option"<<endl;
break;
}
}
return 0;
}
OUTPUT:
Enter Option to Perform Operation:
1.Push
2.Pop
3.Display
4.Exit
1
Push Operation Chosen
Enter value to push:1
Complexity Analysis
-IF condition followed➔ step 1 followed
Since simple return statement, constant time complexity
POP ALGORITHM:
1.If (top = = -1) STACK= Name of stack
Print Underflow and Return ITEM=variable storing
2. Set ITEM= STACK [top] popped value
3. Set top=top-1
4. Return
Complexity Analysis
-IF condition followed➔ step 1 followed
Since simple return statement, constant time complexity
class Stack
{
public:
int top;
int arr[SIZE];
Stack()
{
top=-1;
for(int i=0;i<SIZE-1;i++)
{
arr[i]=0;
}
}
bool isEmpty()
{
if(top==-1)
{
return true;
}
else
{
return false;
}
}
bool isFull()
{
if(top==SIZE-1)
{
return true;
}
else
{
return false;
}
}
void Push(int value)
{
if(isFull())
{
cout<<"Stack Overflow"<<endl;
}
else
{
top++;
arr[top]=value;
}
}
char Pop()
{
if(isEmpty())
{
cout<<"Stack Underflow"<<endl;
return 0;
}
else
{
char PoppedValue=arr[top];
arr[top]=0;
top--;
return PoppedValue;
}
}
void Display()
{
for(int i=SIZE-1;i>=0;i--)
{
cout<<" "<<arr[i]<<" "<<endl;
}
}
};
void Output(Stack&s1)
{
Stack s2;
if(s2.isEmpty())
{
while (s1.isEmpty()==false)
{
s2.Push(s1.Pop());
}
}
while(s2.isEmpty()==false)
{
cout<< s2.Pop()<<" ";
}
}
int main()
{
Stack s1,s2;
char choice,character;
cout<<"Do you want to start pushing your items?(Y/N)";
cin>>choice;
while (choice=='y' || choice=='Y')
{
cout<<"Enter character to push:";
cin>>character;
s1.Push(character);
cout<<endl<<"Do you want to continue pushing?(Y/N)";
cin>>choice;
}
cout<<"Output: ";
Output(s1);
OUTPUT:
Do you want to start pushing your items?(Y/N)Y
Enter character to push:D
top1++;
if(top1==top2)
{
cout<<"Stack 1 Overflow"<<endl;
top1--;
}
else
{
arr[top1]=x;
}
}
void push2(int x)
{
top2--;
if(top1==top2)
{
cout<<"Stack 2 Overflow"<<endl;
top2++;
}
else
{
arr[top2]=x;
}
}
int pop1()
{
if(top1==-1)
{
cout<<"Stack 1 Underflow"<<endl;
return -1;
}
else
{
int poppedValue=arr[top1];
arr[top1]=0;
top1--;
return poppedValue ;
}
}
int pop2()
{
if(top2==size)
{
cout<<"Stack 2 Underflow"<<endl;
return -1;
}
else
{
int poppedValue=arr[top2];
arr[top2]=0;
top2++;
return poppedValue ;
}
}
void Display()
{
cout<<"Displaying the array...."<<endl;
for (int i=0;i<size;i++)
{
cout<<" "<<arr[i]<<" ";
}
cout<<endl;
}
};
int main()
{
int size,option,value;
cout<<"Input size of array:";
cin>>size;
TwoStacks TS(size);
do
{
cout<<"Enter an option to proceed.Enter 0 to exit"<<endl;
cout<<"1.Push in Stack 1"<<endl;
cout<<"2.Push in Stack 2"<<endl;
cout<<"3.Pop in Stack 1"<<endl;
cout<<"4.Pop in Stack 2"<<endl;
cout<<"5.Display"<<endl;
cin>>option;
switch (option)
{
case 0:
break;
case 1:
cout<<"Push in Stack 1 Operation Chosen"<<endl;
cout<<"Enter value to push:";
cin>>value;
TS.push1(value);
break;
case 2:
cout<<"Push in Stack 2 Operation Chosen"<<endl;
cout<<"Enter value to push:";
cin>>value;
TS.push2(value);
break;
case 3:
cout<<"Pop in Stack 1 Operation Chosen"<<endl;
cout<<"Popped value is "<< TS.pop1()<<endl;
break;
case 4:
cout<<"Pop in Stack 2 Operation Chosen"<<endl;
cout<<"Popped value is "<< TS.pop2()<<endl;
break;
case 5:
cout<<"Display Operation Chosen"<<endl;
TS.Display();
break;
default:
cout<<"Enter correct option"<<endl;
break;
}
cout<<endl;
} while (option!=0);
return 0;
}
OUTPUT:
Input size of array:4
Enter an option to proceed.Enter 0 to exit
1.Push in Stack 1
2.Push in Stack 2
3.Pop in Stack 1
4.Pop in Stack 2
5.Display
1
Push in Stack 1 Operation Chosen
Enter value to push:10
Answer : 37
ii. 2,3,^,5,2,2,^,*,12,6,/,-,+
Number Symbol Scanned STACK
1 2 2
2 3 23
3 ^ 8
4 5 85
5 2 852
6 2 8522
7 ^ 854
8 * 8 20
9 12 8 20 12
10 6 8 20 12 6
11 / 8 20 2
12 - 8 18
13 + 26
Answer : 26
2.Implement the algorithm to convert the following infix expression to equivalent
postfix form.
INPUT:
#include<bits/stdc++.h>
using namespace std;
bool isOperator(char CharacterEncountered)
{
if(CharacterEncountered=='+'||CharacterEncountered=='-
'||CharacterEncountered=='*'||CharacterEncountered=='/'||CharacterEnco
untered=='^')
{
return true;
}
else
{
return false;
}
}
int Precedence(char CharacterEncountered)
{
if(CharacterEncountered=='^')
{
return 3;//highest precedence
}
else if (CharacterEncountered=='*'||CharacterEncountered=='/')
{
return 2; //second highest precedence
}
else if(CharacterEncountered=='+'||CharacterEncountered=='-')
{
return 1;//lowest precedence
}
else
{
return -1;//for opening and closing bracket
}
}
string ConvertInfixToPostfix(stack<char> STACK,string infix)
{
string postfix;
for(int i=0;i<infix.length();i++)
{
if((infix[i]>='a'&& infix[i]<='z')||(infix[i]>='A'&&
infix[i]<='Z'))
{
postfix+=infix[i];
}
else if(infix[i]=='(')
{
STACK.push(infix[i]);
}
else if(infix[i]==')')
{
while((STACK.top()!='(')&&(!STACK.empty()))
{
char temp=STACK.top();
postfix+=temp;
STACK.pop();
}
if(STACK.top()=='(')
{
STACK.pop();
}
}
else if(isOperator(infix[i]))//you can also use else block
{
if(STACK.empty())//if no operators present
{
STACK.push(infix[i]);
}
else //precendence rule
{
if(Precedence(infix[i])>Precedence(STACK.top()))
{
STACK.push(infix[i]);
}
else
if((Precedence(infix[i])==Precedence(STACK.top()))&& (infix[i]=='^'))
{
STACK.push(infix[i]);
}
else
{
while((!STACK.empty())&&
(Precedence(infix[i])<=Precedence(STACK.top())))
{
char temp=STACK.top();
postfix+=temp;
STACK.pop();
}
STACK.push(infix[i]);
}
}
}
}
while (!STACK.empty())
{
postfix+=STACK.top();
STACK.pop();
}
return postfix;
}
int main()
{
string InfixExpression,PostfixExpression;
cout<<"Enter an Infix Expression:";
cin>>InfixExpression;
stack<char> stack;
PostfixExpression=ConvertInfixToPostfix(stack,InfixExpression);
cout<<endl<<"POSTFIX EXPRESSION:"<<PostfixExpression;
return 0;
}
OUTPUT:
Enter an Infix Expression:(A+(B*C-(D/E^F)*G)*H)
POSTFIX EXPRESSION:ABC*DEF^/G*-H*+
3.Implement Infix to Postfix Conversion algorithm to solve 2,3,^,5,2,2,^,*,12,6,/,-
,+ also discuss its worst bound.
ALGORITHM:
1. Add a “)” at the end of expression P
2. Scan Expression P from left to right and repeat steps 2 and 3 until “)” is
encountered
3. IF an operand is encountered, push it onto the STACK.
4. IF an operator Θ is encountered
a) pop two operands from the STACK ,A is the top element and B is the
next to top element
b) Evaluate A Θ B
c) Place result of b on top STACK
5.Return value on top of the STACK
WORST BOUND:
Only 1 loop to scan expression so worst case is O(n).
Where n is the number of elements in expression P.
INPUT:
#include<bits/stdc++.h>
using namespace std;
bool isOperator(char CharacterEncountered)
{
if(CharacterEncountered=='+'||CharacterEncountered=='-
'||CharacterEncountered=='*'||CharacterEncountered=='/'||CharacterEnco
untered=='^')
{
return true;
}
else
{
return false;
}
}
int SolvingPostfix(string PostfixExpression)
{
stack<int> STACK;
for(int i=0;i<PostfixExpression.length();i++)
{
if(PostfixExpression[i]==',')
{
continue;
}
else
if((PostfixExpression[i]>='0')&&(PostfixExpression[i]<='9'))
{
string DoubleDigit="";
int ITEM;
if((PostfixExpression[i+1]=='0')&&(PostfixExpression[i+1]<
='9'))
{
DoubleDigit+=PostfixExpression[i];
DoubleDigit+=PostfixExpression[i+1];
i+=1;
}
else
{
DoubleDigit+=PostfixExpression[i];
}
ITEM=stoi(DoubleDigit);
STACK.push(ITEM);
}
else if(isOperator(PostfixExpression[i]))//element is an
operator
{
int operand2=STACK.top();
STACK.pop();
int operand1=STACK.top();
STACK.pop();
switch (PostfixExpression[i])
{
case '+':
STACK.push(operand1+operand2);
break;
case '-':
STACK.push(operand1-operand2);
break;
case '*':
STACK.push(operand1*operand2);
break;
case '/':
STACK.push(operand1/operand2);
break;
case '^':
STACK.push(pow(operand1,operand2));
break;
}
}
}
return STACK.top();
}
int main()
{
string postfix="2,3,^,5,2,2,^,*,12,6,/,-,+";
int solution=SolvingPostfix(postfix);
cout<<solution<<endl;
return 0;
}
OUTPUT:
26
4.Write algorithm to solve prefix expression also give implementation.
ALGORITHM:
1. Add a “(” at the beginning of expression P
2. Scan Expression P from left to right and repeat steps 2 and 3 until “(” is
encountered
3. IF an operand is encountered, push it onto the STACK.
4. IF an operator Θ is encountered
a) pop two operands from the STACK,A is the top element and B is the
next to top element
b) Evaluate A Θ B
c) Place result of b on top STACK
5.Return value on top of the STACK
INPUT:
#include<bits/stdc++.h>
using namespace std;
switch (PrefixExpression[i])
{
case '+':
STACK.push(operand1+operand2);
break;
case '-':
STACK.push(operand1-operand2);
break;
case '*':
STACK.push(operand1*operand2);
break;
case '/':
STACK.push(operand1/operand2);
break;
case '^':
STACK.push(pow(operand1,operand2));
break;
}
}
}
return STACK.top();
}
int main()
{
string prefix;
cout<<"Enter expression in prefix form to evaluate :";
cin>>prefix;
int Solution=SolvingPrefix(prefix);
cout<<Solution<<endl;
return 0;
}
OUTPUT:
Enter expression in prefix form to evaluate : -+7*45+20
25
Lab 07 Queue Data Structure
1.Write Algorithms for Enqueue and dequeue operations in a circular queue, also
implement using an array.
ENQUEUE ALGORITHM:
1.IF ((front==0 and rear==SIZE-1) or(front=rear+1)) then
Write Overflow and Return
2.IF (front== -1) then
Set front=0 and rear=0;
3.ELSE IF (rear=SIZE-1) then
Set rear = 0
4. ELSE
Set rear = rear+1
5.Queue[rear]=ITEM
DEQUEUE ALGORITHM:
1.IF (front== -1) then
Write Underflow and Return
2.Set ITEM=Queue[front]
3.IF (front==rear) then
Set front = -1 and rear = -1;
4.ELSE IF (front==SIZE-1) then
Set front = 0
5. ELSE
Set front=front+1
INPUT:
#include<bits/stdc++.h>
using namespace std;
const int SIZE=3;
int Queue[SIZE];
int front=-1 ;
int rear=-1;
void Enqueue(int ElementToBeInserted)
{
if((front == 0 && rear == SIZE-1) || (front == rear+1))
{
cout<< " Queue Overflow "<<endl;
return;
}
if (front == -1)
{
front = 0;
rear = 0;
}
else
{
if (rear == SIZE- 1)
{
rear = 0;
}
else
{
rear = rear + 1;
}
}
Queue[rear] = ElementToBeInserted ;
}
void Dequeue()
{
if(front==-1)
{
cout<< " Queue Underflow "<<endl;
return;
}
Queue[front]=0;
if(front == rear)
{
front=-1;
rear=-1;
}
else
{
if(front==SIZE-1)
{
front=0;
}
else
{
front=front+1;
}
}
}
void Display()
{
for(int i=0;i<SIZE;i++)
{
cout<<" "<<Queue[i]<<" ";
}
}
int main()
{
int option,value;
INPUT:
#include<bits/stdc++.h>
using namespace std;
class CircularQueue
{
public:
int*array;
int front,rear,size;
CircularQueue(int N)//constructor
{
size=N;
front = -1;
rear = -1;
array = new int[size];
for(int i=0;i<size;i++)
{
array[i]=0;
}
}
void Enqueue(int ElementToBeInserted)
{
if((front == 0 && rear == size-1) || (front == rear+1))
{
cout<< " Queue Overflow "<<endl;
return;
}
if (front == -1)
{
front = 0;
rear = 0;
}
else
{
if (rear == size- 1)
{
rear = 0;
}
else
{
rear = rear + 1;
}
}
array[rear] = ElementToBeInserted ;
}
void Dequeue()
{
if(front==-1)
{
cout<< " Queue Underflow "<<endl;
return;
}
array[front]=0;
if(front == rear)
{
front=-1;
rear=-1;
}
else
{
if(front==size-1)
{
front=0;
}
else
{
front=front+1;
}
}
}
void Display()
{
for(int i=0;i<size;i++)
{
cout<<" "<<array[i]<<" ";
}
}
};
int main()
{
int NUMBER,option,value;
cout<<"Enter size of Queue:";
cin>>NUMBER;
CircularQueue q1(NUMBER);
while(option!=4)
{
switch (option)
{
case 1:
cout<<"Enqueue Operation Chosen"<<endl;
cout<<"Enter value to insert:";
cin>>value;
q1.Enqueue(value);
break;
case 2:
cout<<"Dequeue Operation Chosen"<<endl;
q1.Dequeue();
break;
case 3:
cout<<"Display Operation Chosen"<<endl;
q1.Display();
break;
case 4:
break;
default:
cout<<"Please Enter a valid option"<<endl;
break;
}
cout<<endl<<"Enter Option to Perform Operation:"<<endl;
cout<<"1.Enqueue"<<endl;
cout<<"2.Dequeue"<<endl;
cout<<"3.Display"<<endl;
cout<<"4.Exit"<<endl;
cin>>option;
}
return 0;
}
OUTPUT:
Enter size of Queue:3
Enter Option to Perform Operation:
1.Enqueue
2.Dequeue
3.Display
4.Exit
1
Enqueue Operation Chosen
Enter value to insert:1
3. Analyze circular queue {Enqueue & Dequeue} algorithms and identify Worst
time complexity with brief justification
(Algorithms written in Q1)
ENQUEUE ALGORITHM:
Worst Time for Enqueue Algorithm is O(1)
Because all conditional statements contain simple assignment statements with
constant time.
DEQUEUE ALGORITHM:
Worst Time for Dequeue Algorithm is O(1)
Because all conditional statements contain simple assignment statements with
constant time.
Lab 08 Recursive Algorithms
(Recursion)
1.Calculate the Time complexity of Fibonacci and factorial recursive algorithms,
Discuss their upper bound of both algorithms. Also give the implementation.
FIBONACCI ALGORITHM
Fib(N)
If (N<= 1) then
Return 1
ELSE
Return Fib(N-1)+Fib(N-2)
Time Complexity
Base Case is for N<=1 for which T(N) = 1 as one return statement
For the ELSE part……
T(N) = T(N-1) + T(N-2)+4
//because function is called with N-1 and N-2 as parameter
//4 because there is 1 return statement and three binary operations (+ , - and -)
Generalization
T(N) = 2k T(N-k) + (2k-1)C
INPUT:
#include<bits/stdc++.h>
using namespace std;
int Fibonacci(int Number)
{
if(Number<=1)
{
return 1;
}
else
{
return Fibonacci(Number-1)+Fibonacci(Number-2);
}
}
int main()
{
int n,fib;
cout<<"Enter number to generate the Nth Fibonacci Number:";
cin>>n;
fib=Fibonacci(n);
cout<<n<<"th Fibonacci Number : "<<fib;
return 0;
}
OUTPUT:
Enter number to generate the Nth Fibonacci Number:10
10th Fibonacci Number : 89
FACTORIAL ALGORITHM
Factorial(N)
If (N==0) then
Return 1
ELSE
Return N*Factorial(N-1)
Time Complexity
Base Case is for N=0 for which T(N) = 1 as one return statement
For the ELSE part……
T(N) = T(N-1)+3 //because function is called with N-1 as parameter
//3 because there is 1 return statement and two binary
// operations (+ and *)
T(N) = [T(N-2) +3] +3
T(N) = T(N-2) + 6
Generalization
T(N) = T(N-k) + 3k
int main()
{
int n,fact;
cout<<"Enter number to calculate Factorial of :";
cin>>n;
fact=Factorial(n);
cout<<"Factorial of "<<n<<" : "<<fact;
return 0;
}
OUTPUT:
Enter number to calculate Factorial of :4
Factorial of 4 : 24
2. Write iterative factorial and Fibonacci algorithms, also analyze the time
complexity.
FACTORIAL ALGORITHM:
Factorial(N)
1.If N==0 then
Return 1
2.Else
Set fact=1
For i=1 to i=N
fact=fact*i
Return fact
Time Complexity:
FIBONACCI ALGORITHM:
Fibonacci(N)
1.If N==1 then
Return 0
2. If N==2 then
Return 1
3.Set PreviousPreviousNumber = 0
4.Set PreviousNumber = 1
5. For i=1 to i=N
Set CurrentNumber = PreviousPreviousNumber + PreviousNumber
Set PreviousPreviousNumber = PreviousNumber
Set PreviousNumber = CurrentNumber
6.Return CurrentNumber
Time Complexity:
If condition
For N==1 time complexity is 2(Condition + return statement)
If condition
For N==2 time complexity is 2(Condition + return statement)
Else Condition
Statement 3 and Statement 4 have constant time complexities as they are simple
assignment statements
Statement 5 has a loop that runs for N times
Statement 6 has a simple return statement
Statement Operation Iteration Sub Total
3 1 1 1
4 1 1 1
5a(i<=N) 1 N-1 N-1
5b(i++) 1 N N
5c( 3 assignment statements) 3 N 3N
6 1 1 1
So time complexity is 5N+2
Worst Case is O(N)
Implementation
#include<bits/stdc++.h>
using namespace std;
int Fibonacci(int Number)
{
if (Number == 1) return 0;
if (Number== 2) return 1;
int prevPrev = 0;
int prev = 1;
int currentNumber;
for (int i = 1; i <= Number; i++) {
currentNumber = prevPrev + prev;
prevPrev = prev;
prev = currentNumber;
}
return currentNumber;
}
int main()
{
int n,fib;
cout<<"Enter number to generate the Nth Fibonacci Number:";
cin>>n;
fib=Fibonacci(n);
cout<<n<<"th Fibonacci Number : "<<fib;
return 0;
}
3.Write recursive algorithm for Tower of Hanoi Puzzle also calculate its upper
bound (also give implementation).
TOWER OF HANOI ALGORITHM
TOWER(N,BEG,AUX,END)
1.IF N=1 then
a) Write: BEG➔END
b) Return
2. ELSE
a) Call TOWER (N-1, BEG, END, AUX)
b) Write: BEG➔END
c) Call TOWER (N-1, AUX, BEG, END)
Time Complexity
Base Case is for N=1 for which T(N) = 2 as one return statement and one print
statement
For the ELSE part……
T(N) =2T(N-1)+1 //because function is called with N-1 as parameter two times
//1 because there is 1 print statement
T(N) = 2[2T(N-1) +1] +1
T(N) = 4T(N-2) + 2+1
Generalization
T(N) = 2k T(N-k) + (2k-1+2k-2 +2k-3+……..2+1)
T(1)=1
N-k should be equal to 1
So at k=N-1 recursive cycle ends
T(N) = 2N-1 T(N-(N-1)) + (2N-2+2N-3 +2N-4+……..2+1)
T(N) = 2N-1 T(1) + (2N-2+2N-3 +2N-4+……..2+1)
T(N) = 2N-1 + 2N-2+2N-3 +2N-4+……..2+1➔EQ 1
2T(N) = 2N + 2N-1+2N-2 +2N-3+……..2+1➔EQ 2
}
int main()
{
int pegs;
cout<<"Enter Number of pegs:";
cin>>pegs;
cout<<"Moving "<<pegs<<" pegs from Tower A to Tower C"<<endl;
TOWER(pegs,'A','B','C');
return 0;
}
OUTPUT:
Enter Number of pegs:3
Moving 3 pegs from Tower A to Tower C
Move top disk from A to C
Move top disk from A to B
Move top disk from C to B
Move top disk from A to C
Move top disk from B to A
Move top disk from B to C
Move top disk from A to C
4. Rewrite above algorithm using iterative logic calculate its time complexity.
ALGORITHM
1.Calculate the total number of moves required (pow(2,n)-1) where n is number of
disks
2.If number of disks (n) is even then interchange END pole and AUX pole
3.ELSE For i=1 to i=N repeat steps 4 to 6
4. IF (i%3==1)
Legal movement of top disk between BEG and END pole
5. IF (i%3==2)
Legal movement of top disk between BEG and AUX pole
6. IF (i%3==0)
Legal movement of top disk between AUX and END pole
Time Complexity
Worst Case is O(2N)
Implementation
#include<bits/stdc++.h>
using namespace std;
class Stack
{
unsigned size;
int top;
int* array;
public:
Stack(unsigned N)
{
size=N;
top=-1;
for(int i=0;i<size;i++)
{
array[i]=0;
}
}
bool isEmpty()
{
if (top==-1)
{
return true;
}
else
{
return false;
}
}
bool isFull()
{
if(top==size-1)
{
return true;
}
else
{
return false;
}
}
void push(int val)
{
if(isFull())
{
return;
}
else
{
top++;
array[top]=val;
}
}
int pop()
{
if(isEmpty())
{
cout<<"Stack Underflow"<<endl;
return 0;
}
else
{
int popValue=array[top];
array[top]=0;
top--;
return popValue;
}
}
};
void moveDisk(char fromPeg,char toPeg)
{
cout<<"Move top disk from "<<fromPeg<<" to "<<toPeg<<endl;
}
void LegalMovement(Stack BEG,Stack END,char beg,char end)
{
int pole1TopDisk=BEG.pop();
int pole2TopDisk=END.pop();
else if (i % 3 == 2)
LegalMovement(BEG, AUX, Beg, Aux);
else if (i % 3 == 0)
LegalMovement(BEG, END, Aux, End);
}
}
int main()
{
int pegs;
cout<<"Enter Number of pegs:";
cin>>pegs;
Stack BEG(pegs),END(pegs),AUX(pegs);
IterativeTOH(pegs,BEG,AUX,END);
Return 0;
}
OUTPUT:
Enter Number of pegs:3
Move top disk from A to C
Move top disk from A to B
Move top disk from C to B
Move top disk from A to C
Move top disk from B to A
Move top disk from B to C
Move top disk from A to C
Lab 09 Tree data structure
1. Construct a binary tree (initially empty) , insert nodes 15,10,20,25,8,12 with the
help of following definition of Node in BST
Struct BSTNode{
Int data;
BSTNode* left;
BSTNode* right; } BSTNode* rootPtr;
INPUT:
#include<bits/stdc++.h>
using namespace std;
struct BSTNode
{
int data;
BSTNode* left;
BSTNode* right;
BSTNode(int val)
{
data=val;
left=NULL;
right=NULL;
}
};
BSTNode* Insert(BSTNode* root,int val)
{
if(root==NULL)
{
return new BSTNode(val);
}
else if(val<root->data)
{
root->left=Insert(root->left,val);
}
else
{
root->right=Insert(root->right,val);
}
return root;
}
void inorder(BSTNode *root)
{
if(root==NULL)
{
return;
}
inorder(root->left);
cout<<root->data<<" ";
inorder(root->right);
}
int main()
{
BSTNode* rootPtr=NULL;
rootPtr=Insert(rootPtr,15);
rootPtr=Insert(rootPtr,10);
rootPtr=Insert(rootPtr,20);
rootPtr=Insert(rootPtr,25);
rootPtr=Insert(rootPtr,8);
rootPtr=Insert(rootPtr,12);
inorder(rootPtr);
cout<<endl;
return 0;
}
OUTPUT:
8 10 12 15 20 25
2. Delete One left-child-node and one right-child- node from above tree. Analyze
the change occur in the tree after deletion.
INPUT:
#include<bits/stdc++.h>
using namespace std;
struct BSTNode
{
int data;
BSTNode* left;
BSTNode* right;
BSTNode(int val)
{
data=val;
left=NULL;
right=NULL;
}
};
BSTNode* Insert(BSTNode* root,int val)
{
if(root==NULL)
{
return new BSTNode(val);
}
else if(val<root->data)
{
root->left=Insert(root->left,val);
}
else
{
root->right=Insert(root->right,val);
}
return root;
}
BSTNode* InorderSuccessor(BSTNode* root)
{
BSTNode* current=root;
while(current && current->left!=NULL)
{
current=current->left;
}
return current;
}
BSTNode* Delete(BSTNode* root,int key)
{
if(key<root->data)
{
root->left=Delete(root->left,key) ;
}
else if(key>root->data)
{
root->right=Delete(root->right,key) ;
}
else
{
//case 1 and case 2
if(root->left==NULL)
{
BSTNode* temp=root->right;
free(root);
return temp;
}
else if(root->right==NULL)
{
BSTNode* temp=root->left;
free(root);
return temp;
}
//case 3
BSTNode* temp=InorderSuccessor(root->right);
root->data=temp->data;
root->right=Delete(root->right,temp->data);
}
return root;
}
void inorder(BSTNode *root)
{
if(root==NULL)
{
return;
}
inorder(root->left);
cout<<root->data<<" ";
inorder(root->right);
}
int main()
{
BSTNode* rootPtr=NULL;
rootPtr=Insert(rootPtr,15);
rootPtr=Insert(rootPtr,10);
rootPtr=Insert(rootPtr,20);
rootPtr=Insert(rootPtr,25);
rootPtr=Insert(rootPtr,8);
rootPtr=Insert(rootPtr,12);
inorder(rootPtr);
cout<<endl;
rootPtr=Delete(rootPtr,12);
cout<<"After deleting 12 from the tree:";
inorder(rootPtr);
rootPtr=Delete(rootPtr,20);
cout<<endl<<"After deleting 20 from the tree:";
inorder(rootPtr);
return 0;
}
OUTPUT:
8 10 12 15 20 25
After deleting 12 from the tree:8 10 15 20 25
After deleting 20 from the tree:8 10 15 25
3. From the figure below, identify
i. root ➔A
ii. Height of tree ➔3
iii. Degree ➔3
iv. Size➔9
v. leaf node(s)➔D,E,F,G,I
Preorder: 2 7 2 6 5 11 5 9 4
Inorder: 2 7 5 6 11 2 5 4 9
Postorder: 2 5 11 6 7 4 9 5 2
2. Implement all three tree traversal algorithms , also determine the worst time
complexity.
WORST TIME COMPLEXITY
Preorder: O(N)
Inorder: O(N)
Postorder: O(N)
Where N is the size of Binary tree(Since we traverse all the nodes, we have to go
to every single node hence time is dependent on number of nodes.)
INPUT:
#include<bits/stdc++.h>
using namespace std;
struct BSTNode
{
int data;
BSTNode* left;
BSTNode* right;
BSTNode(int val)
{
data=val;
left=NULL;
right=NULL;
}
};
BSTNode* Insert(BSTNode* root,int val)
{
if(root==NULL)
{
return new BSTNode(val);
}
else if(val<root->data)
{
root->left=Insert(root->left,val);
}
else
{
root->right=Insert(root->right,val);
}
return root;
}
void preorder(BSTNode* root)
{
if(root==NULL)
{
return;
}
cout<<root->data<<" ";
preorder(root->left);
preorder(root->right);
}
void inorder(BSTNode *root)
{
if(root==NULL)
{
return;
}
inorder(root->left);
cout<<root->data<<" ";
inorder(root->right);
}
void postorder(BSTNode* root)
{
if(root==NULL)
{
return;
}
postorder(root->left);
postorder(root->right);
cout<<root->data<<" ";
}
int main()
{
BSTNode* rootPtr=NULL;
rootPtr=Insert(rootPtr,15);
rootPtr=Insert(rootPtr,10);
rootPtr=Insert(rootPtr,20);
rootPtr=Insert(rootPtr,25);
rootPtr=Insert(rootPtr,8);
rootPtr=Insert(rootPtr,12);
cout<<"PreOrder:";
preorder(rootPtr);
cout<<endl<<"InOrder:";
inorder(rootPtr);
cout<<endl<<"PostOrder:";
postorder(rootPtr);
cout<<endl;
return 0;
}
OUTPUT:
PreOrder:15 10 8 12 20 25
InOrder:8 10 12 15 20 25
PostOrder:8 12 10 25 20 15
3. Given a binary tree, write an efficient algorithm to convert the binary tree into
its mirror.
For example, the following binary trees are mirrors of each other: (also give
implementation)
Hint: traverse the tree in a preorder fashion, and for every node, swap its left and
right child pointer after recursively converting its left and right subtree to mirror
first.
ALGORITHM
Mirror(node* root)
1.Call Mirror(root->left)
2. Call Mirror(root->right)
3.Swap left and right subtrees of the root
INPUT:
#include<bits/stdc++.h>
using namespace std;
struct BSTNode
{
int data;
BSTNode* left;
BSTNode* right;
BSTNode(int val)
{
data=val;
left=NULL;
right=NULL;
}
};
BSTNode* Insert(BSTNode* root,int val)
{
if(root==NULL)
{
return new BSTNode(val);
}
else if(val<root->data)
{
root->left=Insert(root->left,val);
}
else
{
root->right=Insert(root->right,val);
}
return root;
}
void preorder(BSTNode* root)
{
if(root==NULL)
{
return;
}
cout<<root->data<<" ";
preorder(root->left);
preorder(root->right);
}
void inorder(BSTNode *root)
{
if(root==NULL)
{
return;
}
inorder(root->left);
cout<<root->data<<" ";
inorder(root->right);
}
void mirror(BSTNode*& root)
{
if(root)
{
mirror(root->left);
mirror(root->right);
BSTNode* temp=root->left;
root->left=root->right;
root->right=temp;
}
return;
int main()
{
BSTNode* rootPtr=NULL;
rootPtr=Insert(rootPtr,15);
rootPtr=Insert(rootPtr,10);
rootPtr=Insert(rootPtr,20);
rootPtr=Insert(rootPtr,25);
rootPtr=Insert(rootPtr,8);
rootPtr=Insert(rootPtr,12);
cout<<"PreOrder of Tree:";
preorder(rootPtr);
cout<<endl<<"InOrder of Tree:";
inorder(rootPtr);
cout<<endl<<endl;
mirror(rootPtr);
cout<<"PreOrder of Mirror Tree:";
preorder(rootPtr);
cout<<endl;
cout<<"InOrder of Mirror Tree:";
inorder(rootPtr);
return 0;
}
OUTPUT:
PreOrder of Tree:15 10 8 12 20 25
InOrder of Tree:8 10 12 15 20 25
OUTPUT:
Vertex 0-> 1 2
Vertex 1-> 0 2
Vertex 2-> 0 3 1
Vertex 3-> 2
ADJACENCY MATRIX
INPUT:
#include<bits/stdc++.h>
using namespace std;
class graph
{
int Vertex;
//pointer to 1D array
int **AdjMatrix;//pointer to pointer variable
public:
graph(int v)
{
this->Vertex=v;
AdjMatrix=new int*[v];
for (int row=0;row<v;row++)
{
AdjMatrix[row]=new int[v];
for(int col=0;col<v;col++)
{
AdjMatrix[row][col]=0;
}
}
}
void AddEdge(int x,int y)
{
AdjMatrix[x][y]=1;
AdjMatrix[y][x]=1;
}
void Display()
{
for(int i=0;i<Vertex;i++)
{
for (int j=0;j<Vertex;j++)
{
cout<<" "<<AdjMatrix[i][j]<<" ";
}
cout<<endl;
}
}
};
int main()
{
graph g(4);
//g.Display();
g.AddEdge(0,1);
g.AddEdge(0,2);
g.AddEdge(1,2);
g.AddEdge(2,3);
g.Display();
return 0;
}
OUTPUT:
0 1 1 0
1 0 1 0
1 1 0 1
0 0 1 0
1. give Implementation of depth & breadth first search algorithms on graph (lab 11
Q2)
BREADTH FIRST SEARCH
INPUT:
#include<bits/stdc++.h>
using namespace std;
template<typename T>
//so you can work with a graph of integers as well as strings
class Graph
{
//map<datatype,list<dataType>> variableName
//key value pair
map<T,list<T>>l;
public:
void addEdge(int x,int y)//bidirectional
{
l[x].push_back(y);
l[y].push_back(x);
}
void BFS(T sourceNode)
{
map<T,int> visited;
queue<T> q;
q.push(sourceNode);
visited[sourceNode]=true;
while(!q.empty())
{
T node=q.front();
q.pop();
cout<<node<<" ";
for(int adjacent:l[node])//l[node] gives me value of the
node
//values contain adjacency list/neighbours of that
{
if(!visited[adjacent])
{
q.push(adjacent);
//mark the adjacent as visited
visited[adjacent]=true;
}
}
}
}
};
int main()
{
Graph<int> g;
g.addEdge(0,1);
g.addEdge(1,2);
g.addEdge(2,3);
g.addEdge(3,4);
g.addEdge(4,5);
g.BFS(0);
return 0;
}
OUTPUT:
012345
DEPTH FIRST SEARCH
INPUT:
#include<bits/stdc++.h>
using namespace std;
//so you can work with a graph of integers as well as strings
template<typename T>
class Graph
{
//map<datatype,list<dataType>> variableName
//key value pair
map<T,list<T>>l;
public:
void addEdge(int x,int y)//bidirectional
{
l[x].push_back(y);
l[y].push_back(x);
}
void DFS_HELPER(T SourceNode,map<T,bool>&visited)
{
//recursive function that will traverse the graph
cout<<SourceNode<<" ";
visited[SourceNode]=true;
//go to all adjacent of node not visited one by one
for(T adj:l[SourceNode])
{
if(!visited[adj])
{
DFS_HELPER(adj,visited);
}
}
}
void DFS(T SourceNode)
{
map<T,bool>visited;
//mark all the nodes as not visited in the beginning
//auto keyword is a simple way to declare a variable that has
a complicated type
for(auto p:l)
{
T node=p.first;
visited[node]= false;
}
//call helper function
DFS_HELPER(SourceNode,visited);
}
};
int main()
{
Graph<int> g;
g.addEdge(0,1);
g.addEdge(1,2);
g.addEdge(2,3);
g.addEdge(3,4);
g.addEdge(4,5);
g.addEdge(3,0);
g.DFS(0);
return 0;
}
OUTPUT:
012345
2. Differentiate DFS and BFS : Also state which traversing method is best suited in
what circumstances?
Depth First Search Breadth First Search
Data Uses Stack to find the shortest Uses Queue to find DFS uses Stack to
Structure path. find the structure the shortest path.
Source Better when target is far from Better when target is close to the
source source
Speed Faster Slower
Time O(V+E) where V is vertices and O(V+E) where V is vertices and E
Complexity E vertices and E is edges. vertices and E is edges.
Memory Requires less memory Requires more memory
Application Suitable for gaming and puzzle Not suitable for decision making trees
problems used in games or puzzles as it
considers all neighbours in general
class Graph
{
int Vertex;
list<int>*l;
public:
Graph(int v)
{
this->Vertex=v;
//l is a pointer to an array in which
//each element of the array is a list
l=new list<int>[v];//dynamic location
}
int main()
{
Graph g(4);
g.addEdge(0,1);
g.addEdge(1,2);
g.addEdge(2,3);
g.addEdge(3,4);
g.addEdge(4,0);
cout<<"Graph 1"<<endl;
if(g.DetectCycle())
{
cout<<"Yes undirected graph contains cycle"<<endl;
}
else
{
cout<<"No ,the graph doesnot contain a cycle"<<endl;
}
Graph g1(4);
g.addEdge(0,1);
g.addEdge(1,2);
g.addEdge(2,3);
g.addEdge(3,4);
cout<<endl<<"Graph 2"<<endl;
if(g1.DetectCycle())
{
cout<<"Yes undirected graph contains cycle"<<endl;
}
else
{
cout<<"No ,the graph doesnot contain a cycle"<<endl;
}
return 0;
}
OUTPUT:
Graph 1
Yes undirected graph contains cycle
Graph 2
No ,the graph doesnot contain a cycle
Lab 13 Rat in a Maze
1.What approach do you used to solve problem and why?
The maze is represented by an N x N matrix (a graph).The concept of backtracking
is employed which solves computational problems recursively by trying to build a
solution incrementally. Hence we also used recursion because we have to
continuously check on which position to move next and we can only move in the x
direction and y direction.
We use backtracking to explore all the possible paths from a given vertex. Using
this, we either find a position to move to next or try another path /edge again. This
continues until we reach our destination. Hence, we use this approach because it
finds out all possible paths easily and uses recursion for locating them.
2. Give the algorithm of above problem, also analyze the time & space complexity
of your algorithm.
1. Create a solution matrix filled with 0’s
2.Recursive Function SolveMazeUntil(initial matrix,output matrix,int I ,int j)
3.Check if position of the rat is valid or not.
IF position is not valid then
Return
4.Mark the position [i][j] of output matrix as 1
5.Check if current position is the destination or not
IF current position is destination then
Print output matrix and Return
6.Recursive call for position (i+1, j) and (i,j+1)
7.Unmark position by simply output matrix[i][j]=0
Space Complexity is O(N2) because of the two dimensional array of size N*N
2
Time Complexity is O(2𝑁 ) because we need to consider two different paths at
every position .
3. Give implementation of Rat in a Maze problem.
INPUT:
#include<iostream>
using namespace std;
int main()
{
int maze[N][N] = { { 1, 0, 0, 0 },
{ 1, 1, 0, 1 },
{ 0, 1, 0, 0 },
{ 1, 1, 1, 1 } };
solveMaze(maze);
return 0;
}
OUTPUT:
1 0 0 0
1 1 0 0
0 1 0 0
0 1 1 1
Lab 14 N- Queen Problem
1.What approach do you used to solve problem and why?
The chessboard is represented by an NxN matrix. We apply the concept of
backtracking which is a general algorithmic technique in which all possible
combinations are considered in order to solve a problem.
We use backtracking because if the position of one of the queens is incorrect, we
can backtrack to correct it and try out other positions.
Backtracking also involves use of recursive functions hence recursion concept is
also used here.
Backtracking is a Depth First Search Technique as well meaning it involves
traversal of Graph(in this case the matrix)
2. Give the algorithm of above problem, also analyze the time & space complexity
of your algorithm.
ALGORITHM
1.Create a N by N matrix to collect all solution states
2.Start in topmost row
3.IF all queens are placed
Return true
4.Try out all the columns in the current row. Perform the following for every tried
column
a) Safe function checks current column, right diagnol and left diagnol. If queen
can be placed safely in the column, mark this position as part of solution and
recursively check if placing queen here leads to a solution
b) IF placing queen in this position leads to a solution,
Return true
c)IF placing queen does not lead to a solution
Unmark the position
Go back to part a to try other columns
5.IF all columns have been tried and nothing works
Return false to trigger backtracking
TIME COMPLEXITY
O(N!)
When you assign a location of the queen in the first row, you have n options, after
that, you only have n-1 options as you can't place the queen in the same row as the
first queen, then n-2 and so on.
E.g if N=4
For the first row, since none is filled in the matrix as a whole, we have 4 options.
For the second row, we have 3 options as one row has already been taken off.
Similarly, for the third row, we have 2 options and for the final row, we are left
with just 1 option.
Total options = 4*3*2*1 = 24 (4!)
Since N=4
T(N)=N!
SPACE COMPLEXITY
Since we are using NxN matrix, Space Complexity will be O(N2)
3. Give implementation of Rat in a Maze problem.
INPUT:
#include<bits/stdc++.h>
using namespace std;
//queen can attack from up ,doen ,left ,right and diagonal
//every queen placed in a different row
//every queen placed in a different column
//no queen to lie in another's diagnol
OUTPUT:
Sample Test 1
Enter a number (n) for which you will have an nxn matrix and place n queens:4
0100
0001
1000
0010
Sample Test 2
Enter a number (n) for which you will have an nxn matrix and place n queens:7
1000000
0010000
0000100
0000001
0100000
0001000
0000010