Unit 2 Arrays
Unit 2 Arrays
An array is a collection of elements of the same data type stored in contiguous memory
locations. Arrays are used to store multiple values in a single variable, making it easier to
manage data in bulk. In C, arrays can be of any data type, including integers, floats,
characters, or even user-defined types like structures.
Declaration of Arrays in C
To declare an array in C, you need to specify the data type of the elements, the name
of the array, and the size (number of elements) of the array.
The general syntax is:
data_type array_name[array_size];
Here's a breakdown of the components:
data_type: Specifies the type of data the array will hold (e.g., int, float, char).
array_name: The name you want to give to the array.
array_size: The number of elements the array can hold.
Examples of Array Declarations
1. Integer Array
int numbers[5]; // Declares an integer array named 'numbers' with 5 elements.
2. Float Array
float temperatures[10]; // Declares a float array named 'temperatures' with 10
elements.
3. Character Array (String)
char name[20]; // Declares a character array named 'name' with 20 elements.
4. Array Initialization Arrays can also be initialized at the time of declaration:
int numbers[5] = {1, 2, 3, 4, 5}; // Initializes an integer array with specified values.
5. Implicit Size Declaration If you initialize an array and do not specify its size, the
compiler determines the size based on the number of elements provided:
int numbers[] = {1, 2, 3, 4, 5}; // Size is inferred as 5.
Key Points
Array indexing starts at 0, so the first element is accessed with index 0
(array_name[0]).
The size of an array must be a constant integer expression in C (cannot be a
variable).
C does not perform bounds checking on arrays, so accessing elements outside
the array's declared size can lead to undefined behavior.
int main() {
int numbers[5] = {10, 20, 30, 40, 50}; // Declare and initialize an array
return 0;
}
Output:
First element: 10
Second element: 20
Third element: 30
2. Storing Elements:
#include <stdio.h>
int main() {
int numbers[5]; // Declare an array of 5 integers
return 0;
}
Output:
First element: 10
Second element: 20
Third element: 30
Memory Layout of Arrays
Arrays in C are stored in contiguous memory locations. For an array of integers,
each element occupies sizeof(int) bytes (usually 4 bytes on most systems).
For example, if int numbers[5]; starts at memory address 1000, the elements
would be stored at:
o numbers[0] at address 1000
o numbers[1] at address 1004
o numbers[2] at address 1008, and so on.
Important Points
1. Out-of-Bounds Access: Accessing an element outside the declared size of the
array (e.g., numbers[5] in an array of size 5) results in undefined behavior.
2. Arrays and Loops: You can easily access or modify array elements using loops:
for (int i = 0; i < 5; i++) {
printf("%d ", numbers[i]); // Prints each element of the array
}
3. Modifying Elements: You can change the value of any element by assigning a
new value to it:
numbers[2] = 100; // Changes the third element to 100
LINEAR SEARCH AND BINARY SEARCH ALGORITHMS
The algorithm for linear search is relatively simple. The procedure starts at the very first index of
the input array to be searched.
Step 1 − Start from the 0th index of the input array, compare the key value with the value
present in the 0th index.
Step 2 − If the value matches with the key, return the position at which the value was found.
Step 3 − If the value does not match with the key, compare the next element in the array.
Step 4 − Repeat Step 3 until there is a match found. Return the position at which the match was
found.
Step 5 − If it is an unsuccessful search, print that the element is not present in the array and exit
the program.
Pseudocode
Analysis
Linear search traverses through every element sequentially therefore, the best case is when the
element is found in the very first iteration. The best-case time complexity would be O(1).
However, the worst case of the linear search method would be an unsuccessful search that
does not find the key value in the array, it performs n iterations. Therefore, the worst-case time
complexity of the linear search algorithm would be O(n).
int main() {
int arr[100], n, i, search, found = 0;
// Linear search
for(i = 0; i < n; i++) {
if(arr[i] == search) {
printf("Element %d found at position %d.\n", search, i+1);
found = 1;
break;
}
}
return 0;
}
Sample Input and Output:
Example 1:
Enter number of elements in the array: 5
Enter 5 elements:
12 34 54 2 3
Enter the element to search: 54
Element 54 found at position 3.
Example 2:
Enter number of elements in the array: 4
Enter 4 elements:
10 20 30 40
Enter the element to search: 25
Element 25 not found in the array.
Explanation:
The program asks for the number of elements in the array and stores them in the
arr[] array.
Then, the user inputs the element they wish to search for.
The program performs a linear search by comparing each element in the array
with the search element. If found, it displays the position of the element (1-based
index). If the element is not found, a message is printed indicating the absence
of the element in the array.
2. Binary Search (In-depth)
How Binary Search Works:
Binary search divides the array into two halves and eliminates half of the search space
each time.
It requires the array to be sorted before searching.
At each step, the middle element of the array is compared with the target. If the target is
less than the middle, the left half is searched. If it's greater, the right half is searched.
Binary Search algorithm is an interval searching method that performs the searching in
intervals only. The input taken by the binary search algorithm must always be in a sorted array
since it divides the array into subarrays based on the greater or lower values. The algorithm
follows the procedure below −
Step 1 − Select the middle item in the array and compare it with the key value to be searched. If
it is matched, return the position of the median.
Step 2 − If it does not match the key value, check if the key value is either greater than or less
than the median value.
Step 3 − If the key is greater, perform the search in the right sub-array; but if the key is lower than
the median value, perform the search in the left sub-array.
Step 4 − Repeat Steps 1, 2 and 3 iteratively, until the size of sub-array becomes 1.
Step 5 − If the key value does not exist in the array, then the algorithm returns an unsuccessful
search.
Pseudocode
The pseudocode of binary search algorithms should look like this –
Procedure binary_search
A ← sorted array
n ← size of array
x ← value to be searched
Set lowerBound = 1
Set upperBound = n
if A[midPoint] < x
set lowerBound = midPoint + 1
if A[midPoint] > x
set upperBound = midPoint - 1
if A[midPoint] = x
EXIT: x found at location midPoint
end while
end procedure
Analysis
Since the binary search algorithm performs searching iteratively, calculating the time complexity
is not as easy as the linear search algorithm.
The input array is searched iteratively by dividing into multiple sub-arrays after every unsuccessful
iteration. Therefore, the recurrence relation formed would be of a dividing function.
To explain it in simpler terms,
During the first iteration, the element is searched in the entire array. Therefore, length of
the array = n.
In the second iteration, only half of the original array is searched. Hence, length of the
array = n/2.
In the third iteration, half of the previous sub-array is searched. Here, length of the array
will be = n/4.
Similarly, in the ith iteration, the length of the array will become n/2i
To achieve a successful search, after the last iteration the length of array must be 1. Hence,
n/2i = 1
That gives us –
n = 2i
Applying log on both sides,
log n = log 2i
log n = i. log 2
i = log n
The time complexity of the binary search algorithm is O(log n)
int main() {
int arr[100], n, search, low, high, mid, found = 0;
// Binary search
low = 0;
high = n - 1;
if(arr[mid] == search) {
printf("Element %d found at position %d.\n", search, mid + 1);
found = 1;
break;
}
else if(arr[mid] < search) {
low = mid + 1;
}
else {
high = mid - 1;
}
}
return 0;
}
Example 2:
Enter the number of elements in the array: 5
Enter 5 sorted elements:
5 15 25 35 45
Enter the element to search: 20
Element 20 not found in the array.
Explanation:
1. Input: The user is asked to input the number of elements and the sorted elements
in the array.
2. Binary Search:
o The array is divided into halves repeatedly, and the middle element is
compared with the search element.
o If the middle element is equal to the search element, the position is
printed.
o If the middle element is less than the search element, the search
continues in the upper half. Otherwise, the search continues in the lower
half.
3. Output: If the element is found, the position is displayed. If not, a message
indicating that the element was not found is printed.
Binary Search Time Complexity:
Best Case: O(1) (if the middle element matches the search query).
Average Case: O(log n) (logarithmic because the search space is halved after each
comparison).
Worst Case: O(log n) (in case the element is not present or found at the last iteration).
Why Binary Search is More Efficient:
Binary search drastically reduces the number of comparisons by halving the array at
every step.
However, the array must be sorted, which adds an O(n log n) overhead if you need to
sort an unsorted array before searching.
Comparison Between Linear Search and Binary Search:
Criteria Linear Search Binary Search
Array Sorted? Not required Required
Time Complexity O(n) O(log n)
Best Case O(1) O(1)
Worst Case O(n) O(log n)
Efficiency Less efficient for large arrays More efficient, especially for large arrays
Use Case Small or unsorted datasets Large, sorted datasets
When to Use Each:
Linear Search is ideal when:
o The array is unsorted.
o The dataset is small or when simplicity is key.
Binary Search is ideal when:
o The array is sorted.
o Performance is critical, especially for larger datasets.
Bubble Sort
Bubble sort is a simple sorting algorithm. This sorting algorithm is comparison-based algorithm in
which each pair of adjacent elements is compared and the elements are swapped if they are
not in order. This algorithm is not suitable for large data sets as its average and worst case
complexity are of O(n2) where n is the number of items.
Step 1 − Check if the first element in the input array is greater than the next element in the array.
Step 2 − If it is greater, swap the two elements; otherwise move the pointer forward in the array.
Step 3 − Repeat Step 2 until we reach the end of the array.
Step 4 − Check if the elements are sorted; if not, repeat the same process (Step 1 to Step 3) from
the last element of the array to the first.
Step 5 − The final output achieved is the sorted array.
Pseudocode
We observe in algorithm that Bubble Sort compares each pair of array element unless the whole
array is completely sorted in an ascending order. This may cause a few complexity issues like
what if the array needs no more swapping as all the elements are already ascending.
To ease-out the issue, we use one flag variable swapped which will help us see if any swap has
happened or not. If no swap has occurred, i.e. the array requires no more processing to be
sorted, it will come out of the loop.
Pseudocode of bubble sort algorithm can be written as follows –
Analysis
In this case, value 33 is greater than 14, so it is already in sorted locations. Next, we compare 33
with 27.
We find that 27 is smaller than 33 and these two values must be swapped.
Next we compare 33 and 35. We find that both are in already sorted positions.
We know then that 10 is smaller 35. Hence they are not sorted. We swap these values. We find
that we have reached the end of the array. After one iteration, the array should look like this −
To be precise, we are now showing how an array should look like after each iteration. After the
second iteration, it should look like this −
Notice that after each iteration, at least one value moves at the end.
And when there's no swap required, bubble sort learns that an array is completely sorted.
int main() {
int arr[10];
int n;
int i, j, temp;
// Read array size and array elements
printf(“Enter Array Size:”);
scanf(“%d”, &n);
printf(“Enter Array Elements:\n”);
for (i=0;i<n;i++)
scanf(“%d”,&arr[i]);
return 0;
}
Output
Enter Array Size: 5
Enter Array Elements: 67 44 82 17 20
Array before Sorting: 67 44 82 17 20
Array after Sorting: 17 20 44 67 82
Selection Sort
Selection Sort is a simple comparison-based sorting algorithm. It divides the input array
into two parts: the sorted part (initially empty) and the unsorted part (initially the entire
array). The algorithm repeatedly selects the smallest (or largest, depending on sorting
order) element from the unsorted part, swaps it with the first element of the unsorted
part, and thus grows the sorted part by one element.
Algorithm Steps:
1. Start from the leftmost element: Begin with the first element of the array.
2. Find the minimum element: Traverse through the unsorted portion of the array to
find the minimum element.
3. Swap the minimum element with the first element: Place the minimum element at
the beginning of the unsorted portion.
4. Move the boundary: After the swap, move the boundary between the sorted
and unsorted portions one element to the right.
5. Repeat: Repeat steps 2–4 for the rest of the array.
Example:
Let's take an example array:
arr[] = {64, 25, 12, 22, 11}
Step-by-Step Process:
1. First Pass:
o Initial array: [64, 25, 12, 22, 11]
o The smallest element in the unsorted array ([64, 25, 12, 22, 11]) is 11.
o Swap 64 with 11.
o Array after the first pass: [11, 25, 12, 22, 64].
2. Second Pass:
o Unsorted part is now [25, 12, 22, 64].
o The smallest element in this part is 12.
o Swap 25 with 12.
o Array after the second pass: [11, 12, 25, 22, 64].
3. Third Pass:
o Unsorted part is [25, 22, 64].
o The smallest element is 22.
o Swap 25 with 22.
o Array after the third pass: [11, 12, 22, 25, 64].
4. Fourth Pass:
o Unsorted part is [25, 64].
o The smallest element is 25 (no swap needed).
o Array remains the same.
5. Final Sorted Array: [11, 12, 22, 25, 64]
Time Complexity:
Best case: O(n²) – The algorithm still compares all elements even if the array is
already sorted.
Worst case: O(n²) – It requires n-1 comparisons in the first pass, n-2 in the second,
and so on.
Average case: O(n²)
Space Complexity:
O(1) – Selection Sort is an in-place sorting algorithm, meaning it does not require
additional memory for another array.
Characteristics:
Simple and easy to implement.
Not stable: Stability means that equal elements maintain their relative order. In
Selection Sort, if there are two equal elements, their relative order may change
after sorting.
Inefficient for large datasets due to its O(n²) time complexity.
In-place sorting: Does not require extra storage except for temporary variables
for swapping.
#include <stdio.h>
int main() {
int arr[10];
int n;
int i, j, min_idx, temp;
// Read array size and array elements
printf(“Enter Array Size:”);
scanf(“%d”, &n);
printf(“Enter Array Elements:\n”);
for (i=0;i<n;i++)
scanf(“%d”,&arr[i]);
The efficiency of the bubble sort is The efficiency of the selection sort is
5.
less. high.
#include <stdio.h>
int main() {
// Declare and initialize a 2D array with 3 rows and 4 columns
int matrix[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
return 0;
}
Traversing a 2D Array:
You can use nested loops to traverse and manipulate a 2D array.
#include <stdio.h>
int main() {
int matrix[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
// Loop through the rows
for (int i = 0; i < 3; i++) {
// Loop through the columns
for (int j = 0; j < 4; j++) {
// Print each element in the 2D array
printf("%d ", matrix[i][j]);
}
printf("\n"); // Newline for each row
}
return 0;
}
Output:
1234
5678
9 10 11 12
int arr[2][3][4] = {
{
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
},
{
{13, 14, 15, 16},
{17, 18, 19, 20},
{21, 22, 23, 24}
}
};
Important Points:
1. Indexing: Array indices in C are zero-based, meaning the first element is at index
[0][0] in 2D arrays.
2. Memory Layout: Multidimensional arrays in C are stored in row-major order,
meaning the elements of a row are stored in contiguous memory locations.
3. Initialization: You can initialize arrays partially. If not fully initialized, remaining
elements are set to zero.
Common Use Cases:
2D Arrays: Represent matrices, grids, or tables.
3D Arrays: Represent a collection of matrices (e.g., data for 3D games, or multi-
layered data sets).
N-Dimensional Arrays: Rarely used beyond 3D, but sometimes necessary for
complex data structures in simulations, scientific computing, etc.
Matrix operations
Matrix operations are commonly performed in C programming using multidimensional
arrays. Common matrix operations include matrix addition, subtraction, multiplication,
and transposition. Below are examples of each operation implemented in C.
1. Matrix Addition
Code for Matrix Addition:
#include <stdio.h>
int main() {
int rows = 2, cols = 2;
int A[2][2] = {{1, 2}, {3, 4}};
int B[2][2] = {{5, 6}, {7, 8}};
int sum[2][2];
return 0;
}
Output:
Matrix A + B:
68
10 12
2. Matrix Subtraction
Code for Matrix Subtraction:
#include <stdio.h>
int main() {
int rows = 2, cols = 2;
int A[2][2] = {{9, 8}, {7, 6}};
int B[2][2] = {{5, 4}, {3, 2}};
int diff[2][2];
// Perform matrix subtraction: diff = A - B
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
diff[i][j] = A[i][j] - B[i][j];
}
}
return 0;
}
Output:
Matrix A - B:
44
44
3. Matrix Multiplication
Code for Matrix Multiplication:
#include <stdio.h>
int main() {
int rowsA = 2, colsA = 2, rowsB = 2, colsB = 2;
int A[2][2] = {{1, 2}, {3, 4}};
int B[2][2] = {{5, 6}, {7, 8}};
int product[2][2];
return 0;
}
Output:
Matrix A * B:
19 22
43 50
4. Matrix Transpose
Code for Matrix Transpose:
#include <stdio.h>
int main() {
int rows = 2, cols = 3;
int A[2][3] = {{1, 2, 3}, {4, 5, 6}};
int transpose[3][2];
return 0;
}
Output:
Transpose of matrix A:
14
25
36
Explanation of Operations:
1. Matrix Addition/Subtraction:
o The operation is performed element-wise between two matrices of the
same dimensions.
o Time Complexity: O(rows * cols)
2. Matrix Multiplication:
o Multiply rows of the first matrix by columns of the second matrix.
o Resulting matrix will have dimensions of rowsA x colsB.
o Time Complexity: O(rowsA * colsA * colsB)
3. Matrix Transposition:
o Swap rows and columns of the matrix.
o Time Complexity: O(rows * cols)
These examples assume that the matrices are properly dimensioned for each operation
(e.g., for multiplication, the number of columns in the first matrix must equal the number
of rows in the second matrix).