Ads Module1.Docx
Ads Module1.Docx
Integer: The integer datatype in C is used to store the integer numbers (any
number including positive, negative and zero without decimal part). Octal values,
hexadecimal values, and decimal values can be stored in int data type in C. Format
specifier for int is %d.
Syntax: int var_name;
Float: Float in C is used to store decimal and exponential values. It is used to
store decimal numbers (numbers with floating point values) with single precision.
Format specifier is %f.
Syntax: float var_name;
Char: Character data type allows its variable to store only a single character.
Format specifier is %c. Syntax: char var_name;
Boolean: The bool in C is a fundamental data type in most that can hold one of
two values: true or false. It is used to represent logical values and is commonly
used in programming to control the flow of execution in decision-making
statements such as if-else statements, while loops, and for loops.
1. Arrays:
It is a collection of elements of same data type stored at memory locations. It
is one of the most popular and simple data structures used in programming.
Basic terminologies:
● Array Index: In an array, elements are identified by their indexes. Array
index starts from 0.
● Array element: Elements are items stored in an array and can be accessed by
their index.
● Array Length: The length of an array is determined by the number of
elements it can contain.
Memory representation of Array
In an array, all the elements are stored in contiguous memory locations. So, if we
initialize an array, the elements will be allocated sequentially in memory.
Array elements
1 4 8 9 7 8
0 1 2 3 4 5
Array index
Declaration of array:
● int arr[5];
● char arr[10];
Initialization of array:
● int arr[] = { 1, 2, 3, 4, 5 };
● char arr[5] = { 'a', 'b', 'c', 'd', 'e' };
● float arr[10] = { 1.4, 2.0, 24, 5.0, 0.0 };
Types of arrays:
● Based on Size
● Based on dimension
Based on size:
● Fixed size arrays: We cannot alter or update the size of this array. Here
only a fixed size (i,e. the size that is mentioned in square brackets [])
of memory will be allocated for storage.
● Dynamic size arrays: The size of the array changes as per user
requirements during execution of code so the coders do not have to
worry about sizes. They can add and remove the elements as per the
need. The memory is mostly dynamically allocated and de-allocated
in these arrays.
Based on dimension:
● 1D array: Elements are stored one after the other.
● Multi-dimensional array: A multi-dimensional array is an array with
more than one dimension. We can use multidimensional array to store
complex data in the form of tables, etc. We can have 2-D arrays, 3-D
arrays, 4-D arrays and so on.
Operations on Array:
1. Array Traversal: Array traversal involves visiting all the elements of the
array once.
2. Insertion in array: We can insert one or multiple elements at any position in
the array.
3. Deletion in array: We can delete an element at any index in an array.
4. Searching in array: We can traverse over an array and search for an element.
Basic terminologies:
Node Structure: A node in a linked list typically consists of two components.
Those are node and next pointer or reference.
Data: It holds the actual value or data associated with the node.
Next Pointer or Reference: It stores the memory address (reference) of the next
node in the sequence.
Head: The linked list is accessed through the head node, which points to the first
node in the list.
Tail: The last node in the list points to NULL or nullptr, indicating the end of the
list. This node is known as the tail node.
3. Stack:
A Stack is a linear data structure that follows a particular order in which the
operations are performed. The order may be LIFO (Last In First Out) or FILO
(First In Last Out). LIFO implies that the element that is inserted last, comes out
first and FILO implies that the element that is inserted first, comes out last. It
behaves like a stack of plates, where the last plate added is the first one to be
removed.
Basic terminologies:
Front: It is also referred as the head of the queue. Position of the entry in a queue
ready to be served, that is, the first entry that will be removed from the queue, is
called the front of the queue.
Rear: Position of the last entry in the queue, that is, the one most recently added, is
called the rear of the queue. It is also referred as the tail of the queue.
Size: Size refers to the current number of elements in the queue.
Operations on Queue:
1. Enqueue: Insertion of elements to the queue.
Operation:
● Check if the queue is full.
● If the queue is full, return overflow error and exit.
● If the queue is not full, increment the rear pointer to point to the next empty
space.
● Add the data element to the queue location, where the rear is pointing.
● return success.
3. isEmpty(): This operation returns a Boolean value that indicates whether the
queue is empty or not.
Types of queues:
1. Simple queue: Simple Queue simply follows FIFO Structure. We can only
insert the element at the back and remove the element from the front of the
queue.
2. Double ended queue: In a double-ended queue the insertion and deletion
operations, both can be performed from both ends. They are of two types:
i. Input Restricted Queue: The input can be taken from only one
end but deletion can be done from any of the ends.
ii. Output Restricted Queue: The input can be taken from both
ends but deletion can be done from only one end.
3. Circular queue: This is a special type of queue where the last position is
connected back to the first position. Here also the operations are performed
in FIFO order.
4. Priority queue: A priority queue is a special queue where the elements are
accessed based on the priority assigned to them.
5.Trees:
It is a hierarchical structure that is used to represent and organize data in the form
of parent child relationship.
Basic terminologies:
1. Root: The root is the topmost node of the tree. It is the starting point of the
tree, and it has no parent. A is the root in the above tree.
2. Parent and child node: A parent node has branches to one or more child
nodes. A child node is derived from a parent node. B is the parent node of
D,E.
3. Leaf nodes: A leaf node is a node that has no children.
4. Edge: An edge is a connection (or link) between two nodes.
5. Subtree: A subtree is a smaller portion of a tree, consisting of a node and its
descendants.
Types of trees:
1. Binary tree: It is a tree where each node has at most two children (left and
right).
2. Complete tree: All levels are fully filled, except possibly the last. The
last level is filled from left to right.
3. Degenerate tree: A tree where each parent has only one child.
6. Graphs: Graph is a non-linear data structure consisting of vertices and
edges. The vertices are sometimes also referred to as nodes and the edges are
lines or arcs that connect any two nodes in the graph.
Basic terminologies:
1. Vertices: These are the fundamental units of the graph. Sometimes, vertices
are also known as vertex or nodes. Every node/vertex can be labeled or
unlabeled.
2. Edges: Edges are drawn or used to connect two nodes of the graph. It can be
ordered pair of nodes in a directed graph. Edges can connect any two nodes
in any possible way. There are no rules. Sometimes, edges are also known as
arcs. Every edge can be labelled/unlabeled.
int main() {
int n;
return 0;
}
Output
Enter the number of disks: 3
Steps to solve Tower of Hanoi:
Move disk 1 from A to C
Move disk 2 from A to B
Move disk 1 from C to B
Move disk 3 from A to C
Move disk 1 from B to A
Move disk 2 from B to C
Move disk 1 from A to C
prefixToPostfix(prefix);
return 0;
}
1.5 Evaluation of Postfix expressions:
Given a postfix expression, the task is to evaluate the postfix expression. A
Postfix expression is of the form “a b operator” (ab+) i.e., a pair of operands is
followed by an operator. We can use a stack for the evaluation of the Postfix
expressions.
Scan the expression from left to right, if the symbol is operand, then push it into
the stack. If the symbol is an operator, pop two operands from the stack, apply
the operator and put back the resultant into the stack.
Ex: 1 2 3 + - 9 *
Illustrations of the above example:
i. 1 will go into the stack.
ii. 2 will go into the stack.
iii. 3 will go into the stack.
iv. There is an operand ‘+’ so take out 2 and 3, add both of them and put
back 5 into the stack.
v. There is an operand ‘-’ so take out 5 and 1, subtract and put back 4 into
the stack.
vi. 9 will go into the stack.
vii. There is an operand ‘*’ so take out and multiply 9 and 4. So the result
will be 36.
// While Loop
int count = 0;
while (count < 5) {
printf("%d ", count);
count++;
}
printf("\n");
// Do-While Loop
count = 0;
do {
printf("%d ", count);
count++;
} while (count < 5);
printf("\n");
return 0;
}
Output:
01234
01234
01234
Recursion is the process of a function calling itself repeatedly till the given
condition is satisfied. A function that calls itself directly or indirectly is called a
recursive function and such kind of function calls are called recursive calls. In
recursion a function calls itself directly or indirectly to solve a problem.
// C Program to calculate the sum of first N natural numbers using recursion
#include <stdio.h>
int nSum(int n)
{
// base condition to terminate the recursion when N = 0
if (n == 0) {
return 0;
}
// recursive case / recursive call
int res = n + nSum(n - 1);
return res;
}
int main()
{
int n = 5;
// calling the function
int sum = nSum(n);
printf("Sum of First %d Natural Numbers: %d", n, sum);
return 0;
}
Output:
Sum of First 5 Natural Numbers: 15
Simulation of queues:
It acts as a modelling activity showcasing the statistics relating to the performance
of queues.
Task scheduling:
Data Streaming:
Queues are useful in handling real-time data streams, where data is processed in
the order it is received. This is common in applications like video streaming and
network packets.
Message Queues:
In systems where events are handled in real time (like in web servers or
event-driven architectures), events are queued and processed in the order of arrival.
Ex: 0 1 2 0 0 0 0 0 0
A sparse matrix is used when a matrix contains a large number of zero elements
and only a few non-zero values. Instead of storing and processing unnecessary
zeros, we use efficient storage formats to save memory and improve computational
performance.
Stores only nonzero elements and their positions in three arrays: row index,
column index, and value.
Ex: 0 0 5 0
0 8 0 0
0 0 0 3
Row Column Value
0 2 5
1 1 8
2 3 3
int main() {
int rows, cols;
return 0;
}
Output:
Enter the number of rows: 3
Enter the number of columns: 3
Enter the elements of the matrix:
102010000
The given matrix is a Sparse Matrix.
int main() {
int rows, cols;
int matrix[rows][cols];
// Input matrix elements
printf("Enter the elements of the matrix:\n");
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
scanf("%d", &matrix[i][j]);
}
}
return 0;
}
Output:
Enter the number of rows: 3
Enter the number of columns: 3
Enter the elements of the matrix:
000123000
#include <stdio.h>
transposed[i][0] = transposed[j][0];
transposed[i][1] = transposed[j][1];
transposed[i][2] = transposed[j][2];
transposed[j][0] = temp0;
transposed[j][1] = temp1;
transposed[j][2] = temp2;
}
}
}
int main() {
int nonZeroCount;
int sparseMatrix[nonZeroCount][3];
There are 4 library functions provided by C defined under <stdlib.h> header file to
facilitate dynamic memory allocation in C programming. They are:
1. malloc ()
2. calloc ()
3. free ()
4. realloc ()
malloc (): It is used to dynamically allocate a single large block of memory with
the specified size.
Ex: int * ptr = (int*) malloc (5* sizeof(int)); // since the size of int 4 bytes, a large
20 bytes of memory block is dynamically allocated to ptr.
Ex: int*ptr = (int*) calloc (5, sizeof(int)); //5 blocks of 4 bytes each is dynamically
allocated to ptr.
free (): It is used to dynamically de-allocate the memory. The memory allocated
using functions malloc () and calloc () is not de-allocated on their own. Hence the
free () method is used, whenever the dynamic memory allocation takes place. It
helps to reduce wastage of memory by freeing it.
#include <stdio.h>
#include <stdlib.h>
int main() {
int *arr;
int n, i;
scanf("%d", &n);
if (arr == NULL) {
return 1;
arr[i] = i + 1;
free(arr);
scanf("%d", &n);
if (arr == NULL) {
return 1;
scanf("%d", &n);
return 1;
arr[i] = i + 1; // reinitialize
// free memory
free(arr);
return 0;
Robust: The program is robust and has the ability to catch errors.
Encapsulation: ADTs hide the internal details of the data and provide a public
interface for users to interact with the data. This allows for easier maintenance and
modification of the data structure.
Information Hiding: ADTs can protect the integrity of the data by allowing access
only to authorized users and operations. This helps prevent errors and misuse of the
data.
Modularity: ADTs can be combined with other ADTs to form larger, more complex
data structures. This allows for greater flexibility and modularity in programming.
Overall, ADTs provide a powerful tool for organizing and manipulating data in a
structured and efficient manner.
Examples of ADTs:
1. List ADT:
The List ADT (Abstract Data Type) is a sequential collection of elements
that supports a set of operations without specifying the internal
implementation. It provides an ordered way to store, access, and modify
data.
The List ADT need to store the required data in the sequence and should have
the following operations:
The Stack ADT is a linear data structure that follows the LIFO (Last In, First
Out) principle. It allows elements to be added and removed only from one end,
called the top of the stack.
In Stack ADT, the order of insertion and deletion should be according to the
FILO or LIFO Principle. Elements are inserted and removed from the same end,
called the top of the stack. It should also support the following operations:
● push(): Insert an element at one end of the stack called the top.
● pop(): Remove and return the element at the top of the stack, if it is not
empty.
● peek(): Return the element at the top of the stack without removing it, if
the stack is not empty.
● size(): Return the number of elements in the stack.
● isEmpty(): Return true if the stack is empty; otherwise, return false.
● isFull(): Return true if the stack is full; otherwise, return false.
The Queue ADT follows a design similar to the Stack ADT, but the order of
insertion and deletion changes to FIFO. Elements are inserted at one end (called
the rear) and removed from the other end (called the front). It should support
the following operations:
C - Programs:-
1. Write a C program to demonstrate dynamic memory allocation using
malloc() and free().
2. Implement a recursive function to solve the Tower of Hanoi problem for
n=3.
3. Write a C program to convert an infix expression to postfix using a stack.
4. Implement a C program to evaluate a postfix expression using a stack.
5. Write a C program to implement Queue using an array.
6. Implement a C program to represent a sparse matrix using a triplet
representation.
7. Write a C program to find the transpose of a sparse matrix.
8. Implement a C program to perform push, pop, and display operations on a
stack using an array.
9. Write a C program to demonstrate iteration vs recursion with an example of
the Fibonacci series.
10.Implement a C program to perform enqueue and dequeue operations on a
circular queue using an array.
11.Implement a C program to solve the Tower of Hanoi problem for n=4 using
recursion.
12.Write a C program to implement a stack using a linked list with push, pop,
and display operations.
13.Implement a C program to evaluate a postfix expression using a stack with a
step-by-step explanation.
14.Write a C program to implement a queue using a linked list and perform
enqueue, dequeue, and display operations.
15.Implement a C program to perform infix to postfix conversion and
evaluation using a stack.
16.Write a C program to demonstrate dynamic memory allocation using
malloc(), calloc(), realloc(), and free().
17.Implement a C program to insert, delete, and display elements in a
double-ended queue (Deque) using an array.
18.Write a C program to find the transpose of a sparse matrix using an efficient
algorithm.
19.Implement a C program to compare the execution time of iteration and
recursion using Fibonacci series computation.
20.Write a C program to simulate CPU scheduling using a queue (Round Robin
algorithm).