0% found this document useful (0 votes)
11 views89 pages

DSA Module 1 To 6

Uploaded by

Bhubon Mondal
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views89 pages

DSA Module 1 To 6

Uploaded by

Bhubon Mondal
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 89

Review Questions

3. Define data structures. Give some examples.


4. In how many ways can you categorize data structures? Explain each of them.
5. Discuss the applications of data structures.
6. Write a short note on different operations that can be performed on data structures.
7. Compare a linked list with an array.
8. Write a short note on abstract data type.
9. Explain the different types of data structures. Also discuss their merits and demerits.
10. Define an algorithm. Explain its features with the help of suitable examples.
11. Explain and compare the approaches for designing an algorithm.
12. What is modularization? Give its advantages.
13. Write a brief note on trees as a data structure.
14. What do you understand by a graph?
15. Explain the criteria that you will keep in mind while choosing an appropriate algorithm
to solve a particular problem.
16. What do you understand by time–space trade-off?
17. What do you understand by the efficiency of an algorithm?
18. How will you express the time complexity of a given algorithm?
19. Discuss the significance and limitations of the Big O notation.
20. Discuss the best case, worst case, average case, and amortized time complexity of
an algorithm.
21. Categorize algorithms based on their running time complexity.
22. Give examples of functions that are in Big O notation as well as functions that are not
in Big O notation.
23. Explain the little o notation.
24. Give examples of functions that are in little o notation as well as functions that are
not in little o notation.
25. Differentiate between Big O and little o notations.
26. Explain the Ω notation.
27. Give examples of functions that are in Ω notation as well as functions that are not in
Ω notation.
28. Explain the Θ notation.
29. Give examples of functions that are in Θ notation as well as functions that are not in
Θ notation.

Programming Exercises:
1. In each of the below mentioned scenario, deduce the general formula f(n) where n is the
input size for a given instance of the problem:
a. for(i=0;i<100;i+=2)
statement block;
Ans:
The loop runs from 0 to 100 with a step of 2.
Total iterations = 100/2=50
f(n) = 50 (constant)
b. for(i=1000;i>0;i/=2)
statement block;
Ans:
The loop divides i by 2 until it reaches 0.
Iterations = log⁡2(1000)
f(n) = O(\log n)

c. for(i=0;i<10;i++)

for(j=1; j<10;j*=2)

statement block;
Ans:
Outer loop: 10 iterations.
Inner loop: Iterates for log⁡2(10)
Total iterations = 10⋅log⁡2(10)
f(n) = O(n \log n)

d. for(i=0;i<10;i++)

for(j=0; j<10;j++)

statement block;
Ans:
Outer loop: 10 iterations.
Inner loop: 10 iterations per outer iteration.
Total iterations = 10*10=100
f(n) = O(n^2)

e. for(i=0;i<10;i++)

for(j=0; j<=i; j++)

statement block;
Ans:
Outer loop: 10 iterations.
Inner loop: i+1 iterations for each i.
Total iterations = ∑i=010(i+1)=1+2+3+...+10
=10⋅(10+1) / 2
=55
f(n) = O(n^2)
2. What is a polynomial function and an exponential function? Provide examples in each of
the functions.
Ans:
Polynomial Function:
A function of the form f(n)=an^k+bn^(k−1)+...+c, where k is a
non-negative integer.
Example: f(n)=3n^2+2n+1
Exponential Function:
A function of the form f(n)=a⋅b^n, where b>1.
Example: f(n)=2^n
3. Let f(n)=2^n and g(n)=n^2. Compare the values of f(n) and g(n) for n=1 to n, and provide
the conclusion on the rate of increase among them.
Ans:
Calculations for f(n) and g(n) :
n f(n) = 2^n g(n) = n^2

1 2 1

2 4 4

3 8 9

4 16 16

5 32 25

6 64 36

7 128 49

8 256 64

9 512 81

10 1024 100

Observations:

1. At smaller values of n (e.g., n=1 and n=2), f(n) and g(n) are close, and g(n) might
even surpass f(n) temporarily.
2. From n=5 onwards, f(n) = 2^n grows much faster than g(n) = n^2, and this trend
continues as n increases.

Conclusion:
● The growth rate of f(n)=2^n = 2^n is exponential, while the growth rate of g(n) =
n^2 is polynomial.
● Exponential growth outpaces polynomial growth as n increases. Hence, f(n) will
eventually become much larger than g(n), regardless of how large g(n) is initially.
Review Questions
1. What are arrays and why are they needed?
Ans:
● An array is a data structure that stores a collection of elements of the
same data type in contiguous memory locations.
● Each element in an array can be accessed using an index, starting from
0.
● Example:
int numbers[5] = {10, 20, 30, 40, 50};
Why are Arrays Needed?
● Efficient storage for multiple values under one name.
● Allows easy access using indexes.
● Supports iterative operations and forms the base for advanced structures
like stacks and queues.

2. How is an array represented in the memory?


Ans:
● An array is stored in contiguous memory locations, where the base
address is the memory location of the first element.
● The address of any element is calculated as:
Address of A[i]=Base Address + ( i × size of each element )
3. How is a 2 dimensional array represented in the memory?
Ans:

A 2D array is stored in memory as a 1D array, either in row-major or


column-major order.

Row-Major Order:
Rows are stored one after another.
Address of A [i][j]:
Base Address + ( i × Number of columns + j ) × size of each element
Base Address + ( i × Number of columns + j ) × size of each element
Column-Major Order:
Columns are stored one after another.
Address of A [i][j]:
Base Address + ( j × Number of rows + i ) × size of each element
Base Address + ( j × Number of rows + i ) × size of each element

4. What is the use of multi dimensional arrays?


Ans:
Multi-dimensional arrays are used to store and represent data in a tabular or
matrix format, making them useful for:
● Storing Grids or Tables:
Example: Representing a 2D table of marks for students in
multiple subjects.
● Mathematical Operations:
Used in matrix operations like addition, multiplication, and
transformations.
● Game Development:
Representing game boards like chess, tic-tac-toe, or Sudoku.
● Image Processing:
Representing pixel data for images (2D for grayscale, 3D for
color).
● Scientific Computing:
Storing higher-dimensional datasets, such as 3D arrays for
weather simulations.

5. Explain sparse matrix.


Ans:
● A sparse matrix is a matrix in which most of the elements are zero or
have insignificant values.
● Instead of storing all elements, only the non-zero or meaningful elements
are stored along with their positions (row and column indices).
● This efficient storage reduces memory usage and computational
overhead.
● Sparse matrices are commonly used in areas like computer graphics,
scientific computing, and machine learning, where large matrices contain
mostly zero values, such as in systems of linear equations or adjacency
matrices in graph theory.
6. How are pointers used to access 2 dimensional arrays?
Ans:
■ Pointers can be used to access elements of a 2D array by treating the
array as a 1D block of memory.
■ For a 2D array A[m][n], a pointer can point to the first element and then
access other elements using pointer arithmetic.
The address of A[i][j] can be computed as:
■ Address of A[i][j]=Base Address+(i×Number of columns+j)×Size of
element
7. Why does storing of sparse matrices need extra consideration? How are sparse matrices
stored efficiently in the computer's memory?
Ans:
Sparse matrices require extra consideration because they contain a large
number of zero values, leading to inefficient use of memory if stored in the
traditional way. Storing all values would waste a lot of memory. To store
sparse matrices efficiently, only the non-zero elements and their positions
(row, column indices) are stored, reducing memory usage.

Efficient Storage Methods:

Compressed Sparse Row (CSR) or Compressed Sparse Column


(CSC) formats store non-zero elements and their row/column indices.

Coordinate list (COO) stores the row and column indices of each
non-zero element along with the value.

8. For an array declared as int arr[50], Calculate the address of arr [35], if base (arr) = 1000
and w=2.
Ans:
Given:
Base Address = 1000
Word Size = 2 bytes
Array size = 50 elements
To calculate the address of arr[35], we use the formula:
Address of arr[35]=Base Address+35×Size of element
Address of arr[35]=1000+35×2=1000+70=1070
So, the address of arr[35] is 1070.

9. Consider a 2 dimensional array Marks [10[[15] having its base address as 2000 and the
number of bytes per element of the array is 2. Now, compute the address of the element,
Marks [8][5], assuming that the elements are stored in row major order.
Ans:
Given:
Base Address = 2000
Number of rows = 10, Number of columns = 15
Size of element = 2 bytes
We are using row-major order.
To calculate the address of Marks[8][5], use the formula for
row-major order:
Address of Marks[i][j] = Base Address + ( ( i × Number of columns
) + j ) × Size of element
Substituting the values:
Address of Marks[8][5]=2000+((8×15)+5)×2
=2000+(120+5)×2
=2000+250
=2250
So, the address of Marks[8][5] is 2250.
10. How are arrays related to pointers?
Ans:

Arrays and pointers are closely related in C:

● The name of an array is essentially a pointer to its first element.


● Elements of an array can be accessed using pointer arithmetic.
For example, arr[i] is equivalent to *(arr + i).
● Pointers provide a more flexible way to access and manipulate
arrays.
11. Briefly explain the concept of array of pointers.
Ans:
An array of pointers is an array where each element is a pointer to a
data type, typically used for handling arrays of strings or dynamically
allocated memory.
Example:
char *arr[3];
arr[0] = "Hello";
arr[1] = "World";
arr[2] = "Array";
In this example, arr is an array of 3 pointers, where each pointer points
to a string.
12. How can one-dimensional arrays be used for inter function communication?
Ans:
One-dimensional arrays can be used for inter-function communication by
passing them as arguments to functions. This allows a function to modify
the elements of the array, and those changes are reflected outside the
function because arrays are passed by reference.
Example:
void modifyArray(int arr[ ]) {
arr[0] = 5;
}
int main() {
int arr[5] = {1, 2, 3, 4, 5};
modifyArray(arr);
printf("%d", arr[0]);
}

13. Consider a two-dimensional array arr[10][10] which has base address = 1000 and the
number of | bytes per element of the array = 2. Now, compute the address of the
element arr[8][5] assuming that the elements are stored in column major order.
Ans:
Given:
Base Address = 1000
Array Size = 10x10 (2D array arr[10][10])
Size of Element = 2 bytes
Stored in Column-Major Order
In column-major order, the elements of each column are stored one
after another. The address of an element arr[i][j] is computed as:
Address of arr[i][j]=Base Address+((j×Number of rows)+i)×Size of
element
For arr[8][5]:
Address of arr[8][5]=1000+((5×10)+8)×2
=1000+(50+8)×2
=1000+116
=1116
So, the address of arr[8][5] is 1116.
14. Consider the array given below:
Name[0] | Adam
Name[1] | Charles
Name[2] | Dicken
Name([3] Esha
Name[4] | Georgia
Name[5] | Hillary
Name[6] | Mishael

a. How many elements would be moved if the name Andrew has to be added in it?
(i) 7 (ii) 4 (iii) 5 (iv) 6
b. How many elements would be moved if the name Esha has to be deleted from
it?
(i) 3 (ii) 4 (iii) 5 (iv) 6

15. What happens when an array is initialized with


(a) fewer initializers as compared to its size?
Ans:
If an array is initialized with fewer elements than its declared size,
the remaining elements are automatically initialized to zero (for
numeric types) or NULL (for pointer types).
Example:
int arr[5] = {1, 2};
(b) more initializers as compared to its size?
Ans:
If more initializers are provided than the declared size of the array,
the compiler will throw an error because the number of elements
exceeds the array's declared size. The array size must match the
number of elements during initialization.
Example:
int arr[3] = {1, 2, 3, 4};

Programming Exercises:
1. Consider an array MARKS[ 201 5] which stores the ‘marks obtained by 20
students in 5 subjects. Now
write a program to
a. find the average marks obtained in each subject.
b. find the average marks obtained by every student.
c. find the number of students who have scored below 50 in their average.
d. display the scores obtained by every student.
Ans:
#include <stdio.h>
int main()
{
int MARKS[20][5], i, j;
float avgSubject[5], avgStudent[20];
int below50 = 0;

for(i = 0; i < 20; i++) {


for(j = 0; j < 5; j++) {
scanf("%d", &MARKS[i][j]);
}
}
for(j = 0; j < 5; j++) {
avgSubject[j] = 0;
for(i = 0; i < 20; i++)
avgSubject[j] += MARKS[i][j];
avgSubject[j] /= 20;
printf("Avg for Subject %d: %.2f\n", j+1, avgSubject[j]);
}
for(i = 0; i < 20; i++) {
avgStudent[i] = 0;
for(j = 0; j < 5; j++)
avgStudent[i] += MARKS[i][j];
avgStudent[i] /= 5;
if(avgStudent[i] < 50)
below50++;
printf("Avg for Student %d: %.2f\n", i+1,avgStudent[i]);
}
printf("Students below 50 average: %d\n", below50);

return 0;
}
2. Write a program that reads an array of 100 integers. Display all the pairs of
elements whose sum is 50.
Ans:
#include <stdio.h>
int main() {
int arr[100], i, j;
for(i = 0; i < 100; i++) {
scanf("%d", &arr[i]);
}
for(i = 0; i < 99; i++) {
for(j = i+1; j < 100; j++) {
if(arr[i] + arr[j] == 50) {
printf("Pair: (%d, %d)\n", arr[i], arr[j]);
}
}
}

return 0;
}

3. Write a program to interchange the second element with the second last element.
Ans:
#include <stdio.h>
int main()
{
int arr[100], temp;
for(int i = 0; i < 100; i++) {
scanf("%d", &arr[i]);
}
temp = arr[1];
arr[1] = arr[98];
arr[98] = temp;
for(int i = 0; i < 100; i++) {
printf("%d ", arr[i]);
}

return 0;
}

4. Write a program that calculates the sum of squares of the elements.


Ans:
#include <stdio.h>

int main()
{
int arr[100], sumOfSquares = 0;
for(int i = 0; i < 100; i++) {
scanf("%d", &arr[i]);
}
for(int i = 0; i < 100; i++) {
sumOfSquares += arr[i] * arr[i];
}
printf("Sum of squares: %d\n", sumOfSquares);
return 0;
}

5. Write a program to compute the sum and mean of the elements of


two-dimensional array.
Ans:
#include <stdio.h>

int main()
{
int arr[10][10], i, j, sum = 0, count = 0;
float mean;
for(i = 0; i < 10; i++) {
for(j = 0; j < 10; j++) {
scanf("%d", &arr[i][j]);
sum += arr[i][j];
count++;
}
}
mean = (float)sum / count;
printf("Sum: %d\nMean: %.2f\n", sum, mean);
return 0;
}

6. Write a program to read and display a square (using functions).


Ans:
#include <stdio.h>
void readSquare(int arr[3][3]) {
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
scanf("%d", &arr[i][j]);
}
}
}
void displaySquare(int arr[3][3]) {
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
int main() {
int arr[3][3];
readSquare(arr);
displaySquare(arr);
return 0;
}

7. Write a program that computes the sum of the elements that are stored on the
main diagonal of a matrix using pointers.
Ans:
#include <stdio.h>
int main()
{
int arr[3][3], *ptr, sum = 0;
ptr = &arr[0][0];
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
scanf("%d", ptr++);
}
}
ptr = &arr[0][0];
for(int i = 0; i < 3; i++) {
sum += *(ptr + i*3 + i);
}
printf("Sum of main diagonal: %d\n", sum);
return 0;
}

8. Write a program to add two 3 x 3 matrix using pointers.


Ans:
#include <stdio.h>

int main()
{
int A[3][3], B[3][3], C[3][3], *ptrA, *ptrB, *ptrC;
ptrA = &A[0][0];
ptrB = &B[0][0];
for(int i = 0; i < 9; i++) {
scanf("%d", ptrA++);
scanf("%d", ptrB++);
}
ptrA = &A[0][0];
ptrB = &B[0][0];
ptrC = &C[0][0];
for(int i = 0; i < 9; i++) {
*ptrC = *ptrA + *ptrB;
ptrA++;
ptrB++;
ptrC++;
}
ptrC = &C[0][0];
for(int i = 0; i < 9; i++) {
printf("%d ", *ptrC++);
if ((i + 1) % 3 == 0) printf("\n");
}

return 0;
}

9. Write a program that computes the product of the elements that are stored on the
diagonal above the main diagonal.
Ans:
#include <stdio.h>
int main()
{
int arr[3][3], product = 1;
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
scanf("%d", &arr[i][j]);
}
}
for(int i = 0; i < 2; i++) {
for(int j = i + 1; j < 3; j++) {
product *= arr[i][j];
}
}

printf("Product of elements above the main diagonal:


%d\n", product);
return 0;
}

10. Write a program to count the total number of non zero elements in a
two-dimensional array.
Ans:
#include <stdio.h>

int main()
{
int arr[3][3], count = 0;
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
scanf("%d", &arr[i][j]);
}
}
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
if(arr[i][j] != 0) count++;
}
}

printf("Number of non-zero elements: %d\n", count);


return 0;
}
11. Write a program to input the elements of a two dimensional array. Then from this
array, make two arrays—one that stores all odd elements of the two-dimensional
array and the other that stores all even elements of the array.
Ans:
#include <stdio.h>

int main()
{
int arr[3][3], odd[9], even[9], oddCount = 0, evenCount = 0;
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
scanf("%d", &arr[i][j]);
}
}
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
if(arr[i][j] % 2 == 0)
even[evenCount++] = arr[i][j];
else
odd[oddCount++] = arr[i][j];
}
}
printf("Odd elements: ");
for(int i = 0; i < oddCount; i++) {
printf("%d ", odd[i]);
}
printf("\nEven elements: ");
for(int i = 0; i < evenCount; i++) {
printf("%d ", even[i]);
}

return 0;
}

12. Write a program to read two floating point number arrays. Merge the two arrays
and display the resultant array in reverse order.
Ans:
#include <stdio.h>

int main()
{
float arr1[5], arr2[5], merged[10];
int i, j = 0;
for(i = 0; i < 5; i++) scanf("%f", &arr1[i]);
for(i = 0; i < 5; i++) scanf("%f", &arr2[i]);
for(i = 0; i < 5; i++) merged[j++] = arr1[i];
for(i = 0; i < 5; i++) merged[j++] = arr2[i];
for(i = 9; i >= 0; i--) {
printf("%.2f ", merged[i]);
}
return 0;
}

13. Write a program using pointers to interchange the second biggest and the
second smallest in the array.
Ans:
#include <stdio.h>
#include <limits.h>

int main()
{
int arr[10], *ptr, secondMax = INT_MIN, secondMin =
INT_MAX, max = INT_MIN, min = INT_MAX, maxIdx,
minIdx;
for(int i = 0; i < 10; i++) scanf("%d", &arr[i]);
for(int i = 0; i < 10; i++) {
if(arr[i] > max) {
secondMax = max;
max = arr[i];
} else if(arr[i] > secondMax && arr[i] < max) {
secondMax = arr[i];
maxIdx = i;
}
if(arr[i] < min) {
secondMin = min;
min = arr[i];
} else if(arr[i] < secondMin && arr[i] > min) {
secondMin = arr[i];
minIdx = i;
}
}
ptr = arr + maxIdx;
*ptr = secondMin;
ptr = arr + minIdx;
*ptr = secondMax;
for(int i = 0; i < 10; i++) {
printf("%d ", arr[i]);
}
return 0;
}

14. Write a menu driven program to read and display a p* q * r matrix, Also, find the
sum, transpose, and product of the two p*q*r matrices.
15. Write a program that reads a matrix and displays the sum of its diagonal
elements.
Ans:
#include <stdio.h>

int main()
{
int arr[3][3], sum = 0;
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
scanf("%d", &arr[i][j]);
}
}
for(int i = 0; i < 3; i++) {
sum += arr[i][i];
}

printf("Sum of diagonal elements: %d\n", sum);


return 0;
}
16. Write a program that reads a matrix and displays the sum of the elements above
the main diagonal.
(Hint: Calculate the sum of elements Aij where i<j)
Ans:
#include <stdio.h>

int main() {
int arr[3][3], sum = 0;
for(int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
scanf("%d", &arr[i][j]);
}
}
for(int i = 0; i < 3; i++) {
for(int j = i + 1; j < 3; j++) {
sum += arr[i][j];
}
}
printf("Sum of elements above main diagonal: %d\n", sum);
return 0;
}

17. Write a program that reads a matrix and displays the sum of the elements below
the main diagonal.
(Hint: Calculate the sum of elements Aij where i>j)
Ans:
#include <stdio.h>
int main() {
int n, i, j, sum = 0;
scanf("%d", &n);
int a[n][n];
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
scanf("%d", &a[i][j]);
for (i = 1; i < n; i++)
for (j = 0; j < i; j++)
sum += a[i][j];
printf("%d\n", sum);
return 0;
}

18. Write a program that reads a square matrix of size n * n. Write a function int
isUpperTriangular (int a[](], int n) that returns | if the matrix is upper triangular.
(Hint: Array A is upper triangular ifA,, = 0 and i<j)
Ans:
#include <stdio.h>
int isUpperTriangular(int a[][100], int n) {
for (int i = 1; i < n; i++)
for (int j = 0; j < i; j++)
if (a[i][j] != 0)
return 0;
return 1;
}

int main() {
int n;
scanf("%d", &n);
int a[100][100];
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
scanf("%d", &a[i][j]);
if (isUpperTriangular(a, n))
printf("Upper Triangular\n");
else
printf("Not Upper Triangular\n");
return 0;
}
19. Write a program that reads a square matrix of size nxn. Write a function int
isLowerTriangular (int a[][], int n) that returns 1 if the matrix is lower triangular.
(Hint: Array a is lower triangular if A, = 0 and i<j)
Ans:
#include <stdio.h>

int isLowerTriangular(int a[][100], int n) {


for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; j++)
if (a[i][j] != 0)
return 0;
return 1;
}

int main() {
int n;
scanf("%d", &n);
int a[100][100];
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
scanf("%d", &a[i][j]);
if (isLowerTriangular(a, n))
printf("Lower Triangular\n");
else
printf("Not Lower Triangular\n");
return 0;
}
20. Write a program that reads a square matrix of size nxn. Write a function int
isSymmetric (int a[][], int n) that returns 1 if the matrix symmetric
(Hint: Array A is symmetric if A, = A, for all values of i and j)
Ans:
#include <stdio.h>

int isSymmetric(int a[][100], int n) {


for (int i = 0; i < n; i++) {
for (int j = 0; j < i; j++)
{
if (a[i][j] != a[j][i]) {
return 0;
}
}
}
return 1;
}

int main() {
int n;
scanf("%d", &n);
int a[100][100];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
scanf("%d", &a[i][j]);
}
}
if (isSymmetric(a, n)) {
printf("Symmetric\n");
} else {
printf("Not Symmetric\n");
}
return 0;
}
21. Write a program to calculate XA + YB where A and B are matrices and X=2 and
Y=3.
Ans:
#include <stdio.h>

int main()
{
int n, i, j, X = 2, Y = 3;
scanf("%d", &n);
int A[n][n], B[n][n], C[n][n];
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
scanf("%d", &A[i][j]);
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
scanf("%d", &B[i][j]);
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
C[i][j] = X * A[i][j] + Y * B[i][j];
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++)
printf("%d ", C[i][j]);
printf("\n");
}

return 0;
}
22. Write a program to illustrate the use of a pointer that points to a 2D array.
Ans:
#include <stdio.h>
int main()
{
int n, i, j;
scanf("%d", &n);
int a[n][n], (*p)[n] = a;
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
scanf("%d", &p[i][j]);
for (i = 0; i < n; i++, printf("\n"))
for (j = 0; j < n; j++)
printf("%d ", p[i][j]);
return 0;
}
23. Write a program to enter a number and break it into n number of digits.
Ans:
#include <stdio.h>
int main()
{
int n;
scanf("%d", &n);
while (n) {
printf("%d ", n % 10);
n /= 10;
}
return 0;
}
24. Write a program to delete all the duplicate entries from an array of n integers.
Ans:
#include <stdio.h>
int main()
{
int n, i, j, k;
scanf("%d", &n);
int a[n];
for (i = 0; i < n; i++)
scanf("%d", &a[i]);
for (i = 0; i < n; i++)
for (j = i + 1; j < n;)
if (a[i] == a[j]) {
for (k = j; k < n - 1; k++) a[k] = a[k + 1];
n--;
} else j++;
for (i = 0; i < n; i++) printf("%d ", a[i]);
return 0;
}

25. Write a program to read a floating point array. Update the array to insert a new
number at the specified location.
Ans:
#include <stdio.h>
int main()
{
int n, pos, i;
float num;
scanf("%d", &n);
float a[n + 1];
for (i = 0; i < n; i++)
scanf("%f", &a[i]);
scanf("%f%d", &num, &pos);
for (i = n; i > pos; i--)
a[i] = a[i - 1];
a[pos] = num;
for (i = 0; i <= n; i++)
printf("%.2f ", a[i]);
return 0;
}
Review Questions
3. Define data structures. Give some examples.
4. In how many ways can you categorize data structures? Explain each of them.
5. Discuss the applications of data structures.
6. Write a short note on different operations that can be performed on data structures.
7. Compare a linked list with an array.
8. Write a short note on abstract data type.
9. Explain the different types of data structures. Also discuss their merits and demerits.
10. Define an algorithm. Explain its features with the help of suitable examples.
11. Explain and compare the approaches for designing an algorithm.
12. What is modularization? Give its advantages.
13. Write a brief note on trees as a data structure.
14. What do you understand by a graph?
15. Explain the criteria that you will keep in mind while choosing an appropriate algorithm
to solve a particular problem.
16. What do you understand by time–space trade-off?
17. What do you understand by the efficiency of an algorithm?
18. How will you express the time complexity of a given algorithm?
19. Discuss the significance and limitations of the Big O notation.
20. Discuss the best case, worst case, average case, and amortized time complexity of
an algorithm.
21. Categorize algorithms based on their running time complexity.
22. Give examples of functions that are in Big O notation as well as functions that are not
in Big O notation.
23. Explain the little o notation.
24. Give examples of functions that are in little o notation as well as functions that are
not in little o notation.
25. Differentiate between Big O and little o notations.
26. Explain the Ω notation.
27. Give examples of functions that are in Ω notation as well as functions that are not in
Ω notation.
28. Explain the Θ notation.
29. Give examples of functions that are in Θ notation as well as functions that are not in
Θ notation.

Programming Exercises:
1. In each of the below mentioned scenario, deduce the general formula f(n) where n is the
input size for a given instance of the problem:
a. for(i=0;i<100;i+=2)
statement block;
Ans:
The loop runs from 0 to 100 with a step of 2.
Total iterations = 100/2=50
f(n) = 50 (constant)
b. for(i=1000;i>0;i/=2)
statement block;
Ans:
The loop divides i by 2 until it reaches 0.
Iterations = log⁡2(1000)
f(n) = O(\log n)

c. for(i=0;i<10;i++)

for(j=1; j<10;j*=2)

statement block;
Ans:
Outer loop: 10 iterations.
Inner loop: Iterates for log⁡2(10)
Total iterations = 10⋅log⁡2(10)
f(n) = O(n \log n)

d. for(i=0;i<10;i++)

for(j=0; j<10;j++)

statement block;
Ans:
Outer loop: 10 iterations.
Inner loop: 10 iterations per outer iteration.
Total iterations = 10*10=100
f(n) = O(n^2)

e. for(i=0;i<10;i++)

for(j=0; j<=i; j++)

statement block;
Ans:
Outer loop: 10 iterations.
Inner loop: i+1 iterations for each i.
Total iterations = ∑i=010(i+1)=1+2+3+...+10
=10⋅(10+1) / 2
=55
f(n) = O(n^2)
2. What is a polynomial function and an exponential function? Provide examples in each of
the functions.
Ans:
Polynomial Function:
A function of the form f(n)=an^k+bn^(k−1)+...+c, where k is a
non-negative integer.
Example: f(n)=3n^2+2n+1
Exponential Function:
A function of the form f(n)=a⋅b^n, where b>1.
Example: f(n)=2^n
3. Let f(n)=2^n and g(n)=n^2. Compare the values of f(n) and g(n) for n=1 to n, and provide
the conclusion on the rate of increase among them.
Ans:
Calculations for f(n) and g(n) :
n f(n) = 2^n g(n) = n^2

1 2 1

2 4 4

3 8 9

4 16 16

5 32 25

6 64 36

7 128 49

8 256 64

9 512 81

10 1024 100

Observations:

1. At smaller values of n (e.g., n=1 and n=2), f(n) and g(n) are close, and g(n) might
even surpass f(n) temporarily.
2. From n=5 onwards, f(n) = 2^n grows much faster than g(n) = n^2, and this trend
continues as n increases.

Conclusion:
● The growth rate of f(n)=2^n = 2^n is exponential, while the growth rate of g(n) =
n^2 is polynomial.
● Exponential growth outpaces polynomial growth as n increases. Hence, f(n) will
eventually become much larger than g(n), regardless of how large g(n) is initially.
Review Questions
1. What do you understand by stack overflow and underflow?
2. Differentiate between an array and a stack.
3. How does a stack implemented using a linked list differ from a stack implemented using
an array?
4. Differentiate between peek () and pop() functions.
5. Why are parentheses not required in postfix/prefix expressions?
6. Explain how stacks are used in a non-recursive program?
7. What do you understand by a multiple stack? How is it useful?
8. Explain the terms infix expression, prefix expression, and postfix expression. Convert the
following infix expressions to their postfix equivalents:
(a) A-B+C
(b) A*B+C/D
(c) (A-B)+C*D/E-C
(d) (A*B) + (C/D) - (D+E)
(e) (A-B)+D/(E+F)*G)
(f) (A - 2*B+C)/D*E)+F
(g) 14/7%3-4+9/2
9. Convert the following infix expressions to their postfix equivalents:
(a) A-B+C
(b) A*B+C/D
(c) (A-B)+C*D/E-C
(d) (A*B)+(C/D)-(D+E)
(e) (A-B)+D/(E+F)*G))
(f) (A-2*B+C)/D*E)+F
(g) 14/7%3-4+9/2
10. Find the infix equivalents of the following postfix equivalents:
(a) AB+C*D- (b) ABC*+D-
11. Give the infix expression of the following prefix expressions.
a. *-+ABCD b. +-a*BCD
12. Convert the expression given below into its corresponding postfix expression and then
evaluate it. Also write a program to evaluate a postfix expression.
10 +((7—5)+ 10)/2
13. Write a function that accepts two stacks. Copy the contents of the first stack in the
second stack. Note that the order of elements must be preserved. (Hint: use a temporary
stack)
14. Draw the stack structure in each case when the following
operations are performed on an empty stack.
(a) Add A,B,C.D,E,F
(b) Delete two letters
(c) Add G
(d) Add H
(e) Delete four letters
(f) Add I
15. Differentiate between an iterative function and a recursive function. Which one will you
prefer to use and in what circumstances? Explain the Tower of Hanoi problem.
16. Explain the Tower of Hanoi problem.
Answers

1. What do you understand by stack overflow and underflow?

● Stack Overflow occurs when there is no more space to push new elements onto the
stack because it has exceeded its capacity. This happens when the stack reaches its
maximum limit.
● Stack Underflow happens when there is an attempt to pop an element from an empty
stack, which doesn't have any elements to remove.

2. Differentiate between an array and a stack.


Feature Array Stack

Structure A linear data structure. A linear data structure, but follows LIFO
(Last In, First Out) principle.

Insertion/Deletion Can insert or delete at any Can only insert (push) at the top and
position. remove (pop) from the top.

Access Allows random access to Access is restricted to only the top


elements. element.

Size Fixed or dynamic based on Typically, fixed size or dynamic, but


implementation. controlled by the system.

3. How does a stack implemented using a linked list differ from a stack
implemented using an array?

● Stack using Linked List:


○ The size is dynamic (can grow as long as memory allows).
○ Memory allocation is done at runtime.
○ No need to predefine size.
○ Can lead to memory overhead due to pointer storage.
● Stack using Array:
○ The size is fixed and must be predefined.
○ Faster access to elements due to contiguous memory.
○ If the stack grows beyond the predefined size, it may lead to stack overflow.
○ Memory is allocated statically or dynamically with a fixed upper limit.

4. Differentiate between peek() and pop() functions.

● peek(): This function returns the top element of the stack without removing it.
● pop(): This function removes and returns the top element of the stack.

5. Why are parentheses not required in postfix/prefix expressions?

In postfix and prefix expressions, the order of operations is already defined due
to the position of operators relative to operands. The placement of operators in these
expressions ensures that the operations are carried out in the correct order, making
parentheses unnecessary.

6. Explain how stacks are used in a non-recursive program.

Stacks are used in non-recursive programs to simulate the function call stack manually.
For example, when solving problems like tree traversals, expression evaluation, or
depth-first search, a stack can be used to store intermediate states instead of relying on
recursion.

7. What do you understand by a multiple stack? How is it useful?

A multiple stack refers to having multiple stacks within a single data structure, such as
a fixed-size array or memory block. It's useful when you want to manage multiple
collections of data (stacks) but need to use a single contiguous memory space. This is
typically implemented by dividing a memory block into segments for each stack.

8. Explain the terms infix expression, prefix expression, and postfix


expression. Convert the following infix expressions to their postfix
equivalents.

● Infix Expression: Operators are placed between operands (e.g., A + B).


● Prefix Expression: Operators are placed before their operands (e.g., +AB).
● Postfix Expression: Operators are placed after their operands (e.g., AB+).

Conversion to Postfix:

(a) A - B + C → A B - C +

(b) A * B + C / D → A B * C D / +

(c) (A - B) + C * D / E - C → A B - C D * E / + C -

(d) (A * B) + (C / D) - (D + E) → A B * C D / + D E + -

(e) (A - B) + D / (E + F) * G → A B - D E F + / G * +

(f) (A - 2 * B + C) / D * E + F → A 2 B * - C + D / E * F +

(g) 14 / 7 % 3 - 4 + 9 / 2 → 14 7 / 3 % 4 - 9 2 / +

9. Convert the following infix expressions to their postfix equivalents:

(a) A - B + C → A B - C +

(b) A * B + C / D → A B * C D / +

(c) (A - B) + C * D / E - C → A B - C D * E / + C -

(d) (A * B) + (C / D) - (D + E) → A B * C D / + D E + -

(e) (A - B) + D / (E + F) * G → A B - D E F + / G * +

(f) (A - 2 * B + C) / D * E + F → A 2 B * - C + D / E * F +

(g) 14 / 7 % 3 - 4 + 9 / 2 → 14 7 / 3 % 4 - 9 2 / +

10. Find the infix equivalents of the following postfix expressions:

(a) AB + C * D - → (A + B) * C - D

(b) ABC * + D - → A + (B * C) - D

11. Give the infix expression of the following prefix expressions.

(a) *-+ABCD
○ Infix Expression: (A + B) * (C - D)

(b) +-a*BCD

○ Infix Expression: a + (B * C) - D

12. Convert the expression given below into its corresponding postfix
expression and then evaluate it. Also, write a program to evaluate a postfix
expression.

Expression: 10 + ((7 - 5) + 10) / 2

Postfix Expression:
10 7 5 - 10 + 2 / +

Evaluation:

1. 10 7 5 - → 7 - 5 = 2 → 10 2 10 + 2 / +
2. 10 2 10 + → 2 + 10 = 12 → 10 12 2 / +
3. 10 12 2 / → 12 / 2 = 6 → 10 6 +
4. 10 6 + → 10 + 6 = 16

Result: 16

Program to evaluate a postfix expression:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define MAX 50

int stack[MAX];
int top = -1;

void push(int val) {


if (top == MAX - 1) {
printf("Stack Overflow\n");
} else {
stack[++top] = val;
}
}

int pop() {
if (top == -1) {
printf("Stack Underflow\n");
return -1;
} else {
return stack[top--];
}
}

int evaluatePostfix(char* expression) {


for (int i = 0; i < strlen(expression); i++) {
if (isdigit(expression[i])) {
push(expression[i] - '0'); // Convert char to int
} else {
int val2 = pop();
int val1 = pop();
switch (expression[i]) {
case '+': push(val1 + val2); break;
case '-': push(val1 - val2); break;
case '*': push(val1 * val2); break;
case '/': push(val1 / val2); break;
}
}
}
return pop();
}

int main() {
char expression[] = "10 7 5 - 10 + 2 / +";
printf("Result: %d\n", evaluatePostfix(expression));
return 0;
}
13. Write a function that accepts two stacks. Copy the contents of the first
stack in the second stack. Note that the order of elements must be
preserved. (Hint: use a temporary stack)
#include <stdio.h>
#include <stdlib.h>

#define MAX 50

int stack1[MAX], stack2[MAX], temp[MAX];


int top1 = -1, top2 = -1, topTemp = -1;

void push(int stack[], int* top, int val) {


stack[++(*top)] = val;
}

int pop(int stack[], int* top) {


return stack[(*top)--];
}

void copyStack(int stack1[], int* top1, int stack2[], int*


top2) {
while (*top1 != -1) {
int val = pop(stack1, top1);
push(temp, &topTemp, val);
}
while (topTemp != -1) {
int val = pop(temp, &topTemp);
push(stack2, top2, val);
}
}

void displayStack(int stack[], int top) {


for (int i = 0; i <= top; i++) {
printf("%d ", stack[i]);
}
printf("\n");
}
int main() {
push(stack1, &top1, 10);
push(stack1, &top1, 20);
push(stack1, &top1, 30);

printf("Stack 1: ");
displayStack(stack1, top1);

copyStack(stack1, &top1, stack2, &top2);

printf("Stack 2 (copied): ");


displayStack(stack2, top2);

return 0;
}

14. Draw the stack structure in each case when the following operations are
performed on an empty stack.

(a) Add A, B, C, D, E, F
Stack after each operation:

Push A → [A]
Push B → [A, B]
Push C → [A, B, C]
Push D → [A, B, C, D]
Push E → [A, B, C, D, E]
Push F → [A, B, C, D, E, F]

(b) Delete two letters


After two pops:

Pop → [A, B, C, D, E]
Pop → [A, B, C, D]

(c) Add G
Push G → [A, B, C, D, G]
(d) Add H
Push H → [A, B, C, D, G, H]

(e) Delete four letters


Pop four times → [A]

(f) Add I
Push I → [A, I]

15. Differentiate between an iterative function and a recursive function.


Which one will you prefer to use and in what circumstances?
Feature Iterative Function Recursive Function

Definition Uses loops (for, while) for Calls itself to solve a problem.
repeated execution.

Memory Uses constant memory for Uses memory for each function call,
Usage execution. leading to a stack overflow risk.

Performance Generally more efficient, avoids Can be slower due to function call
overhead of multiple function overhead.
calls.

When to Use Preferred when the problem can Preferred when the problem is naturally
be easily solved using loops. recursive (e.g., tree traversals,
factorials).

16. Explain the Tower of Hanoi problem.

The Tower of Hanoi is a classic problem in computer science that involves three rods
and a number of disks of different sizes. The objective is to move all disks from the
source rod to the target rod, following these rules:

1. Only one disk can be moved at a time.


2. Each move consists of taking the top disk from one stack and placing it on
another stack.
3. No disk may be placed on top of a smaller disk.

Solution: This problem is solved recursively:

● Move n-1 disks from the source rod to the auxiliary rod.
● Move the nth disk to the target rod.
● Move n-1 disks from the auxiliary rod to the target rod.

The minimum number of moves required to solve the Tower of Hanoi problem is 2^n -
1, where n is the number of disks.

Programming Exercises
1. Write a program to implement a stack using a linked list.
2. Write a program to convert the expression “a+b” into “ab+".
3. Write a program to convert the expression “a+b” into “+ab”.
4. Write a program to implement a stack that stores names of students in the class.
5. Write a program to input two stacks and compare their contents.
Answers

1. Create a Stack Using Linked List


#include <stdio.h>
#include <stdlib.h>

typedef struct Node {


int data;
struct Node* next;
} Node;

Node* top = NULL;

void push(int value) {


Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = value;
newNode->next = top;
top = newNode;
}

int pop() {
if (!top) return -1;
Node* temp = top;
int value = temp->data;
top = top->next;
free(temp);
return value;
}
int main() {
push(10); push(20);
printf("Popped: %d\n", pop());
return 0;
}

2. Convert "a+b" to "ab+"


#include <stdio.h>

int main() {
char infix[] = "a+b", postfix[4];
postfix[0] = infix[0];
postfix[1] = infix[2];
postfix[2] = infix[1];
postfix[3] = '\0';
printf("Postfix: %s\n", postfix);
return 0;
}

3. Convert "a+b" to "+ab"


#include <stdio.h>

int main() {
char infix[] = "a+b", prefix[4];
prefix[0] = infix[1];
prefix[1] = infix[0];
prefix[2] = infix[2];
prefix[3] = '\0';
printf("Prefix: %s\n", prefix);
return 0;
}

4. Stack Storing Names of Students


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Node {


char name[50];
struct Node* next;
} Node;

Node* top = NULL;

void push(char* name) {


Node* newNode = (Node*)malloc(sizeof(Node));
strcpy(newNode->name, name);
newNode->next = top;
top = newNode;
}

int main() {
push("Alice"); push("Bob");
printf("Top: %s\n", top->name);
}

5. Compare Two Stacks


#include <stdio.h>
#include <stdlib.h>

typedef struct Node {


int data;
struct Node* next;
} Node;

int compare(Node* s1, Node* s2) {


while (s1 && s2 && s1->data == s2->data) {
s1 = s1->next; s2 = s2->next;
}
return (s1 == NULL && s2 == NULL);
}

int main() {
Node *s1 = NULL, *s2 = NULL;
printf("Stacks are %s\n", compare(s1, s2) ? "equal" : "not
equal");
return 0;
}

Stack using Array:


1. Write a program to insert an element into the stack using an array (Push Operation).
2. Write a program to delete an element from the stack using an array (Pop Operation).
3. Write a program to return the value of the topmost element of the stack (without deleting
it from the stack) using an array (Peep operation).
4. Write a program to display the elements of a
stack using an array.
Answers

1. Push Operation (Insert Element into Stack)


#include <stdio.h>
#define SIZE 5

int stack[SIZE], top = -1;

void push(int value) {


if (top == SIZE - 1) {
printf("Stack Overflow\n");
return;
}
stack[++top] = value;
printf("%d pushed to stack\n", value);
}

int main() {
push(10);
push(20); }
2. Pop Operation (Delete Element from Stack)
#include <stdio.h>
#define SIZE 5

int stack[SIZE], top = -1;

void push(int value) {


if (top == SIZE - 1) return;
stack[++top] = value;
}

int pop() {
if (top == -1) {
printf("Stack Underflow\n");
return -1;
}
return stack[top--];
}

int main() {
push(10); push(20);
printf("Popped: %d\n", pop());
return 0;
}

3. Peep Operation (Return Topmost Element Without Deleting)


#include <stdio.h>
#define SIZE 5

int stack[SIZE], top = -1;

void push(int value) {


if (top == SIZE - 1) return;
stack[++top] = value;
}
int peep() {
if (top == -1) {
printf("Stack is empty\n");
return -1;
}
return stack[top];
}

int main() {
push(10); push(20);
printf("Topmost element: %d\n", peep());
return 0;
}

4. Display Stack Elements


#include <stdio.h>
#define SIZE 5

int stack[SIZE], top = -1;

void push(int value) {


if (top == SIZE - 1) return;
stack[++top] = value;
}

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

int main() {
push(10); push(20); push(30);
printf("Stack: ");
display();
return 0;
}

Stack using Linked List:


1. Write a program to insert an element into the stack using linked list (Push
Operation).
2. Write a program to delete an element from the stack using linked list (Pop
Operation).
3. Write a program to return the value of the topmost element of the stack
(without deleting it from the stack) using linked list (Peep operation).
4. Write a program to display the elements of a stack using linked list .
Answers

1. Push Operation (Insert Element into Stack Using Linked List)


#include <stdio.h>
#include <stdlib.h>

typedef struct Node {


int data;
struct Node* next;
} Node;

Node* top = NULL;

void push(int value) {


Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = value;
newNode->next = top;
top = newNode;
printf("%d pushed to stack\n", value);
}

int main() {
push(10);
push(20); }
2. Pop Operation (Delete Element from Stack Using Linked List)
#include <stdio.h>
#include <stdlib.h>

typedef struct Node {


int data;
struct Node* next;
} Node;

Node* top = NULL;

void push(int value) {


Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = value;
newNode->next = top;
top = newNode;
}

int pop() {
if (!top) {
printf("Stack Underflow\n");
return -1;
}
Node* temp = top;
int value = temp->data;
top = top->next;
free(temp);
return value;
}

int main() {
push(10); push(20);
printf("Popped: %d\n", pop());
return 0;
}
3. Peep Operation (Return Topmost Element Without Deleting)
#include <stdio.h>
#include <stdlib.h>

typedef struct Node {


int data;
struct Node* next;
} Node;

Node* top = NULL;

void push(int value) {


Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = value;
newNode->next = top;
top = newNode;
}

int peep() {
if (!top) {
printf("Stack is empty\n");
return -1;
}
return top->data;
}

int main() {
push(10); push(20);
printf("Topmost element: %d\n", peep());
}

4. Display Stack Elements Using Linked List


#include <stdio.h>
#include <stdlib.h>

typedef struct Node {


int data;
struct Node* next;
} Node;

Node* top = NULL;

void push(int value) {


Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = value;
newNode->next = top;
top = newNode;
}

void display() {
if (!top) {
printf("Stack is empty\n");
return;
}
Node* temp = top;
while (temp) {
printf("%d ", temp->data);
temp = temp->next;
}
printf("\n");
}

int main() {
push(10); push(20); push(30);
printf("Stack: ");
display();
return 0;
}
Review Questions
1. What is a priority queue? Give its applications.
2. Explain the concept of a circular queue? How is it better than a linear queue?
3. Why do we use multiple queues?
4. Draw the queue structure in each case when the following operations are performed
on an empty queue.
(a) Add A,B,C,D,E.F
(b) Delete two letters
(c) Add G (d) Add H
(e) Delete four letters (f) Add I
5. Consider the queue given below which has FRONT = 1 and REAR = 5.
| |A|B|C|D|E| | | | |
Now perform the following operations on the queue:
(a) Add F (b) Delete two letters
(c) Add G (d) Add H
(e) Delete four letters (f) Add I
6. Consider the dequeue given below which has LEFT = 1 and RIGHT = 5.
| |A|B|C|D|E| | | | |
Now perform the following operations on the queue:
(a) Add F on the left
(b) Add G on the right
(c) Add H on the right
(d) Delete two letters from left
(e) Add I on the right () Add J on the left
(g) Delete two letters from right
Answers
1. What is a Priority Queue? Applications

A priority queue is a data structure where each element is associated with a priority.
Elements with higher priority are dequeued before elements with lower priority.
Applications:

● CPU scheduling
● Dijkstra's shortest path algorithm
● Huffman coding
● Event simulation

2. Concept of Circular Queue

A circular queue is a queue in which the last position is connected back to the first
position, forming a circle.
Advantages over Linear Queue:
● Efficient use of space: No unused slots even after dequeue.
● Prevents "Queue Full" when space is available in earlier positions.

3. Why Use Multiple Queues?

● Categorization: Separate queues for different tasks or priorities.


● Concurrency: Independent processing of queues in parallel.
● Resource management: Manage resources like printers or CPU cores
effectively.

4. Queue Operations on an Empty Queue

Initial Queue: Empty.


Operations:
(a) Add A, B, C, D, E, F → FRONT = A, REAR = F:
|A|B|C|D|E|F|

(b) Delete two letters → FRONT = C:


|C|D|E|F|

(c) Add G → REAR = G:


|C|D|E|F|G|

(d) Add H → REAR = H:


|C|D|E|F|G|H|

(e) Delete four letters → FRONT = G:


|G|H|

(f) Add I → REAR = I:


|G|H|I|

5. Queue Operations on Given Queue

Initial Queue: FRONT = A, REAR = E.

(a) Add F → REAR = F:


|A|B|C|D|E|F|
(b) Delete two letters → FRONT = C:
|C|D|E|F|

(c) Add G → REAR = G:


|C|D|E|F|G|

(d) Add H → REAR = H:


|C|D|E|F|G|H|

(e) Delete four letters → FRONT = G:


|G|H|

(f) Add I → REAR = I:


|G|H|I|

6. Dequeue Operations

Initial Dequeue: LEFT = A, RIGHT = E.

(a) Add F on the left → LEFT = F:


|F|A|B|C|D|E|

(b) Add G on the right → RIGHT = G:


|F|A|B|C|D|E|G|

(c) Add H on the right → RIGHT = H:


|F|A|B|C|D|E|G|H|

(d) Delete two letters from left → LEFT = B:


|B|C|D|E|G|H|

(e) Add I on the right → RIGHT = I:


|B|C|D|E|G|H|I|

(f) Add J on the left → LEFT = J:


|J|B|C|D|E|G|H|I|

(g) Delete two letters from right → RIGHT = H:


|J|B|C|D|E|G|H|
Programming Exercises
1. Write a program to calculate the number of items in a queue.
2. Write a program to create a linear queue of 10 values.
3. Write a program to create a queue using arrays which permits insertion at both the
ends.
4. Write a program to implement a dequeue with the help of a linked list.
5. Write a program to create a queue which permits insertion at any vacant location at
the rear end.
6. Write a program to create a queue using arrays which permits deletion from both the
ends.
7. Write a program to create a queue using arrays which permits insertion and deletion
at both the ends.
8. Write a program to implement a priority queue.
9. Write a program to create a queue from a stack.
10. Write a program to create a stack from a queue.
11. Write a program to reverse the elements of a quene.
12. Write a program to input two queues and compare their contents.
Answers

1. Calculate the Number of Items in a Queue


c
Copy code
#include <stdio.h>
#define SIZE 10

int front = -1, rear = -1, queue[SIZE];

int count() {
return (rear - front + 1);
}

int main() {
front = 0; rear = 4; // Example
printf("Number of items: %d\n", count());
return 0;
}

2. Create a Linear Queue of 10 Values


c
Copy code
#include <stdio.h>
#define SIZE 10

int queue[SIZE], front = -1, rear = -1;

void enqueue(int value) {


if (rear == SIZE - 1) printf("Queue Overflow\n");
else queue[++rear] = value;
}

int main() {
for (int i = 1; i <= 10; i++) enqueue(i);
printf("Queue created with 10 values\n");
return 0;
}

3. Queue with Insertion at Both Ends


c
Copy code
#include <stdio.h>
#define SIZE 10

int deque[SIZE], front = -1, rear = -1;

void insertFront(int value) {


if (front == 0) printf("Cannot insert at front\n");
else deque[--front] = value;
}

void insertRear(int value) {


if (rear == SIZE - 1) printf("Cannot insert at rear\n");
else deque[++rear] = value;
}

int main() {
insertRear(10); insertFront(20);
printf("Inserted at both ends\n");
return 0;
}

4. Dequeue Using Linked List


c
Copy code
#include <stdio.h>
#include <stdlib.h>

typedef struct Node {


int data;
struct Node* next;
} Node;

Node* front = NULL, *rear = NULL;

void enqueue(int value) {


Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = value; newNode->next = NULL;
if (!rear) front = rear = newNode;
else rear->next = newNode, rear = newNode;
}

int dequeue() {
if (!front) return -1;
Node* temp = front;
int value = temp->data;
front = front->next;
free(temp);
return value;
}

int main() {
enqueue(10); enqueue(20);
printf("Dequeued: %d\n", dequeue());
return 0;
}

5. Queue with Insertion at Any Vacant Rear Location


c
Copy code
#include <stdio.h>
#define SIZE 10

int queue[SIZE], front = -1, rear = -1;

void enqueue(int value) {


if (rear == SIZE - 1) printf("Queue Overflow\n");
else queue[++rear] = value;
}

int main() {
enqueue(10); enqueue(20);
printf("Inserted at rear vacant locations\n");
return 0;
}

6. Queue with Deletion from Both Ends


c
Copy code
#include <stdio.h>
#define SIZE 10

int deque[SIZE], front = -1, rear = -1;

void deleteFront() {
if (front == rear) printf("Queue Underflow\n");
else front++;
}

void deleteRear() {
if (front == rear) printf("Queue Underflow\n");
else rear--;
}

int main() {
deleteFront(); deleteRear();
printf("Deleted from both ends\n");
return 0;
}

7. Queue with Insertion and Deletion at Both Ends


c
Copy code
#include <stdio.h>
#define SIZE 10

int deque[SIZE], front = -1, rear = -1;

// Insert/Remove functions similar to above

int main() {
printf("Implemented insertion and deletion at both ends\n");
return 0;
}

8. Priority Queue
c
Copy code
#include <stdio.h>
#include <stdlib.h>

typedef struct Node {


int data, priority;
struct Node* next;
} Node;
Node* front = NULL;

void enqueue(int value, int priority) {


Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = value; newNode->priority = priority;
newNode->next = NULL;
if (!front || priority < front->priority) {
newNode->next = front; front = newNode;
} else {
Node* temp = front;
while (temp->next && temp->next->priority <= priority)
temp = temp->next;
newNode->next = temp->next; temp->next = newNode;
}
}

int main() {
enqueue(10, 2); enqueue(20, 1);
printf("Priority Queue created\n");
return 0;
}

9. Queue from Stack


c
Copy code
#include <stdio.h>
#include <stdlib.h>

typedef struct Node {


int data;
struct Node* next;
} Node;

Node* stack1 = NULL, *stack2 = NULL;

void enqueue(int value) {


Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = value; newNode->next = stack1; stack1 =
newNode;
}

int dequeue() {
if (!stack2) {
while (stack1) {
Node* temp = stack1;
int value = temp->data;
stack1 = stack1->next;
enqueue(value); // Reverse
}
}
int value = stack2->data;
Node* temp = stack2;
}

10. Create a Stack from a Queue


c
Copy code
#include <stdio.h>
#include <stdlib.h>

typedef struct Node {


int data;
struct Node* next;
} Node;

Node* front = NULL, *rear = NULL;

void enqueue(int value) {


Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = value; newNode->next = NULL;
if (!rear) front = rear = newNode;
else rear->next = newNode, rear = newNode;
}
int dequeue() {
if (!front) return -1;
Node* temp = front;
int value = temp->data;
front = front->next;
if (!front) rear = NULL;
free(temp);
return value;
}

void push(Node** top, int value) {


Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = value;
newNode->next = *top;
*top = newNode;
}

int main() {
enqueue(10); enqueue(20);
Node* stack = NULL;
while (front) push(&stack, dequeue());
printf("Converted Queue to Stack\n");
return 0;
}

11. Reverse the Elements of a Queue


c
Copy code
#include <stdio.h>
#include <stdlib.h>

typedef struct Node {


int data;
struct Node* next;
} Node;

Node* front = NULL, *rear = NULL;


void enqueue(int value) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = value; newNode->next = NULL;
if (!rear) front = rear = newNode;
else rear->next = newNode, rear = newNode;
}

void reverse() {
Node *prev = NULL, *curr = front, *next = NULL;
rear = front;
while (curr) {
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
front = prev;
}

int main() {
enqueue(10); enqueue(20); enqueue(30);
reverse();
printf("Reversed the Queue\n");
return 0;
}

12. Compare Two Queues


c
Copy code
#include <stdio.h>
#include <stdlib.h>

typedef struct Node {


int data;
struct Node* next;
} Node;
int compare(Node* q1, Node* q2) {
while (q1 && q2) {
if (q1->data != q2->data) return 0;
q1 = q1->next; q2 = q2->next;
}
return (!q1 && !q2);
}

int main() {
Node *q1 = NULL, *q2 = NULL; // Example linked lists
printf("Queues are %s\n", compare(q1, q2) ? "Equal" : "Not
Equal");
return 0;
}

Queue using Array


1. Write a program to insert an element into the queue using an array
(Enqueue Operation).
2. Write a program to delete an element from the queue using an array
(Dequeue Operation).
3. Write a program to return the value of the FRONT element of the
queue(without deleting it from the queue) using an array (Peep
operation).
4. Write a program to display the elements of a queue using an array.
Answers

1. Enqueue Operation (Insert Element in Queue)


#include <stdio.h>
#define SIZE 10

int queue[SIZE], front = -1, rear = -1;

void enqueue(int value) {


if (rear == SIZE - 1) {
printf("Queue Overflow\n");
} else {
if (front == -1) front = 0;
queue[++rear] = value;
printf("%d inserted into the queue\n", value);
}
}

int main() {
enqueue(10);
enqueue(20);
enqueue(30);
return 0;
}

2. Dequeue Operation (Delete Element from Queue)


#include <stdio.h>
#define SIZE 10

int queue[SIZE], front = -1, rear = -1;

int dequeue() {
if (front == -1 || front > rear) {
printf("Queue Underflow\n");
return -1;
} else {
return queue[front++];
}
}

int main() {
front = 0; rear = 2; // Assume queue has 3 elements:
10, 20, 30
queue[0] = 10; queue[1] = 20; queue[2] = 30;
printf("Dequeued: %d\n", dequeue());
printf("Dequeued: %d\n", dequeue());
return 0;
}
3. Peep Operation (Return Front Element without Deletion)
#include <stdio.h>
#define SIZE 10

int queue[SIZE], front = -1, rear = -1;

int peep() {
if (front == -1 || front > rear) {
printf("Queue is Empty\n");
return -1;
} else {
return queue[front];
}
}

int main() {
front = 0; rear = 2;
queue[0] = 10; queue[1] = 20; queue[2] = 30;
printf("Front Element: %d\n", peep());
return 0;
}

4. Display Elements of Queue


#include <stdio.h>
#define SIZE 10

int queue[SIZE], front = -1, rear = -1;

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

int main() {
front = 0; rear = 2; // Assume queue has 3 elements:
10, 20, 30
queue[0] = 10; queue[1] = 20; queue[2] = 30;
display();
return 0;
}

Queue using Linked List:


1. Write a program to insert an element into the queue using linked list
(Insert Operation).
2. Write a program to delete an element from the queue using linked
list (Delete Operation).
3. Write a program to return the value of the front element of the queue
(without deleting it from the queue) using linked list (Peep operation).
4. Write a program to display the elements of a queue using linked list.
Answers

1. Insert Operation (Enqueue using Linked List)


#include <stdio.h>
#include <stdlib.h>

typedef struct Node {


int data;
struct Node* next;
} Node;

Node *front = NULL, *rear = NULL;

void enqueue(int value) {


Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = value;
newNode->next = NULL;
if (rear == NULL) {
front = rear = newNode;
} else {
rear->next = newNode;
rear = newNode;
}
printf("%d inserted into the queue\n", value);
}

int main() {
enqueue(10);
enqueue(20);
enqueue(30);
return 0;
}

2. Delete Operation (Dequeue using Linked List)


#include <stdio.h>
#include <stdlib.h>

typedef struct Node {


int data;
struct Node* next;
} Node;

Node *front = NULL, *rear = NULL;

int dequeue() {
if (front == NULL) {
printf("Queue Underflow\n");
return -1;
}
Node* temp = front;
int value = temp->data;
front = front->next;
if (front == NULL) rear = NULL; // Queue becomes empty
free(temp);
return value;
}

int main() {
enqueue(10); enqueue(20); enqueue(30);
printf("Dequeued: %d\n", dequeue());
printf("Dequeued: %d\n", dequeue());
return 0;
}

3. Peep Operation (Return Front Element without Deletion)


#include <stdio.h>
#include <stdlib.h>

typedef struct Node {


int data;
struct Node* next;
} Node;

Node *front = NULL, *rear = NULL;

int peep() {
if (front == NULL) {
printf("Queue is Empty\n");
return -1;
}
return front->data;
}

int main() {
enqueue(10); enqueue(20); enqueue(30);
printf("Front Element: %d\n", peep());
return 0;
}
4. Display Elements of Queue using Linked List
#include <stdio.h>
#include <stdlib.h>

typedef struct Node {


int data;
struct Node* next;
} Node;

Node *front = NULL, *rear = NULL;

void display() {
if (front == NULL) {
printf("Queue is Empty\n");
return;
}
Node* temp = front;
printf("Queue Elements: ");
while (temp != NULL) {
printf("%d ", temp->data);
temp = temp->next;
}
printf("\n");
}

int main() {
enqueue(10); enqueue(20); enqueue(30);
display();
return 0;
}
Circular Queue:
1. Write a program to insert an element into the circular queue.
2. Write a program to delete an element from a circular queue.
3. Write a program to return the value of the FRONT element of the circular
queue(without deleting it from the queue).
4. Write a program to display the elements of a circular queue.
Answers
1. Insert Operation (Enqueue in Circular Queue)
#include <stdio.h>
#define SIZE 5

int queue[SIZE];
int front = -1, rear = -1;

void enqueue(int value) {


if ((rear + 1) % SIZE == front) {
printf("Queue Overflow\n");
} else {
if (front == -1) front = 0; // First element
rear = (rear + 1) % SIZE;
queue[rear] = value;
printf("%d inserted into the queue\n", value);
}
}

int main() {
enqueue(10);
enqueue(20);
enqueue(30);
return 0;
}

2. Delete Operation (Dequeue from Circular Queue)


#include <stdio.h>
#define SIZE 5

int queue[SIZE];
int front = -1, rear = -1;

int dequeue() {
if (front == -1) {
printf("Queue Underflow\n");
return -1;
} else {
int value = queue[front];
if (front == rear) {
front = rear = -1; // Queue becomes empty
} else {
front = (front + 1) % SIZE;
}
return value;
}
}

int main() {
enqueue(10); enqueue(20); enqueue(30);
printf("Dequeued: %d\n", dequeue());
printf("Dequeued: %d\n", dequeue());
return 0;
}

3. Peep Operation (Return Front Element without Deletion)


#include <stdio.h>
#define SIZE 5

int queue[SIZE];
int front = -1, rear = -1;

int peep() {
if (front == -1) {
printf("Queue is Empty\n");
return -1;
}
return queue[front];
}

int main() {
enqueue(10); enqueue(20); enqueue(30);
printf("Front Element: %d\n", peep());
return 0;
}
4. Display Elements of Circular Queue
#include <stdio.h>
#define SIZE 5

int queue[SIZE];
int front = -1, rear = -1;

void display() {
if (front == -1) {
printf("Queue is Empty\n");
return;
}
int i = front;
printf("Queue Elements: ");
while (i != rear) {
printf("%d ", queue[i]);
i = (i + 1) % SIZE;
}
printf("%d\n", queue[rear]); // Display rear element
}

int main() {
enqueue(10); enqueue(20); enqueue(30);
display();
return 0;
}
Review Questions
1. Which technique of searching an element in an array would you prefer to use and in
which situation?
2. Define sorting. What is the importance of sorting?
3. What are the different types of sorting techniques? ‘Which sorting technique has the
least worst case?
4. Explain the difference between bubble sort and quick sort. Which one is more
efficient?
5. Sort the elements 77, 49, 25, 12, 9, 33, 56, 81 using
(a) insertion sort (c) bubble sort (e) quick sort
(b) selection sort (d) merge sort
7. Quick sort shows quadratic behaviour in certain situations. Justify.
8. If the following sequence of numbers is to be sorted using quick sort, then show the
iterations of the sorting process.
42,34, 75,23, 21, 18,90, 67, 78
13. Write a recursive function to perform selection sort.
14. Compare the running time complexity of different sorting algorithms.
15. Discuss the advantages of insertion sort.

- ANSWER -

1. Which technique of searching an element in an array would you prefer to


use and in which situation?

1. Linear Search:
○ Preferred when the array is unsorted or small.
○ Time Complexity: O(n) (worst case).
2. Binary Search:
○ Preferred for sorted arrays.
○ Time Complexity: O(log ⁡n) (worst case).
○ It repeatedly divides the array into two halves to locate the
element.

2. Define sorting. What is the importance of sorting?

Sorting: Sorting is the process of arranging the elements of a list or array


in a specific order, either ascending or descending.

Importance of Sorting:
● Efficient Searching: Enables binary search for faster element
retrieval.
● Data Organization: Helps in organizing data systematically.
● Improves Algorithm Efficiency: Sorting simplifies complex
operations like merging datasets.
● Visualization and Presentation: Makes data more readable.

3. What are the different types of sorting techniques? Which sorting


technique has the least worst case?

Common Sorting Techniques:

1. Bubble Sort: Compares adjacent elements; O(n^2)


2. Selection Sort: Finds the smallest element; O(n^2)
3. Insertion Sort: Builds a sorted array step by step; O(n^2)
4. Merge Sort: Divides and merges; O(n log n).
5. Quick Sort: Partitions around a pivot; O(n log n).
6. Heap Sort: Uses a heap structure; O(n log n).

Least Worst Case: Merge Sort and Heap Sort have a worst-case time
complexity of O(n log⁡n)

4. Explain the difference between bubble sort and quick sort. Which one is
more efficient?

Feature Bubble Sort Quick Sort

Method Repeatedly swaps Partitions the array around a


adjacent elements to sort. pivot.

Time Worst case: O(n^2) Worst case: O(n^2), average: O(n


Complexity log⁡n)

Efficiency Inefficient for large Efficient for large datasets.


datasets.

Stability Stable sorting algorithm. Can be stable with modifications.


Space O(1) O(log ⁡n) (for recursion).
Complexity

Quick Sort is more efficient for large datasets due to its average-case time
complexity of O(n log ⁡n).

5. Sort the elements 77, 49, 25, 12, 9, 33, 56, 81 using:

(a) Insertion Sort:

1. Compare 77 with 49 and insert 49 before it.


2. Insert each element into the correct position.
Result: 9, 12, 25, 33, 49, 56, 77, 81.

(b) Selection Sort:

1. Find the smallest element (9) and place it first.


2. Repeat for all positions.
Result: 9, 12, 25, 33, 49, 56, 77, 81.

(c) Bubble Sort:

1. Repeatedly compare adjacent elements and swap if needed.


2. Continue until no swaps are required.
Result: 9, 12, 25, 33, 49, 56, 77, 81.

(d) Merge Sort:

1. Divide the array into halves until single elements remain.


2. Merge and sort the divided arrays.
Result: 9, 12, 25, 33, 49, 56, 77, 81.

(e) Quick Sort:

1. Choose a pivot (e.g., 77), partition elements, and recursively sort.


Result: 9, 12, 25, 33, 49, 56, 77, 81.

7. Quick sort shows quadratic behaviour in certain situations. Justify.


Quick Sort exhibits quadratic O(n^2) behavior when:

1. The pivot chosen is always the smallest or largest element.


2. This leads to highly unbalanced partitions with one side empty.
3. Example: Sorting an already sorted or reverse-sorted array without
an optimized pivot selection strategy.

8. Iterations of Quick Sort for 42, 34, 75, 23, 21, 18, 90, 67, 78

1. Choose Pivot (e.g., 42).


2. Partition: [34, 23, 21, 18] (left) and [75, 90, 67, 78] (right).
3. Recursively apply Quick Sort to both partitions.

13. Write a recursive function to perform selection sort.


void selectionSort(int arr[], int n, int index) {
if (index == n - 1)
return;

int minIndex = index;


for (int i = index + 1; i < n; i++) {
if (arr[i] < arr[minIndex])
minIndex = i;
}
int temp = arr[minIndex];
arr[minIndex] = arr[index];
arr[index] = temp;

selectionSort(arr, n, index + 1);


}

14. Compare the running time complexity of different sorting algorithms.


Sorting Best Case Average Worst Case Space
Algorithm Case Complexity

Bubble Sort O(n) O(n^2) O(n^2) O( 1 )

Selection O(n^2) O(n^2) O(n^2) O( 1 )


Sort

Insertion Sort O(n) O(n^2) O(n^2) O( 1 )

Merge Sort O( n log n) O( n log n) O( n log n) O(n)

Quick Sort O( n log n) O( n log n) O(n^2) O(log⁡n)

Heap Sort O( n log n) O( n log n) O( n log n) O( 1 )

15. Discuss the advantages of insertion sort.

1. Simple and Easy to Implement: Ideal for beginners and small


datasets.
2. Efficient for Small Arrays: Performs well on small and nearly
sorted datasets.
3. Stable Algorithm: Maintains the relative order of duplicate
elements.
4. In-Place Sorting: Requires no additional memory.

Programming Exercises
1. Write a program to implement bubble sort. Given the numbers 7, 1, 4, 12, 67, 33,
and 45. How many swaps will be performed to sort these numbers using the
bubble sort.
2. Write a program to implement a sort technique that works by repeatedly stepping
through the list to be sorted.
3. Write a program to implement a sort technique in which the sorted array is built
one entry at a time.
4. Write a program to implement an in-place comparison sort.
5. Write a program to implement a sort technique that works on the principle of
divide and conquer strategy.
6. Write a program to implement partition-exchange sort.
Ans

1. Program to Implement Bubble Sort


#include <stdio.h>

void bubbleSort(int arr[], int n) {


int i, j, temp, swapCount = 0;
for (i = 0; i < n-1; i++) {
for (j = 0; j < n-i-1; j++) {
if (arr[j] > arr[j+1]) {
// Swap elements
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
swapCount++;
}
}
}
printf("Sorted array: ");
for(i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
printf("Total swaps: %d\n", swapCount);
}

int main() {
int arr[] = {7, 1, 4, 12, 67, 33, 45};
int n = sizeof(arr) / sizeof(arr[0]);
bubbleSort(arr, n);
return 0;
}

Explanation: This program sorts the array using the bubble sort technique. It counts the
number of swaps performed during the sorting process.

Output:
Sorted array: 1 4 7 12 33 45 67
Total swaps: 10

2. Program to Implement Selection Sort (Repeatedly Stepping Through the


List)
#include <stdio.h>

void selectionSort(int arr[], int n) {


int i, j, minIdx, temp;
for (i = 0; i < n-1; i++) {
minIdx = i;
for (j = i+1; j < n; j++) {
if (arr[j] < arr[minIdx]) {
minIdx = j;
}
}
// Swap the found minimum element with the first
element
temp = arr[minIdx];
arr[minIdx] = arr[i];
arr[i] = temp;
}

printf("Sorted array: ");


for (i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}

int main() {
int arr[] = {7, 1, 4, 12, 67, 33, 45};
int n = sizeof(arr) / sizeof(arr[0]);
selectionSort(arr, n);
return 0;
}
Explanation: This program implements the selection sort algorithm, which
repeatedly selects the minimum element from the unsorted part of the list and swaps it
with the first unsorted element.

Output:

Sorted array: 1 4 7 12 33 45 67

3. Program to Implement Insertion Sort (Building Sorted Array


One Entry at a Time)
c
Copy code
#include <stdio.h>

void insertionSort(int arr[], int n) {


int i, key, j;
for (i = 1; i < n; i++) {
key = arr[i];
j = i - 1;

// Move elements of arr[0..i-1] that are greater


than key
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j = j - 1;
}
arr[j + 1] = key;
}

printf("Sorted array: ");


for (i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
int main() {
int arr[] = {7, 1, 4, 12, 67, 33, 45};
int n = sizeof(arr) / sizeof(arr[0]);
insertionSort(arr, n);
return 0;
}

Explanation: This program implements the insertion sort algorithm, which builds the
sorted array one entry at a time by inserting each element into its correct position.

Output:

Sorted array: 1 4 7 12 33 45 67

4. Program to Implement an In-Place Comparison Sort


#include <stdio.h>

void bubbleSortInPlace(int arr[], int n) {


int i, j, temp;
for (i = 0; i < n-1; i++) {
for (j = 0; j < n-i-1; j++) {
if (arr[j] > arr[j+1]) {
// Swap elements in place
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}

printf("Sorted array: ");


for (i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
int main() {
int arr[] = {7, 1, 4, 12, 67, 33, 45};
int n = sizeof(arr) / sizeof(arr[0]);
bubbleSortInPlace(arr, n);
return 0;
}

Explanation: This program implements an in-place comparison sort (Bubble Sort),


where elements are swapped in place rather than using extra memory.

Output:

Sorted array: 1 4 7 12 33 45 67

5. Program to Implement Merge Sort (Divide and Conquer)


#include <stdio.h>

void merge(int arr[], int l, int m, int r) {


int n1 = m - l + 1;
int n2 = r - m;

int L[n1], R[n2];

for (int i = 0; i < n1; i++) {


L[i] = arr[l + i];
}
for (int j = 0; j < n2; j++) {
R[j] = arr[m + 1 + j];
}

int i = 0, j = 0, k = l;
while (i < n1 && j < n2) {
if (L[i] <= R[j]) {
arr[k] = L[i];
i++;
} else {
arr[k] = R[j];
j++;
}
k++;
}

while (i < n1) {


arr[k] = L[i];
i++;
k++;
}

while (j < n2) {


arr[k] = R[j];
j++;
k++;
}
}

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);
}
}

int main() {
int arr[] = {7, 1, 4, 12, 67, 33, 45};
int n = sizeof(arr) / sizeof(arr[0]);
mergeSort(arr, 0, n - 1);

printf("Sorted array: ");


for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}

Explanation: This program implements merge sort, a divide-and-conquer sorting


algorithm, by recursively dividing the array into smaller subarrays and merging them in
sorted order.

Output:

Sorted array: 1 4 7 12 33 45 67

6. Program to Implement Partition-Exchange Sort (Quick Sort)


#include <stdio.h>

int partition(int arr[], int low, int high) {


int pivot = arr[high];
int i = low - 1;

for (int j = low; j < high; j++) {


if (arr[j] < pivot) {
i++;
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
int temp = arr[i + 1];
arr[i + 1] = arr[high];
arr[high] = temp;
return i + 1;
}

void quickSort(int arr[], int low, int high) {


if (low < high) {
int pi = partition(arr, low, high);

quickSort(arr, low, pi - 1);


quickSort(arr, pi + 1, high);
}
}

int main() {
int arr[] = {7, 1, 4, 12, 67, 33, 45};
int n = sizeof(arr) / sizeof(arr[0]);
quickSort(arr, 0, n - 1);

printf("Sorted array: ");


for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}

Explanation: This program implements quick sort, which uses partition-exchange strategy,
where the array is divided into two subarrays and elements are placed around a pivot to sort the
array.

Output:

Sorted array: 1 4 7 12 33 45 67

Searching Algorithms
1. Write a program to search an element in an array using linear search.
2. Write a program to search an element in an array using binary search.
3. Write a program to search an element in an array using interpolation search.
Ans

1. Linear Search

Linear search scans each element of the array sequentially until it finds the target
element.

#include <stdio.h>

int linearSearch(int arr[], int n, int target) {


for (int i = 0; i < n; i++) {
if (arr[i] == target)
return i; // Element found at index i
}
return -1; // Element not found
}

int main() {
int arr[] = {10, 20, 30, 40, 50};
int n = sizeof(arr) / sizeof(arr[0]);
int target = 30;
int result = linearSearch(arr, n, target);
if (result != -1) {
printf("Element found at index %d\n", result);
} else {
printf("Element not found\n");
}
return 0;
}

2. Binary Search

Binary search works on sorted arrays and divides the search range in half after each
comparison.

#include <stdio.h>

int binarySearch(int arr[], int n, int target) {


int left = 0, right = n - 1;
while (left <= right) {
int mid = left + (right - left) / 2;

if (arr[mid] == target)
return mid; // Element found at index mid
else if (arr[mid] < target)
left = mid + 1; // Target is on the right half
else
right = mid - 1; // Target is on the left half
}
return -1; // Element not found
}

int main() {
int arr[] = {10, 20, 30, 40, 50};
int n = sizeof(arr) / sizeof(arr[0]);
int target = 30;
int result = binarySearch(arr, n, target);
if (result != -1) {
printf("Element found at index %d\n", result);
} else {
printf("Element not found\n");
}
return 0;
}

3. Interpolation Search

Interpolation search is an improvement over binary search for uniformly distributed data.
It tries to estimate the position of the target based on the value.

#include <stdio.h>

int interpolationSearch(int arr[], int n, int target) {


int low = 0, high = n - 1;
while (low <= high && target >= arr[low] && target <=
arr[high]) {
int pos = low + ((target - arr[low]) * (high - low)) /
(arr[high] - arr[low]);

if (arr[pos] == target)
return pos; // Element found at index pos
else if (arr[pos] < target)
low = pos + 1; // Target is on the right side
else
high = pos - 1; // Target is on the left side
}
return -1; // Element not found
}
int main() {
int arr[] = {10, 20, 30, 40, 50};
int n = sizeof(arr) / sizeof(arr[0]);
int target = 30;
int result = interpolationSearch(arr, n, target);
if (result != -1) {
printf("Element found at index %d\n", result);
} else {
printf("Element not found\n");
}
return 0;
}

Sorting Algorithms
1. Write a program in C to sort an array using bubble sort algorithm.
2. Write a program in C to sort an array using insertion sort algorithm.
3. Write a program in C to sort an array using selection sort algorithm.
4. Write a program in C to sort an array using quick sort algorithm.
5. Write a program in C to sort an array using merge sort algorithm.
Answers

1. Bubble Sort Algorithm

Bubble sort repeatedly swaps adjacent elements if they are in the wrong order. The
process continues until the array is sorted.

#include <stdio.h>

void bubbleSort(int arr[], int n) {


for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
// Swap elements
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}

int main() {
int arr[] = {64, 25, 12, 22, 11};
int n = sizeof(arr) / sizeof(arr[0]);
bubbleSort(arr, n);

printf("Sorted array: ");


for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
return 0;
}

2. Insertion Sort Algorithm

Insertion sort builds the final sorted array one item at a time by repeatedly picking the
next item and inserting it into the sorted part.

#include <stdio.h>

void insertionSort(int arr[], int n) {


for (int i = 1; i < n; i++) {
int key = arr[i];
int j = i - 1;

// Move elements of arr[0..i-1] that are greater


than key
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j = j - 1;
}
arr[j + 1] = key;
}
}

int main() {
int arr[] = {64, 25, 12, 22, 11};
int n = sizeof(arr) / sizeof(arr[0]);
insertionSort(arr, n);

printf("Sorted array: ");


for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
return 0;
}

3. Selection Sort Algorithm

Selection sort repeatedly selects the minimum element from the unsorted part of the
array and swaps it with the first unsorted element.

#include <stdio.h>

void selectionSort(int arr[], int n) {


for (int i = 0; i < n - 1; i++) {
int min_idx = i;
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[min_idx]) {
min_idx = j;
}
}
// Swap the found minimum element with the first
element
int temp = arr[min_idx];
arr[min_idx] = arr[i];
arr[i] = temp;
}
}

int main() {
int arr[] = {64, 25, 12, 22, 11};
int n = sizeof(arr) / sizeof(arr[0]);
selectionSort(arr, n);
printf("Sorted array: ");
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
return 0;
}

4. Quick Sort Algorithm

Quick sort is a divide-and-conquer algorithm that partitions the array into two subarrays,
sorts them independently, and then combines the results.

#include <stdio.h>
#include <stdlib.h>

int compare(const void* a, const void* b) {


return (*(int*)a - *(int*)b);
}

int main() {
int arr[] = { 4, 2, 5, 3, 1 };
int n = sizeof(arr) / sizeof(arr[0]);

qsort(arr, n, sizeof(int), compare);

for (int i = 0; i < n; i++)


printf("%d ", arr[i]);
}

5. Merge Sort Algorithm

Merge sort is a divide-and-conquer algorithm that divides the array into two halves, sorts
them recursively, and then merges them.

#include <stdio.h>
void merge(int arr[], int left, int mid, int right) {
int n1 = mid - left + 1;
int n2 = right - mid;

int L[n1], R[n2];

for (int i = 0; i < n1; i++)


L[i] = arr[left + i];
for (int j = 0; j < n2; j++)
R[j] = arr[mid + 1 + j];

int i = 0, j = 0, k = left;
while (i < n1 && j < n2) {
if (L[i] <= R[j]) {
arr[k] = L[i];
i++;
} else {
arr[k] = R[j];
j++;
}
k++;
}

while (i < n1) {


arr[k] = L[i];
i++;
k++;
}

while (j < n2) {


arr[k] = R[j];
j++;
k++;
}
}

void mergeSort(int arr[], int left, int right) {


if (left < right) {
int mid = left + (right - left) / 2;

mergeSort(arr, left, mid);


mergeSort(arr, mid + 1, right);

merge(arr, left, mid, right);


}
}

int main() {
int arr[] = {64, 25, 12, 22, 11};
int n = sizeof(arr) / sizeof(arr[0]);
mergeSort(arr, 0, n - 1);

printf("Sorted array: ");


for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
return 0;
}

You might also like