DS Unit-1
DS Unit-1
Syntax of a Structure:
struct StructureName {
data_type member1;
data_type member2;
...
};
struct is the keyword used to define a structure.
StructureName is the name of the structure.
member1, member2 are the variables (also called members of the structure).
Example Program:
#include <stdio.h>
Output:
// Defining a structure Roll No: 101
struct Student { Name: Alice
int rollNo; Marks: 85.50
char name[50];
float marks; The structure Student contains
}; three members: rollNo (integer),
name (string), and marks (float).
int main() { Inside main(), we declare s1, a
struct Student s1 = {101, "Alice", 85.5}; structure variable of type
printf("Roll No: %d\n", s1.rollNo); Student, and initialize it with
printf("Name: %s\n", s1.name); values.
printf("Marks: %.2f\n", s1.marks); The printf function accesses and
prints each member of the
return 0; structure.
}
Syntax of a Union:
union UnionName {
data_type member1;
data_type member2;
...
};
union Data {
int rollNo; // 4 bytes
float marks; // 4 bytes
double grade; // 8 bytes
}; Output:
Union:
int main() { Size: 8 bytes
union Data d1; Roll No: 101
Marks: 89.50
printf("Union:\n");
printf("Size: %lu bytes\n", sizeof(d1));
d1.rollNo = 101;
printf("Roll No: %d\n", d1.rollNo);
return 0;
}
Structure stores rollNo (4 bytes) and marks (4 bytes) separately, so the total
memory is 8 bytes.
Union has rollNo (4 bytes), marks (4 bytes), and grade (8 bytes), but it only
occupies 8 bytes because it takes the size of its largest member (double).
When a new value is assigned to a union member, the previous value is lost
because all members share the same memory space.
3. Illustrate the concept of nested structure with examples.
A nested structure in C is a structure inside another structure. It helps represent
complex data by combining related structures, making data organization easier and
improving code readability.
int main() {
struct Student s1 = {101, "Alice", {"New York", 10001}};
return 0;
}
Explanation:
The inner structure Address is defined separately.
The outer structure Student contains Address as a member.
This approach allows code reusability, as Address can be used in other
structures as well.
2. Embedded Nested Structure
In this type, the inner structure is defined inside the outer structure itself.
Example: Embedded Nested Structure :
#include <stdio.h>
struct Student {
int rollNo;
Output :
char name[50];
Name: Alice
City: Los Angeles
struct {
Pincode: 90001
char city[20];
int pincode;
} addr;
};
int main() {
struct Student s1 = {101, "Alice", {"Los Angeles", 90001}};
return 0;
}
Explanation:
The inner structure is directly declared inside the outer structure.
This approach is useful when the inner structure is only relevant to the outer
structure and will not be used elsewhere.
Key Differences Between Separated and Embedded Nested Structures
Separated Nested Structure allows reusability of the inner structure.
Embedded Nested Structure is useful when the inner structure is used only
within the outer structure.
4. Explain about an array of structures with a suitable example.
Example Program :
#include <stdio.h>
return 0;
}
int main() {
int arr[5] = {10, 20, 30, 40, 50}; // Array declaration
printf("Array elements:\n");
for (int i = 0; i < 5; i++) { Output :
printf("%d ", arr[i]); Array elements:
} 10 20 30 40 50
return 0;
}
Key Differences Between Linear and Non-Linear Data Structures :
Linear structures are simple to implement but have higher time complexity for some
operations.
Non-linear structures provide efficient searching and organization, especially in
complex data handling.
6. Explain time and space complexities in data structures.
Time Complexity
Time complexity refers to the amount of time an algorithm takes to complete based
on the input size (n). It helps in evaluating the efficiency of an algorithm.
Types of Time Complexities:
1. Best Case Complexity: Minimum time required for execution (e.g., already sorted
array in Bubble Sort).
2. Worst Case Complexity: Maximum time required for execution (e.g., reversed
array in Bubble Sort).
3. Average Case Complexity: The expected time for random inputs.
Example:
Searching for an element in an array of size n using linear search takes O(n) time,
as we might need to check all elements.
Searching in a sorted array using binary search takes O(log n) time, as it divides
the array into halves.
Big-O Notation for Common Algorithms:
O(1) – Constant Time: Accessing an array element (arr[i]).
O(n) – Linear Time: Traversing an array (for loop from 0 to n).
O(log n) – Logarithmic Time: Binary Search.
O(n²) – Quadratic Time: Nested loops in sorting (Bubble Sort).
Space Complexity
Space complexity refers to the amount of memory used by an algorithm during
execution. This includes:
1. Fixed Part: Memory required for constants, variables, and program instructions.
2. Variable Part: Memory required for dynamic allocation (e.g., recursion, arrays,
linked lists).
Types of Space Complexities:
O(1) – Constant Space: Uses a fixed amount of memory. Example: Swapping two
numbers.
O(n) – Linear Space: Uses memory proportional to input size. Example: Storing an
array of size n.
Example:
A recursive function requires additional stack memory for each function call,
increasing space complexity.
Example : Array Traversal (Time Complexity O(n)) :
#include <stdio.h>
int main() {
int arr[] = {10, 20, 30, 40, 50};
int size = sizeof(arr) / sizeof(arr[0]);
traverseArray(arr, size);
return 0;
}
Types of ADTs :
1. Linear Data Structures
Linear data structures store elements sequentially, and each element is connected
to its previous and next element.
Types of linear data structures :
Array – Stores elements in adjacent memory locations.
Stack – Follows LIFO (Last In, First Out) principle.
Queue – Follows FIFO (First In, First Out) principle.
Linked List – A sequence of nodes connected via pointers.
2. Stack ADT
A stack is a linear data structure that follows LIFO (Last In, First Out) principle.
Operations of Stack ADT :
Push(): Inserts an element at the top of the stack.
Pop(): Removes and returns the top element.
Peek(): Returns the top element without removing it.
IsEmpty(): Checks if the stack is empty.
Stack follows sequential memory allocation and is useful in function calls, undo
mechanisms, and expression evaluation.
3. Queue ADT
A queue is a linear data structure that follows FIFO (First In, First Out) principle.
Operations of Queue ADT (From PPTs):
Enqueue(x): Adds an element to the rear of the queue.
Dequeue(): Removes and returns the front element.
Front(): Returns the front element without removing it.
IsEmpty(): Checks if the queue is empty.
Queues are used in scheduling, data buffering, and handling requests in order.
4. Linked List ADT
A linked list is a collection of nodes where each node contains a data field and a
pointer to the next node.
Types of Linked Lists :
Singly Linked List: Each node points to the next node.
Doubly Linked List: Each node points to both next and previous nodes.
Circular Linked List: The last node connects to the first node.
Linked lists provide dynamic memory allocation and efficient insertions/deletions.
5. Abstract Data Types
Stack ADT
Queue ADT
List ADT
Linked List ADT
Each ADT defines a set of operations without specifying how the data is stored
internally.
8. Sort the following elements using Quick Sort and also write the C
program to implement the Quick Sort algorithm.
#include <stdio.h>
int main() {
void swap(int *a, int *b) {
int arr[] = {75, 45, 40, 80, 35, 78, 98, 30, 39,
int temp = *a;
100};
*a = *b;
int n = sizeof(arr) / sizeof(arr[0]);
*b = temp;
}
printArray(arr, n);
quickSort(arr, 0, n - 1);
int partition(int arr[], int low, int high) {
printArray(arr, n);
int pivot = arr[high], i = low - 1, j;
for (j = low; j < high; j++) {
return 0;
if (arr[j] < pivot) {
}
i++;
swap(&arr[i], &arr[j]);
} Output :
} 75 45 40 80 35 78 98 30 39 100
swap(&arr[i + 1], &arr[high]); 30 35 39 40 45 75 78 80 98 100
return i + 1;
}
int main() {
for (i = 0; i < n1; i++)
int arr[] = {75, 45, 40, 80, 35, 78, 98, 30, 39,
L[i] = arr[left + i];
100};
for (j = 0; j < n2; j++)
int n = sizeof(arr) / sizeof(arr[0]);
R[j] = arr[mid + 1 + j];
printArray(arr, n);
i = 0, j = 0, k = left;
mergeSort(arr, 0, n - 1);
while (i < n1 && j < n2) {
printArray(arr, n);
if (L[i] <= R[j])
arr[k++] = L[i++];
return 0;
else
}
arr[k++] = R[j++];
}