Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Ds Rec

Download as pdf or txt
Download as pdf or txt
You are on page 1of 66

Quick Sort

Aim : To perform quick sort on the given list of elements.

Algorithm :
1. Quick sort is a sorting algorithm that uses the divide and conquer approach.
2.An array is divided into sub-arrays by selecting a pivot element (element selected from the
array).
3.While dividing the array, the pivot element should be positioned in such a way that elements
less than pivot are kept on the left side and elements greater than pivot are on the right side of
the pivot.
4.The left and right sub-arrays are also divided using the same approach. This process
continues until each sub-array contains a single element.
5.At this point, elements are already sorted. Finally, elements are combined to form a sorted
array.

Code :
//Quick sort; Roll no. 160121733008
#include <stdio.h>
#include<stdlib.h>
void swap(int *a, int *b) {
int t = *a;
*a = *b;
*b = t;
return;
}
int partition(int array[], int low, int high) {
int pivot = array[high];
int i = (low - 1);
for (int j = low; j < high; j++) {
if (array[j] <= pivot) {
i++;
swap(&array[i], &array[j]);
}
}
swap(&array[i + 1], &array[high]);
return (i + 1);
}
void quickSort(int array[], int low, int high) {
if (low < high) {
int pi = partition(array, low, high);
quickSort(array, low, pi - 1);
quickSort(array, pi + 1, high);
}
return;
}
void print(int a[],int n) {
for (int i = 0; i < n; ++i) {
printf("%d ", a[i]);
}
printf("\n");
return;
}
int main() {
int arr[10], n,i=0;
printf("\nEnter the no. of elements in the array : ");
scanf("%d", &n);
printf("\nEnter the elements of the array : \n");
while(i<n){
scanf("%d",&arr[i]);
i++;
}
printf("\nThe given array is : ");
print(arr, n);
quickSort(arr, 0, n -1);
printf("The sorted array is : ");
print(arr, n);
}

Output :

Test Case 1 :
Test Case 2 :

Worst Time Complexity : O( n^2 )

Conclusion : The given list is sorted using Quick sort algorithm.


Merge Sort

Aim : To perform merge sort on the given list.

Algorithm :
1. According to the merge sort, first divide the given array into two equal halves. Merge sort
keeps dividing the list into equal parts until it cannot be further divided.
2. Now, they are combined in the same manner they were broken. In combining, the elements
of each array are compared and then combined into another array of sorted order.
3. In the next iteration of combining, the resultant sorted arrays from previous step are
compared and combined in sorted order.
4. This process is continued until there is one final sorted array left.
Code :
// Merge sort; Roll no. 160121733008
#include <stdio.h>
#include<stdlib.h>
void merge(int arr[], int p, int q, int r) {
int n1 = q - p + 1;
int n2 = r - q;
int L[n1], M[n2];
for (int i = 0; i < n1; i++){
L[i] = arr[p + i];
}
for (int j = 0; j < n2; j++){
M[j] = arr[q + 1 + j];
}
int i, j, k;
i = 0;
j = 0;
k = p;
while (i < n1 && j < n2) {
if (L[i] <= M[j]) {
arr[k] = L[i];
i++;
} else {
arr[k] = M[j];
j++;
}
k++;
}
while (i < n1) {
arr[k] = L[i];
i++;
k++;
}
while (j < n2) {
arr[k] = M[j];
j++;
k++;
}
return;
}
void mergeSort(int arr[], int l, int r) {
if (l < r) {
int m = l + (r - l) / 2;
mergeSort(arr, l, m);
mergeSort(arr, m + 1, r);
merge(arr, l, m, r);
}
return;
}
void print(int a[], int n) {
for (int i = 0; i < n; i++){
printf("%d ", a[i]);
}
printf("\n");
return;
}
int main() {
int arr[10], n, i=0;
printf("\nEnter the no. of elements in the list : ");
scanf("%d", &n);
printf("\nEnter the elements of the list : \n");
while (i < n){
scanf("%d", &arr[i]);
i++;
}
printf("The given array is : ");
print(arr,n);
mergeSort(arr, 0, n-1);
printf("The sorted array is : ");
print(arr,n);
return 0;
}
Output :

Test Case 1 :

Test Case 2 :
Worst Time Complexity : O(n*logn )

Conclusion : The given list is sorted using merge sort algorithm.


Selection Sort

Aim : To perform selection sort on the given list of elements.

Algorithm :
1. The selection sort algorithm sorts an array by repeatedly finding the minimum element
(considering ascending order) from the unsorted part and putting it at the beginning.
2. The algorithm maintains two sub-arrays in a given array i.e., the sub-array which is already
sorted and the remaining sub-array is to be sorted.
3. In every iteration of the selection sort, the minimum element (considering ascending order)
from the unsorted sub-array is picked and moved to the sorted subarray.
Code :
//Selection Sort; Roll no. 160121733008
#include <stdio.h>
#include<stdlib.h>
int main() {
int arr[10], i=0, n, j, position, swap;
printf("\nEnter the no. of elements in the array : ");
scanf("%d", &n);
printf("\nEnter the elements of the array : \n");
while(i<n){
scanf("%d",&arr[i]);
i++;
}
printf("\nThe given list is : ");
i=0;
while(i<n){
printf("%d ",arr[i]);
i++;
}
for (i = 0; i < (n - 1); i++) {
position = i;
for (j = i + 1; j < n; j++) {
if (arr[position] > arr[j])
position = j;
}
if (position != i) {
swap = arr[i];
arr[i] = arr[position];
arr[position] = swap;
}
}
printf("\n\nThe sorted list is : ");
for (i = 0; i < n; i++)
printf("%d ", arr[i]);
return 0;
}

Output :

Test Case 1 :

Test Case 2 :
Worst Time Complexity : O( n^2 )

Conclusion : The given list of elements are sorted using selection sort algorithm.
Radix Sort

Aim : To perform radix sort on the given list of elements.

Algorithm :
1. In Radix sort, there is digit by digit sorting is performed that is started from the least
significant digit to the most significant digit.
2. First, we = the largest element max from the given array.
3. Suppose 'x' be the number of digits in max. The 'x' is calculated because we need to go
through the significant places of all elements from left to right in the list.
4. When all the digits are considered, we update the array with the elements in the buckets with
least index to highest index.
5. This array we obtain from above step is sorted in ascending order.

Code :
// Radix Sort; Roll no. 160121733008
#include <stdio.h>
#include<stdlib.h>
int getMax(int array[], int n) {
int max = array[0];
for (int i = 1; i < n; i++)
if (array[i] > max)
max = array[i];
return max;
}
void countingSort(int array[], int size, int place) {
int output[size + 1];
int max = (array[0] / place) % 10;
for (int i = 1; i < size; i++) {
if (((array[i] / place) % 10) > max)
max = array[i];
}
int count[max + 1];
for (int i = 0; i < max; ++i)
count[i] = 0;
for (int i = 0; i < size; i++)
count[(array[i] / place) % 10]++;
for (int i = 1; i < 10; i++)
count[i] += count[i - 1];
for (int i = size - 1; i >= 0; i--) {
output[count[(array[i] / place) % 10] - 1] = array[i];
count[(array[i] / place) % 10]--;
}
for (int i = 0; i < size; i++)
array[i] = output[i];
return;
}
void radixsort(int array[], int size) {
int max = getMax(array, size);
for (int place = 1; max / place > 0; place *= 10)
countingSort(array, size, place);
return;
}
void printArray(int array[], int size) {
for (int i = 0; i < size; ++i) {
printf("%d ", array[i]);
}
printf("\n");
return;
}
int main() {
int arr[10], n,i=0;
printf("\nEnter the no. of elements in the array : ");
scanf("%d", &n);
printf("\nEnter the elements of the array : \n");
while(i<n){
scanf("%d",&arr[i]);
i++;
}
printf("\nThe given list is : ");
printArray(arr, n);
radixsort(arr, n);
printf("\nThe sorted list is : ");
printArray(arr, n);
return;
}
Output :

Test Case 1 :

Test Case 2 :
Worst Time Complexity : O(n*k)

Conclusion : The elements of the given list are sorted using radix sort algorithm.
Singly Linked List

Aim : To create a singly linked list and perform insertion and deletion operations at different
positions on it.

Algorithm :

1. Insertion at the Beginning : Allocate memory for new node and store data. Change next of
new node to point to head. Change head to point to new node.

2. Insertion at the End : Allocate memory for new node. Store data. Traverse to last node.
Change next of last node to new node and point next of new node to NULL.

3. Insertion at the Specified Position : Allocate memory and store data for new node.
Traverse to node just before the required position of new node. Point next of previous node to
current node at the specified position to new node and next of new node to the the current node
at the specified position.

4. Deletion at the Beginning : Point head to the node next to head and next of head to NULL.
Make next node to head as head.

5. Deletion at the End : Traverse to second last element. Change its next pointer to null

6. Deletion at the Specified Position : Traverse to previous node of the node to be deleted.
Point next of previous node to next node of node to be deleted. Point the next of node to be
deleted to NULL.

Code:

//Singly linked list oprations; Roll no. 160121733008


#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
} *head, *temp, *flag, *nw, *del;

void read(){
head=(struct node*)malloc(sizeof(struct node));
flag=(struct node*)malloc(sizeof(struct node));
int n,i,val;
printf("\nEnter the number of nodes : ");
scanf("%d", &n);
printf("\nInput values for nodes : \n");
scanf("%d", &val);
head->data = val;
head->next = NULL;
temp = head;
for(i=2; i<=n; i++)
{
flag = (struct node *)malloc(sizeof(struct node));
if(flag == NULL)
{
printf("\nMemory can not be allocated.\n");
break;
}
else
{
scanf(" %d", &val);
flag->data = val;
flag->next = NULL;
temp->next = flag;
temp = temp->next;
}
}
return;
}

void print(){
temp=head;
printf("\n");
while(temp!=NULL){
printf("%d->", temp->data);
temp=temp->next;
}
printf("NULL\n");
return;
}

int lcount(){
int i=0;
temp=head;
while(temp!=NULL){
i++;
temp=temp->next;
}
return i;
}

void insert_beginning(){
int val;
printf("\nEnter the value of node to be inserted : ");
scanf("%d",&val);
nw = (struct node *)malloc(sizeof(struct node));
nw->data=val;
nw->next=head;
head=nw;
return;
}

void insert_end(){
int val;
printf("\nEnter the value of node to be inserted : ");
scanf("%d",&val);
nw = (struct node *)malloc(sizeof(struct node));
nw->data=val;
nw->next=NULL;
temp=head;
while(temp->next!=NULL){
temp=temp->next;
}
temp->next=nw;
return;
}

void insert_pos(){
int val,n;
printf("\nEnter the position in which node is to be inserted : ");
scanf("%d", &n);
printf("\nEnter the value of node to be inserted : ");
scanf("%d",&val);
struct node *temp1 = (struct node*)malloc(sizeof(struct node));
temp1->data = val;
temp1->next = NULL;
if(n==1){
temp1->next=head;
head=temp1;
return;
}
struct node *temp2 = head;
for(int i=0; i<n-1; i++){
temp2=temp2->next;
}
temp1->next=temp2->next;
temp2->next=temp1;
return;
}

void del_beginning(){
del=head;
head=head->next;
del->next=NULL;
return;
}

void del_end(){
del=head;
while(del->next->next!=NULL){
del=del->next;
}
del->next=NULL;
return;
}

void del_pos(){
int i,pos;
printf("\nEnter the position of node to be deleted : ");
scanf("%d", &pos);
temp = head;
if(pos==0) {
head=head->next;
temp->next=NULL;
}
else {
for(i=0;i<pos-1;i++) {
temp=temp->next;
}
del=temp->next;
temp->next=temp->next->next;
del->next=NULL;
}
return;
}

void revlist(){
struct node *prevNode, *curNode;
if(head != NULL)
{
prevNode = head;
curNode = head->next;
head = head->next;
prevNode->next = NULL;
while(head != NULL)
{
head = head->next;
curNode->next = prevNode;
prevNode = curNode;
curNode = head;
}
head = prevNode;
}
return;
}

int main()
{
read();
print();
int co;
co=lcount();
printf("\nThe no. of nodes in the linked list is : %d",co);
printf("\n\nINSERTION AT THE BEGINNING\n");
insert_beginning();
print();
printf("\nINSERTION AT THE END\n");
insert_end();
print();
printf("\nINSERTION AT SPECIFIED POSITION\n");
insert_pos(co);
print();
printf("\nDELETION AT THE BEGINNING\n");
del_beginning();
print();
printf("\nDELETION AT THE END\n");
del_end();
print();
printf("\nDELETION AT THE SPCIFIED POSITION\n");
del_pos();
print();
printf("\nREVERSE OF THE LIST\n");
revlist();
print();
return 0;
}
Output :
Conclusion : The singly linked list is created and the insertion and deletion operations at
different positions were performed.
Doubly Linked List

Aim : To create and perform insertion and deletion operations on a doubly linked list.

Algorithm :

1. Insertion At Beginning of the list : Allocate memory to new node. Assign data to the new
node. Point next of new node to head and point prev to NULL. Point prev of headto new node
and make new node as head.

2. Inserting At End of the list : Allocate memory to new node. Assign data to the new node.
Assign value. Traverse till the end of the list and point next of tail to new node and new node
prev to tail. Point next of new node to NULL and make new node as tail.

3. Insertion At A Specific location : Allocate memory to new node. Assign data to the new
node. Assign the value of next from previous node to next of new node. Assign the address of
new node to next of previous node. Assign the value of prev of next node to the prev of new
node. Assign the address of new node to prev of next node.

4. Deleting from Beginning of the list : Point prev of node next to head to tail and next of tail
to node next to head. Free the memory of head and make next node to head as head.

5. Deleting from End of the list : Point next of previous node to tail as NULL and free the
memory allocated to tail. Make the node previous to tail as tail.

6. Deleting a Specific Node from the list : Traverse to the node in specified position. Point the
next of previous node to node next to the node to be deleted. Point prev of node next to the
node to be deleted to previous node. Free the memory allocated to the specified node.

Code :
//Doubly linked list; Roll no. 160121733008
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

struct node {
int data;
struct node *next;
struct node *prev;
};
struct node *head = NULL;
struct node *tail = NULL;
struct node *current = NULL;
bool isEmpty() {
return head == NULL;
}
void display() {
struct node *ptr = head;
printf("\n");
while(ptr != NULL) {
printf("%d <-> ",ptr->data);
ptr = ptr->next;
}
printf("NULL");
printf("\n ");
}
void insert_beginning(int data) {
struct node *temp = (struct node*) malloc(sizeof(struct node));
if(isEmpty()) {
tail = temp;
}
else {
head->prev = temp;
}temp->data = data;
temp->next = head;
head = temp;
}
void insert_end(int data) {
struct node *temp = (struct node*) malloc(sizeof(struct node));
temp->data = data;
if(isEmpty()) {
tail = temp;
}
else {
tail->next = temp;
temp->prev = tail;
}
tail = temp;
}
struct node* delete_beginning() {
struct node *temp = head;
if(head->next == NULL){
tail = NULL;
}
else {
head->next->prev = NULL;
}
head = head->next;
return temp;
}
void delete_end() {
if(head->next == NULL) {
head = NULL;
}
else {
tail->prev->next = NULL;
}
tail = tail->prev;
return;
}
void delete_pos() {
int pos;
printf("\nEnter the position : ");
scanf("%d",&pos);
struct node* current = head;
struct node* previous = NULL;
if(head == NULL) {
return;
}
for(int i=0;i<pos-1;i++) {
if(current->next == NULL) {
return;
}
else {
previous = current;
current = current->next;
}
}
if(current == head) {
head = head->next;
}
else {
current->prev->next = current->next;
}
if(current == tail) {
tail = current->prev;
}
else {
current->next->prev = current->prev;
}
return;
}
void insert_pos(data) {
int i,pos;
printf("\nEnter the position : ");
scanf("%d",&pos);
struct node *current = head;
if(head == NULL) {
return false;
}
for(int i=0;i<pos-1;i++) {
if(current->next == NULL) {
return;
}
else {
current = current->next;
}
}
struct node *nw = (struct node*) malloc(sizeof(struct node));
nw->data = data;
if(current == tail) {
nw->next = NULL;
tail = nw;
}
else {
nw->next = current->next;
current->next->prev = nw;
}
nw->prev = current;
current->next = nw;
return ;
}
void main() {
int n,i,data;
printf("\nEnter the no. of nodes : ");
scanf("%d",&n);
printf("\nEnter the elements of the list : \n");
scanf("%d",&data);
insert_beginning(data);
for(i=0;i<n-1;i++){
scanf("%d",&data);
insert_end(data);
}
printf("\nThe given doubly linked list is : \n");
display();
printf("\nThe doubly linked list after insertion at beginning : \n");
printf("\nEnter the value : ");
scanf("%d",&data);
insert_beginning(data);
display();
printf("\nThe doubly linked list after insertion at end : \n");
printf("\nEnter the value : ");
scanf("%d",&data);
insert_end(data);
display();
printf("\nThe doubly linked list after insertion at specified position : \n");
printf("\nEnter the value : ");
scanf("%d",&data);
insert_pos(data);
display();
printf("\nThe doubly linked list after deletion at beginning : \n");
delete_beginning();
display();
printf("\nThe doubly linked list after deletion at end : \n");
delete_end();
display();
printf("\nThe doubly linked list after deletion at specified position : \n");
delete_pos();
display();
return;
}

Output :
Conclusion : The Doubly linked list was created and insertion and deletion operations were
performed on it.
Circular Linked List

Aim : To create and perform insertion and deletion operations on a circular linked list.

Algorithm :

1. Insertion at the Beginning : Store the address of current head in the new node and point the
new node to current first node. Point the last node to the new node and make the new node as
head.
2. Insertion at the End : Store the address of head node to next of the new node and point
current tail node to the new node. Make new node as the tail node.
3. Insertion at the specified position : Traverse to the node in the position given. Point the
next of new node to next node to the node in specified position and stare the address of new
node in next of node in specified position.
4. Deletion at the Beginning : Free the memory occupied by the node and make next of the
node ass NULL. Make the node next to head as head.
5. Deletion at the End : Traverse to the node before tail node. Let it be temp. Store the address
of the next node to the tail node in temp. Free memory of the tail node and make temp as tail
node.
6. Deletion at the Specified Position : Traverse to the node to be deleted. Let it be d. Let the
node before d be temp. Store the address of the node next to d in temp. Free the memory of d.

Code :

#Circular linked list; Roll no. 160121733008


class node:
def __init__(self, d):
self.d = d
self.n = None
class CircularLL:
def __init__(self):
self.head = None
def Display(self):
x = self.head
if (x != None):
print("The Circular linked list is : ", end=" ")
while (True):
print(x.d, end=" ")
x = x.n
if (x == self.head):
break
print()
else:
print("The list is empty.")
def InsertBeg(self, ele):
nw = node(ele)
if (self.head == None):
self.head = nw
nw.n = self.head
return
else:
x = self.head
while (x.n != self.head):
x = x.n
x.n = nw
nw.n = self.head
self.head = nw
def InsertEnd(self, ele):
nw = node(ele)
if (self.head == None):
self.head = nw
nw.n = self.head
return
else:
x = self.head
while (x.n != self.head):
x = x.n
x.n = nw
nw.n = self.head
def InsertPos(self, ele, pos):
nw = node(ele)
x = self.head
count = 0
if (x != None):
count += 1
x = x.n
while (x != self.head):
count += 1
x = x.n
if (pos < 1 or pos > (count + 1)):
print("\nInavalid pos.")
elif (pos == 1):
if (self.head == None):
self.head = nw
self.head.n = self.head
else:
while (x.n != self.head):
x = x.n
nw.n = self.head
self.head = nw
x.n = self.head
else:
x = self.head
for i in range(1, pos - 1):
x = x.n
nw.n = x.n
x.n = nw
def DelBeg(self):
if (self.head != None):
if (self.head.n == self.head):
self.head = None
else:
x = self.head
n1 = self.head
while (x.n != self.head):
x = x.n
self.head = self.head.n
x.n = self.head
n1 = None
def DelPos(self, pos):
k = self.head
x = self.head
count = 0
if (x != None):
count += 1
x = x.n
while (x != self.head):
count += 1
x = x.n
if (pos < 1 or pos > count):
print("\nInavalid pos.")
elif (pos == 1):
if (self.head.n == self.head):
self.head = None
else:
while (x.n != self.head):
x = x.n
self.head = self.head.n
x.n = self.head
k = None
else:
x = self.head
for i in range(1, pos - 1):
x = x.n
k = x.n
x.n = x.n.n
k = None
def DelEnd(self):
if (self.head != None):
if (self.head.n == self.head):
self.head = None
else:
x = self.head
while (x.n.n != self.head):
x = x.n
tail = x.n
x.n = self.head
tail = None
Cll = CircularLL()
n=int(input("Enter the number of nodes : "))
print("Enter the elements of the list :")
val = int(input())
Cll.InsertBeg(val)
for i in range(n-1):
val = int(input())
Cll.InsertEnd(val)
Cll.Display()
print("Insertion at the beginning.... ")
val=int(input("Enter value to be inserted : "))
Cll.InsertBeg(val)
Cll.Display()
print("Insertion at the end.... ")
val=int(input("Enter value to be inserted : "))
Cll.InsertEnd(val)
Cll.Display()
print("Insertion at the specified position.... ")
pos = int(input("Enter the position : "))
val = int(input("Enter value to be inserted : "))
Cll.InsertPos(val, pos)
Cll.Display()
print("Deletion at the beginning.... ")
Cll.DelBeg()
Cll.Display()
print("Deletion at the end....")
Cll.DelEnd()
Cll.Display()
print("Deletion at the specified position....")
pos = int(input("Enter the position : "))
Cll.DelPos(pos)
Cll.Display()
Output :
Conclusion : A circular linked list was created and insertion and deletion operations at
different positions were performed on it.
Stack Using An Array

Aim : To create a stack using an array and perform push and pop operations on it.

Algorithm :

1. Push : Check whether stack is full i.e., top == size-1. If it is full, then display Overflow and
terminate the function. If it is not full, then increment top value by one and set stack[top] to
value .

2. Pop : Check whether stack is empty. (top == -1). If it is empty, then display Underflow and
terminate the function. If it is not empty, then define a variable 'i' and initialize with top. Display
stack[i] value and decrement i value by one.

Code :

//stack using array; Roll no. 160121733008


#include<stdio.h>
#include<stdlib.h>
#define size 8
int stack[size];
int top=-1;

void push(){
int val;
if(top==size-1){
printf("\nOverflow\n");
}
else{
int val;
scanf("%d",&val);
top++;
stack[top]=val;
}
return;
}

void pop(){
int val;
if(top==-1){
printf("\nUnderflow\n");
}
else{
val=stack[top];
top--;
}
return;
}
void display(){
if(top==-1)
{
printf("\nUnderflow\n");
}
else{
int i;
for(i=top; i>=0; i--){
printf("%d ",stack[i]);
}
}
return;
}

int main(){
int n,val;
printf("\nEnter the no of elements to be stored in a stack : ");
scanf("%d",&n);
int i=0;
printf("\nEnter the values to be stored in stack :\n");
while(i<n){
push();
i++;
}
printf("\nThe given stack is : ");
display();
printf("\n");
printf("\nEnter the value to be inserted in stack : ");
push();
printf("\nThe stack after insertion is : ");
display();
printf("\n");
pop();
printf("\nThe stack after pop function is called : ");
display();
printf("\n");
return 0;
}
Output :

Conclusion : The stack was created using a linked list and push and pop operations were
performed on it.
Stack Using A Linked List

Aim : To create a stack using a linked list and perform push and pop operations on it.

Algorithm :

1. Push : Create a new node and assign value to the node. Check if stack is empty or not, i.e, (top ==
NULL). If it is empty, then set the next pointer of the node to NULL. If it is not empty, the newly
created node should be linked to the current top element of the stack. Make sure that the top of the
stack should always be pointing to the newly created node.

2. Pop : Check if stack is empty or not, i.e, (TOP == NULL). If it is empty, then print Stack Underflow.
Now, make top point to the next node. Delete the temporary node and return the value stored in
temp_data.

Code :

// Stack using linked list; Roll no. 160121733008


#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node *next;
};
struct Node* top = NULL;
void push(int value) {
struct Node *newNode;
newNode = (struct Node *)malloc(sizeof(struct Node));
newNode->data = value;
if (top == NULL) {
newNode->next = NULL;
} else {
newNode->next = top;
}
top = newNode;
printf("Node is Inserted\n\n");
return;
}
int pop() {
if (top == NULL) {
printf("\nStack Underflow\n");
} else {
struct Node *temp = top;
int temp_data = top->data;
top = top->next;
free(temp);
return temp_data;
}
return;
}

void display() {
if (top == NULL) {
printf("\nStack Underflow\n");
} else {
printf("The stack is \n");
struct Node *temp = top;
while (temp->next != NULL) {
printf("%d -> ", temp->data);
temp = temp->next;
}
printf("%d -> NULL\n\n", temp->data);
}
return;
}

int main() {
int choice, value;
printf("\nImplementation of Stack using Linked List\n");
while (1) {
printf("1. Push\n2. Pop\n3. Display\n4. Exit\n");
printf("\nEnter your choice : ");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("\nEnter the value to insert: ");
scanf("%d", &value);
push(value);
break;
case 2:
printf("Popped element is :%d\n", pop());
break;
case 3:
display();
break;
case 4:
exit(0);
break;
default:
printf("\nWrong Choice\n");
}
}
return 0;
}

Output :
Conclusion : The stack was created using a linked list and push and pop operations were
performed on it.
Infix expression to Postfix expression conversion

Aim : To convert infix expression to postfix expression.

Algorithm :

1. Scan the infix expression from left to right.


2. If the scanned character is an operand, output it.
3. Else, If the precedence and associativity of the scanned operator are greater than the
precedence and associativity of the operator in the stack or the stack is empty or the stack
contains a ‘(‘ , then push it.
4. Else, Pop all the operators from the stack which are greater than or equal to in precedence
than that of the scanned operator.
5. After doing that Push the scanned operator to the stack. If you encounter parenthesis while
popping then stop there and push the scanned operator in the stack.
6. If the scanned character is an ‘(‘, push it to the stack. If the scanned character is an ‘)’, pop
the stack and output it until a ‘(‘ is encountered, and discard both the parenthesis.
7. Repeat the above steps until the infix expression is scanned. Pop and print the output from
the stack until it is not empty.
Code :

#Convertion of infix expression to postfix expression; Roll no. 160121733008


class Conversion:
def __init__(self, capacity):
self.top = -1
self.capacity = capacity
self.array = []
self.output = []
self.precedence = {'+': 1, '-': 1, '*': 2, '/': 2, '^': 3}
def isEmpty(self):
return True if self.top == -1 else False
def peek(self):
return self.array[-1]
def pop(self):
if not self.isEmpty():
self.top -= 1
return self.array.pop()
else:
return "$"
def push(self, op):
self.top += 1
self.array.append(op)
def isOperand(self, ch):
return ch.isalpha()
def notGreater(self, i):
try:
a = self.precedence[i]
b = self.precedence[self.peek()]
return True if a <= b else False
except KeyError:
return False
def infixToPostfix(self, exp):
for i in exp:
if self.isOperand(i):
self.output.append(i)
elif i == '(':
self.push(i)
elif i == ')':
while((not self.isEmpty()) and
self.peek() != '('):
a = self.pop()
self.output.append(a)
if (not self.isEmpty() and self.peek() != '('):
return -1
else:
self.pop()
else:
while(not self.isEmpty() and self.notGreater(i)):
self.output.append(self.pop())
self.push(i)
while not self.isEmpty():
self.output.append(self.pop())
print ("".join(self.output))

exp = "a+b*(c^d-e)^(f+g*h)-i"
print("The given infix expression is : ",exp)
obj = Conversion(len(exp))
print("The postfix expression is : ", end=" ")
obj.infixToPostfix(exp)
Output :

Conclusion : The given infix expression was converted to postfix expression using a stack.
Postfix Evaluation

Aim : To evaluate Postfix expression.

Algorithm :

1. Create a stack to store operands.


2. Scan the given expression from left to right and do the following for every scanned element.
3. If the element is a number, push it into the stack.
4. If the element is an operator, pop operands for the operator from the stack. Evaluate the
operator and push the result back to the stack.
5. When the expression is ended, the number in the stack is the final answer.
Code :

# Evaluation a postfix expression; Roll no. 160121733008


class Evaluate:
def __init__(self, capacity):
self.top = -1
self.capacity = capacity
self.array = []
def isEmpty(self):
return True if self.top == -1 else False
def peek(self):
return self.array[-1]
def pop(self):
if not self.isEmpty():
self.top -= 1
return self.array.pop()
else:
return "$"
def push(self, op):
self.top += 1
self.array.append(op)
def evaluatePostfix(self, exp):
for i in exp:
if i.isdigit():
self.push(i)
else:
val1 = self.pop()
val2 = self.pop()
self.push(str(eval(val2 + i + val1)))
return int(self.pop())
exp = "231*+9-"
print("The given expression is : ", exp)
obj = Evaluate(len(exp))
print("postfix evaluation: %d" % (obj.evaluatePostfix(exp)))

Output :

Test Case 1 :

Test Case 2 :

Conclusion : The given postfix expressions were evaluated using stacks.


Queue Using An Array

Aim : To create a queue using an array and perform enqueue and dequeue operations.

Algorithm :

1. Enqueue : First check if the queue is full. If the queue is full, then it will print Overflow and
exit. Else, increment the variable rear by 1. Finally, assign the new value to be inserted into the
array of queue in Queue[rear].

2. Dequeue : First checks whether the value of Front is -1 or the value of Front is greater than
the rear. If the condition is true then it will print Underflow and exit. Else, keep increasing the
value of the variable Front and return the value stored at the Front end of the queue.

Code :

// queue using array; Roll no. 160121733008


#include<stdio.h>
#include<stdlib.h>
#define SIZE 8
int Queue[SIZE];
int rear=-1;
int front=-1;

void enqueue(){
if(rear==SIZE-1){
printf("\n\t\tOverflow\n");
}
else{
int elem;
printf("\nEnter the element to be entered in queue : ");
scanf("%d",&elem);
if(front==-1){
front=0;
}
rear++;
Queue[rear]=elem;
}
return;
}

void dequeue(){
if(rear==-1 || front>rear)
{
printf("\t\tUnderflow\n");
}
else{
printf("\n\nThe element being deleted is : %d",Queue[front]);
front++;
}
return;
}

void display(){
if(rear==-1||front>rear)
{
printf("\nUnderflow\n");
}
else{
int i;
for(i=front; i<=rear; i++){
printf("%d ",Queue[i]);
}
}
return;
}

int main()
{
while(1){
int key;
enqueue();
printf("\n\t\tEnter 0 to stop inserting and 1 to continue : ");
scanf("%d",&key);
if(key==0){
break;
}
}
printf("\n\nThe given queue is : ");
display();
dequeue();
printf("\n\nThe given queue after dequeue is : ");
display();
printf("\n");
return 0;
}
Output :

Conclusion : The queue was created using an array and enqueue and dequeue operations were
performed on it.
Queue Using A Linked List

Aim : To create a queue using a linked list and perform enqueue and dequeue operations.

Algorithm :

1. Enqueue : Create a newNode with given value and set 'newNode → next' to NULL. Check
whether queue is Empty (rear == NULL). If it is Empty then, set front = newNode and rear =
newNode. If it is Not Empty then, set rear → next = newNode and rear = newNode.

2. Dequeue : Check whether queue is Empty (front == NULL). If it is Empty, then display
Queue is empty and terminate from the function If it is not Empty then, define a Node pointer
'temp' and set it to 'front'. Then set front = front → next and delete temp.

Code :

// Using linked list; Roll no. 160121733008


#include<stdio.h>
#include<stdlib.h>
struct node{
int data;
struct node *next;
}*temp, *nw,*front,*rear;

void enqueue(){
int val;
nw=(struct node *)malloc(sizeof(struct node));
printf("\nEnter the elemnts to be inserted : ");
scanf("%d",&val);
nw->data=val;
nw->next=NULL;
if(rear==NULL){
front=nw;
rear=nw;
}
else{
rear->next=nw;
rear=nw;
}
return;
}

void dequeue(){
temp=(struct node*)malloc(sizeof(struct node));
if(front==NULL){
printf("\nQueue is empty\n");
}
else{
printf("\n\nThe elemnt being deleted is : %d",front->data);
temp=front;
front=front->next;
temp->next=NULL;
}
free(temp);
return;
}
void display(){
if(front==NULL){
printf("\nQueue is empty\n");
}
else{
temp=front;
while(temp!=NULL){
printf("%d ",temp->data);
temp=temp->next;
}
}
return;
}
int main(){
while(1){
int key;
enqueue();
printf("\n\t\tEnter 0 to stop inserting and 1 to continue : ");
scanf("%d",&key);
if(key==0){
break;
}
}
printf("\n\nThe elemnts in the queue are : ");
display();
dequeue();
printf("\n\nThe elemnts in the queue after dequeue operation : ");
display();
printf("\n");
return 0;
}
Output :

Conclusion : The queue was created using a linked list and enqueue and dequeue operations
were performed on it.
Double Ended Queue Using An Array

Aim : To create a double ended queue using an array and to perform insertion and deletion
operations at front and rear.

Algorithm :

Take an array of size n. Set two pointers at the first position and set front = -1 and rear = 0.
1. Insert at the Front : Check the position of front. If front < 1, reinitialize front as last index.
Else, decrease front by 1. Add the new value into array[front].
2. Insert at the Rear : Check if the array is full. If it is full, reinitialize rear as zero. Else,
increase rear by 1. Add the value into array[rear].
3. Delete from Front : Check if the double ended queue is empty. If the it is empty i.e., front =
-1, deletion cannot be performed due to underflow condition. If the double ended queue has
only one element i.e., front = rear, set front = -1 and rear = -1. Else if front is at the end i.e.,
front = n - 1, set go to the front front = 0. Else, front = front + 1.
4. Delete from the Rear : Check if the double ended queue is empty. If the double ended
queue is empty i.e., front = -1, deletion cannot be performed due to underflow condition. f the
double ended queue has only one element i.e., front = rear, set front = -1 and rear is -1, else
follow the steps below. If rear is at the front i.e., rear = 0, set go to the front rear = n - 1. Else,
rear = rear - 1.
Code :

# Double ended queque; Roll no. 160121733008


class Doble_ended_queue:
def __init__(self):
self.items = list(map(int, input("Enter the elements : ").split(" ")))
def isEmpty(self):
return self.items == []
def addRear(self, item):
self.items.append(item)
def addFront(self, item):
self.items.insert(0, item)
def removeFront(self):
return self.items.pop(0)
def removeRear(self):
return self.items.pop()

d = Doble_ended_queue()
d.addFront(7)
print("The list after updating is : ", d.items)
d.addFront(10)
print("The list after updating is : ", d.items)
d.addRear(8)
print("The list after updating is : ", d.items)
d.addRear(5)
print("The list after updating is : ", d.items)
if d.isEmpty()==True:
print("The list is empty.")
else:
print("The element being removed from front : ", d.removeFront())
print("The element being removed from rear : ", d.removeRear())
print("The list after updating is : ", d.items)

Output :

Conclusion : The double ended queue was created using an array and insertion and deletion
operations were performed at front and rear.
Double Ended Queue Using a Linked List

Aim : To create a double ended queue using a linked list and to perform insertion and deletion
operations at front and rear.

Algorithm :

We define a class Deque which contains a reference named front to the first element of the
linked list.
1. Insert at the Front : The element is added before the node currently being referenced by
the front and then the dequeSize is incremented by one.
2. Insert at the Rear : We traverse to the end of the linked list and the node node is added to
the current last node.
3. Delete from Front : We check if the deque is empty. If the deque is empty i.e., front points
to None, a message is printed that the deque is empty. We then delete the element from the
start of the linked list which is being referenced by front. After deletion, we decrement the
dequeSize by one.
4. Delete from the Rear : We traverse to the last node and delete the last node of the linked list
and then, decrement the dequeSize by one.
Code :

#Double ended queue using linked list; Roll no. 160121733008


class Node:
def __init__(self,data):
self.data=data
self.next=None
class Deque:
def __init__(self):
self.front=None
self.dequeSize=0
def isEmpty(self):
if self.dequeSize==0:
return True
return False
def dequeLength(self):
return self.dequeSize
def insertAtFront(self,data):
temp=Node(data)
if self.front==None:
self.front=temp
self.dequeSize=self.dequeSize+1
else:
temp.next=self.front
self.front=temp
self.dequeSize=self.dequeSize+1
def insertAtRear(self,data):
temp=Node(data)
if self.front==None:
self.front=temp
self.dequeSize=self.dequeSize+1
else:
curr=self.front
while curr.next!=None:
curr=curr.next
curr.next=temp
self.dequeSize=self.dequeSize+1
def delFromFront(self):
if self.dequeSize==0:
raise Exception("Deque is Empty")
else:
temp=self.front
self.front=self.front.next
self.dequeSize=self.dequeSize-1
del temp
def deleteFromRear(self):
if self.dequeSize==0:
print("Deque is Empty")
else:
curr=self.front
prev=None
while curr.next!=None:
prev=curr
curr=curr.next
prev.next=curr.next
self.dequeSize=self.dequeSize-1
del curr
def pelem(self):
temp = self.front
while temp != None:
print(temp.data, end=" ")
temp = temp.next
d = Deque()
d.insertAtFront(2)
d.insertAtFront(5)
d.insertAtFront(8)
d.insertAtFront(12)
d.insertAtFront(14)
d.insertAtRear(30)
d.insertAtRear(43)
d.insertAtRear(52)
d.insertAtRear(27)
d.insertAtRear(65)
print("The elements of the queue are : ")
d.pelem()
print()
d.delFromFront()
print("The elements of the queue after deletion from front are : ")
d.pelem()
print()
d.deleteFromRear()
print("The elements of the queue after deletion from rear are : ")
d.pelem()
print()

Output :

Conclusion : The double ended queue was created using a linked list and insertion and deletion
operations were performed at front and rear.
Circular Queue Using An Array

Aim : To create circular queue using an array and perform enqueue and dequeue operations.

Algorithm :

1. Enqueue : In a circular queue, the new element is always inserted at Rear position.
Check whether queue is Full – Check ((rear == SIZE-1 && front == 0) || (rear == front-1)).
If it is full then display Queue is full. If queue is not full then, check if (rear == SIZE – 1 &&
front != 0) if it is true then set rear=0 and insert element.
2. Dequeue : This function is used to delete an element from the circular queue. In a circular
queue, the element is always deleted from front position.
Check whether queue is Empty means check (front==-1).
If it is empty then display Queue is empty. If queue is not empty then, Check if (front==rear) if
it is true then set front=rear= -1 else check if (front==size-1), if it is true then set front=0 and
return the element.
Code :

#Circular queue using array; Roll no. 160121733008


class CircularQueue():
def __init__(self, size):
self.size = size
self.queue = [None for i in range(size)]
self.front = self.rear = -1
def enqueue(self, data):
if ((self.rear + 1) % self.size == self.front):
print(" Queue is Full\n")
elif (self.front == -1):
self.front = 0
self.rear = 0
self.queue[self.rear] = data
else:
self.rear = (self.rear + 1) % self.size
self.queue[self.rear] = data
def dequeue(self):
if (self.front == -1):
print ("Queue is Empty\n")
elif (self.front == self.rear):
temp=self.queue[self.front]
self.front = -1
self.rear = -1
return temp
else:
temp = self.queue[self.front]
self.front = (self.front + 1) % self.size
return temp
def display(self):
if(self.front == -1):
print ("Queue is Empty")
elif (self.rear >= self.front):
print("Elements in the circular queue are:",end = " ")
for i in range(self.front, self.rear + 1):
print(self.queue[i], end = " ")
print ()
else:
print ("Elements in Circular Queue are:",end = " ")
for i in range(self.front, self.size):
print(self.queue[i], end = " ")
for i in range(0, self.rear + 1):
print(self.queue[i], end = " ")
print ()
if ((self.rear + 1) % self.size == self.front):
print("Queue is Full")

ob = CircularQueue(10)
ob.enqueue(14)
ob.enqueue(22)
ob.enqueue(13)
ob.enqueue(-6)
ob.enqueue(9)
ob.enqueue(20)
ob.enqueue(8)
ob.enqueue(5)
ob.enqueue(10)
ob.display()
print ("Deleted value = ", ob.dequeue())
print ("Deleted value = ", ob.dequeue())
ob.display()
Output :

Conclusion : The circular queue was created and enqueue and dequeue operations were
performed on it.
Circular Queue Using a Linked List

Aim : To create circular queue using linked list and perform enqueue and dequeue operations.

Algorithm :

1. Enqueue : This function is used to insert an element into the circular queue. In a circular
queue, the new element is always inserted at Rear position.
Create a new node dynamically and insert value into it.
Check if front==NULL, if it is true then front = rear = (newly created node)
If it is false then rear=(newly created node) and rear node always contains the address of the
front node.
2. Dequeue : This function is used to delete an element from the circular queue. In a queue,
the element is always deleted from front position.
Check whether queue is empty or not means front == NULL.
If it is empty then display Queue is empty. If queue is not empty then, Check if (front==rear) if
it is true then set front = rear = NULL else move the front forward in queue, update address of
front in rear node and return the element.
Code :

#Circular queue using linked list ; Roll no. 160121733008


class Node:
def __init__(self):
self.data = None
self.link = None
class Queue:
def __init__(self):
front = None
rear = None
def enQueue(q, value):
temp = Node()
temp.data = value
if (q.front == None):
q.front = temp
else:
q.rear.link = temp
q.rear = temp
q.rear.link = q.front
def deQueue(q):
if (q.front == None):
int("Queue is empty")
return
value = None
if (q.front == q.rear):
value = q.front.data
q.front = None
q.rear = None
else:
temp = q.front
value = temp.data
q.front = q.front.link
q.rear.link = q.front
return value
def displayQueue(q):
temp = q.front
print("Elements in Circular Queue are: ",end = " ")
while (temp.link != q.front):
print(temp.data, end = " ")
temp = temp.link
print(temp.data)

q = Queue()
q.front = q.rear = None
enQueue(q, 14)
enQueue(q, 22)
enQueue(q, 6)
enQueue(q, 9)
enQueue(q, 20)
displayQueue(q)
print("Deleted element = ", deQueue(q))
print("Deleted value = ", deQueue(q))
displayQueue(q)

Output :
Conclusion : A circular queue was created using a linked list and enqueue and dequeue
operations were performed on it.
Radix Sort using Queues

Aim : To perform radix sort on the given list of elements using queues.

Algorithm :
1. The maximum element in the given list is found first and the number of digits in the
maximum elements is found.
2. Then, we iterate through the digits of each element, from least significant digit to most
significant digit.
3. The elements are then placed in the queue according to the value of the digit being
considered in the respective iteration.
4. The least element is stored at the beginning of the queue and the greatest element is stored at
the end of the queue.

Code :
//Radix sort using queues; Roll no. 160121733008
#include<stdio.h>
#include<stdlib.h>
int arr[15];
struct node
{
int data;
struct node *next;
struct node *prev;
}*front,*rear,*temp;
void read(int n){
for(int i=0;i<n;i++){
scanf("%d",&arr[i]);
}
return;
}
void print(int n){
for(int i=0;i<n;i++){
printf("%d ",arr[i]);
}
printf("\n");
return;
}
int find_max(int n){
int max=arr[0];
for(int i=0;i<n;i++){
if(arr[i]>max){
max=arr[i];
}
}
return max;
}
int main(){
int z,i,j,max,dig=0,d=1,k;
printf("Enter the no. of elements : ");
scanf("%d",&z);
printf("\nEnter the elements of the list : \n");
read(z);
printf("The given list is : ");
print(z);
max=find_max(z);
while(max!=0){
dig++;
max=max/10;
}
for(j=0;j<dig;j++){
k=0;
front=0;
rear=0;
for(i=0;i<z;i++){
struct node *n;
n=(struct node*)malloc(sizeof(struct node));
n->data=arr[i];
n->next=0;
n->prev=0;
if(front==0 && rear==0){
front=rear=n;
}
else{
int p=((n->data)/d)%10;
int l=((front->data)/d)%10;
int m=((rear->data)/d)%10;
if(p<l){
n->next=front;
front->prev=n;
front=n;
}
else if(p>=m){
rear->next=n;
n->prev=rear;
rear=n;
}
else{
temp=front;
while(temp!=0){
l=((temp->data)/d)%10;
if(p<l){
break;
}
temp=temp->next;
}
n->next=temp;
n->prev=temp->prev;
n->prev->next=n;
temp->prev=n;
}
}
}
temp=front;
while(temp!=0){
arr[k]=temp->data;
k++;
temp=temp->next;
}
d=d*10;
}
printf("\nThe sorted list is : ");
print(z);
}
Output :

Test Case 1 :
Test Case 2 :

Conclusion : The given list of elements were sorted using radix sort algorithm using queues.

You might also like