0% found this document useful (0 votes)
15 views

Midterm gr12

Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views

Midterm gr12

Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 17

Vietnam National University, Ha Noi

International School

Midterm exam report

Group: 12
Class: INS305003
Subjects: Data Structure & Algorithm with C
Members: Le Thi Bich Ngoc - 22070439
Tran Van Anh - 22070395
Do Huyen Trang - 22070377
Vu Thi Tu Chau - 22070310
Lecture: PhD. Diem Cong Hoang
Topic: Merge sort

Ha Noi, 5th November, 2024

1
Thanks

We would like to express my gratitude to lecturer Diem Cong Hoang for imparting
to we the necessary knowledge and skills to complete the midterm report.

Although our group tried very hard, due to our limited professional qualifications,
we encountered many difficulties during the research process and inevitably made
mistakes. Therefore, we look forward to receiving comments and feedback from you
to make our report more complete.

Thank you very much!

Contents
2
Vietnam National University, Ha Noi........................................................................................1
I. Algorithms introduction......................................................................................................4
1. Definition................................................................................................................................4
2. Applications of Merge sort.....................................................................................................4
II. How Merge Sort algorithm works......................................................................................5
1. The basic steps of Merge Sort.........................................................................................5
2. Example...........................................................................................................................5
III. Code explaination.................................................................................................................7
IV. Algorithm complexity analysis..........................................................................................14
1. Time Complexity Analysis............................................................................................14
2. Space Complexity..........................................................................................................15
V. Advantages and disadvantages of algorithms....................................................................15
1. Advantages...........................................................................................................................15
2. Disadvantages.......................................................................................................................15
VI. Conclusion...........................................................................................................................16
VII. References .........................................................................................................................16
Contribution ..........................................................................................................................17

I. Algorithms introduction

3
1. Definition
Merge sort is a sorting algorithm that follows the divide-and-conquer approach. It
works by recursively dividing the input array into smaller subarrays, sorting those
subarrays, and merging them back together to obtain the sorted array.

2. Applications of Merge Sort

- Sorting large datasets

- External sorting (when the dataset is too large to fit in memory) is a term for a class of
sorting algorithms that can handle massive amounts of data. It is required when the data
being sorted does not fit into the main memory of a computing device (usually RAM)
and instead must reside in the slower external memory (usually a hard drive).

- Inversion counting: Given an integer array arr[] of size n, find the inversion count in the
array.
Two array elements: arr[i] > arr[j] and i < j.

- Merge Sort and its variations are used in library methods of programming languages. For
example, its variation TimSort is used in Python, Java Android, and Swift. The main
reason it is preferred to sort non-primitive types is stability which is not there in
QuickSort.

- It is a preferred algorithm for sorting Linked lists.

- It can be easily parallelized as we can independently sort subarrays and merge them.
4
- The merge function of merge sort efficiently solves the problems like union and
intersection of two sorted arrays: A Union of two arrays is an array having all distinct
elements that are present in either array whereas an Intersection of two arrays is an array
containing distinct common elements between the two arrays

II. How Merge Sort algorithm works


The key idea behind this algorithm is to split the original sequence into individual
elements and then merge them back together in sorted order.

1. The basic steps of Merge Sort


- Divide: Divide the list or array recursively into two halves until it can no more be
divided.

- Conquer: Each subarray is sorted individually using the merge sort algorithm.

- Merge: The sorted subarrays are merged back together in sorted order. The process
continues until all elements from both subarrays have been merged.

2. Example
Let’s sort the array or list [38, 27, 43, 3] using Merge Sort

5
6
III. Code explaination

Standard Library Declaration


#include <stdio.h> // Include standard input-output header file

#include <stdio.h>: The C standard library provides input/output


functions such as printf and scanf.

Merge Function
int i, j, k;
int n1 = middle - left + 1;
int n2 = right - middle;
int L[n1], R[n2];
 i, j, k: Index valuables used to traverse the arrays.
 n1, n2: The sizes of the two halves of the array (left half and right half).
 L[], R[]: Temporary arrays to store the elements of the left and right halves.
 n1 = middle - left + 1: When splitting the array, n1 is calculated as middle - left + 1
(adding 1 to include the element at the middle index).

Copy elements into temporary arrays


for (i = 0; i < n1; i++) // Copy left half to L[]
L[i] = arr[left + i];
for (j = 0; j < n2; j++) // Copy right half to R[]
R[j] = arr[middle + 1 + j];

 Two for loops copy elements from the main array arr[] into the temporary arrays L[] and
R[].
 L[] contains elements from arr[left] to arr[middle].
 R[] contains elements from arr[middle + 1] to arr[right].
 For loop:
o i = 0: Start the loop with i equal to 0.
o i < n1: Continue the loop while i is less than n1 (size of the left half).
o i++: Increment i by 1 after each iteration.

Copy elements:
 L[i] = arr[left + i]: Copy the element from arr[] to the temporary array
L[].
 arr[left + i]: Access the element at index left + i in arr[].
 L[i]: Assign the value of arr[left + i] to L[i].

Example:

7
 Assume left = 0, middle = 2, and the array arr is [10, 20, 30, 40, 50].
 n1 = middle - left + 1 = 3.
o When i = 0, L[0] = arr[0] = 10.
o When i = 1, L[1] = arr[1] = 20.
o When i = 2, L[2] = arr[2] = 30.
 Result: L[] = [10, 20, 30].
 For loop:
o j = 0: Start the loop with j equal to 0.
o j < n2: Continue the loop while j is less than n2 (size of the right half).
o j++: Increment j by 1 after each iteration.

Copy elements:
 R[j] = arr[middle + 1 + j]: Copy the element from arr[] to the temporary array
R[].
 arr[middle + 1 + j]: Access the element at index middle + 1 + j in
arr[].
 R[j]: Assign the value of arr[middle + 1 + j] to R[j].

Example:
 Assume middle = 2, right = 4, and the array arr is [10, 20, 30, 40, 50].
 n2 = right - middle = 2.
o When j = 0, R[0] = arr[3] = 40.
o When j = 1, R[1] = arr[4] = 50.
 Result: R[] = [40, 50].

Initialize index variables:


 i = 0; // Initial index of the first subarray (L[])
 j = 0; // Initial index of the second subarray (R[])
 k = left; // Initial index of the merged subarray
 Initialize i and j for the two temporary arrays L[] and R[].
 k is the index for the main array arr[], starting from the position left.

Merge the arrays:

while (i < n1 && j < n2) {


if (L[i] <= R[j]) {
arr[k] = L[i];
i++;
} else {
arr[k] = R[j];
j++;
}

8
k++;
}

 while (i < n1 && j < n2): This loop continues as long as both conditions i < n1 and j <
n2 are true.
o i < n1: Ensures that i is within the bounds of L[].
o j < n2: Ensures that j is within the bounds of R[].

Check and assign value from L[] or R[] to arr[]:


 if (L[i] <= R[j]): Check if the current element of L[] (L[i]) is less than or equal to the
current element of R[] (R[j]).
o If true:
 arr[k] = L[i]: Assign the value of L[i] to arr[k].
 i++: Increment i to move to the next element of L[].
o If false:
 arr[k] = R[j]: Assign the value of R[j] to arr[k].
 j++: Increment j to move to the next element of R[].
 k++: Increment k to move to the next position in the main array arr[].

Purpose of the code:


 This code merges two sorted arrays L[] and R[] into the main array arr[].
 It traverses each element of L[] and R[], compares them, and assigns the smaller element
to arr[].

Copy remaining elements of L[] if any:


while (i < n1) {
arr[k] = L[i];
i++;
k++;
}

Detailed explanation:
 Purpose: This loop copies all remaining elements of the temporary array L[] into the
main array arr[] after merging the elements from both temporary arrays.
 Condition: while (i < n1): The loop continues as long as i is less than n1 (number of
elements in L[]).
o arr[k] = L[i]: Assign the value of the element at L[i] to arr[k].
o i++: Increment i to move to the next element of L[].
o k++: Increment k to move to the next position in the main array arr[].

Usage scenario:
 If R[] is exhausted, but L[] still has remaining elements, this loop will copy all
remaining elements from L[] to arr[].
9
Copy remaining elements of R[] if any
while (j < n2) {
arr[k] = R[j];
j++;
k++;
}

Purpose:
This loop copies all remaining elements from the temporary array R[] to the main array
arr[] after merging elements from both temporary arrays.
 Condition: while (j < n2): The loop continues running as long as j is less than n2 (the
number of elements in R[]).
 arr[k] = R[j];: Assigns the value of the element at R[j] to arr[k].
 j++;: Increments the index j by 1 to move to the next element in R[].
 k++;: Increments the index k by 1 to move to the next position in the main array
arr[].

Use Case:
If the L[] array has been exhausted but R[] still has remaining elements, this loop will
copy all the remaining elements from R[] into arr[].

The mergeSort Function


1. Recursion Base Case
if (left < right)
 Explanation: The mergeSort function continues to divide the array only if left <
right.
This ensures that we only divide the array when there are at least two elements.
When left >= right, further division is unnecessary.

2. Finding the Middle Point


int middle = left + (right - left) / 2; // Find the middle point

 Explanation: middle is the middle point of the current array segment.


The expression left + (right - left) / 2 safely calculates the middle point, avoiding
overflow compared to (left + right) / 2.
Example: Suppose the array has the following indices:
arr = [10, 20, 30, 40, 50]
left = 0, right = 4
middle = 0 + (4 - 0) / 2 = 2
The middle point is index 2.
10
3. Recursively Sort the First Half
mergeSort(arr, left, middle); // Sort the first half

 Explanation: Call the mergeSort function to sort the first half of the array, from
index left to middle.

4. Recursively Sort the Second Half


mergeSort(arr, middle + 1, right); // Sort the second half

 Explanation: Call the mergeSort function to sort the second half of the array, from
index middle + 1 to right.

5. Merging the Sorted Halves


merge(arr, left, middle, right); // Merge the sorted halves

 Explanation: Call the merge function to merge the two sorted halves together.
After recursively sorting the two halves, the merge function combines them into one
sorted array.

The printArray Function


void printArray(int arr[], int size) {
int i;

 Explanation:
o void printArray(int arr[], int size): Defines the printArray function with two
parameters:
 int arr[]: The array of integers to print.
 int size: The size of the array (number of elements in the array).
o int i;: Declares the variable i to be used as an index in the for loop.

Loop to Print Array Elements:


for (i = 0; i < size; i++)
printf("%d ", arr[i]);

 Explanation:
o for (i = 0; i < size; i++): The for loop runs from i = 0 to i < size.
 i = 0: Initializes the index i to 0.
 i < size: The loop continues as long as i is less than size.
 i++: Increments the index i by 1 after each iteration.
o printf("%d ", arr[i]);: Prints the element at index i of the array arr to the screen.
 %d: Format specifier to print an integer.
 arr[i]: The element at position i in the array arr.
 " ": Adds a space after each integer to separate the elements.
11
Print Newline After All Elements:
printf("\n");
}

 Explanation: printf("\n");: Prints a newline character to move the cursor to a new


line after printing all the elements of the array.
Example: Assuming the array arr has elements [1, 2, 3, 4, 5] and size = 5.
 The function printArray(arr, 5) performs:
o Iteration 1: Prints 1, increments i to 1.
o Iteration 2: Prints 2, increments i to 2.
o Iteration 3: Prints 3, increments i to 3.
o Iteration 4: Prints 4, increments i to 4.
o Iteration 5: Prints 5, increments i to 5 (loop ends as i is not less than size).
o Prints newline: Moves cursor to the new line.
Result: 1 2 3 4 5 followed by a newline character.

The main Function


1. Declaring the Variable n
int n;
printf("Enter the number of elements in the array: ");
scanf("%d", &n);

 Explanation:
o int n;: Declares the variable n to store the number of elements in the array.
o printf("Enter the number of elements in the array: ");: Prints a prompt to the
screen asking the user to enter the number of elements.
o scanf("%d", &n);: Reads the value entered by the user and assigns it to the
variable n.

2. Declaring the Array and Inputting Its Elements


int arr[n];
printf("Enter the elements of the array:\n");
int i;
for (i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}

 Explanation:
o int arr[n];: Declares the array arr with a size of n.
o printf("Enter the elements of the array:\n");: Prints a prompt to the screen asking
the user to enter the elements of the array.
o int i;: Declares the variable i to be used in the for loop.
12
o for (i = 0; i < n; i++) { scanf("%d", &arr[i]); }: The for loop runs from i = 0 to i <
n. In each iteration, it reads the value entered by the user and assigns it to arr[i].

3. Printing the Initial Array


printf("Initial array: \n");
printArray(arr, n);

 Explanation:
o printf("Initial array: \n");: Prints the string "Initial array:" to the screen.
o printArray(arr, n);: Calls the printArray function to print the elements of the
initial array.

4. Calling the mergeSort Function


mergeSort(arr, 0, n - 1);

 Explanation:
o mergeSort(arr, 0, n - 1);: Calls the mergeSort function to sort the array arr from
index 0 to n - 1.

5. Printing the Sorted Array


printf("Sorted array: \n");
printArray(arr, n);

 Explanation:
o printf("Sorted array: \n");: Prints the string "Sorted array:" to the screen.
o printArray(arr, n);: Calls the printArray function to print the elements of the
sorted array.

6. Ending the Program


return 0;

 Explanation:
o return 0;: Returns the value 0 to indicate that the program has ended successfully.

13
The result of the code when displayed on the screen with a custom array.

IV. Algorithm complexity analysis


1. Time Complexity Analysis

To analyze the time complexity of Merge Sort, let's consider the mergeSort function:

 Divide and Conquer:


o At each step of Merge Sort, the array is divided into two halves. This division
occurs repeatedly until each half has only one element (the base case of
recursion).
o Dividing the array into two halves forms a recursion tree with a depth of log 2 n.
Therefore, the number of divisions required is log 2 n (since the array is halved at
each step).

14
 Merge:
o After the array is split into individual elements, the merge steps (merge function)
will combine each pair of sorted halves to create a larger sorted array.
o At each level of the recursion tree, merging the two sorted halves has a complexity
of O(n) (since we have to go through all the elements of the array at each level to
sort them back).
o Therefore, the total time to merge through all levels is:

( The recursive relation for Merge Sort can be represented as follows:

2T(n/2): Time to recursively sort two halves of the array.


O(n): Time to merge two sorted halves of the array, which is linear in the input size.
Solve the recursive relation: Using the Master Theorem method, we can solve this
recursive relation to find the time complexity of Merge Sort:

)
2. Space Complexity

- Additional Space: The merge function in this code uses temporary arrays L[ ] and R[ ]
to store the split halves. Therefore, the algorithm requires additional memory
proportional to the size of the O(n) array to store the temporary elements during the
merge.
- The total space complexity is O(n).
V. Advantages and disadvantages of algorithms

1. Advantages
- Stability: Merge sort is a stable sorting algorithm, which means it maintains the relative
order of equal elements in the input array.
- Worst-case performance guarantee: Merge sort has a worst-case time complexity of O(N
logN), which means it performs well even on large datasets.
- Ease of implementation: The divide-and-conquer approach is very simple.
- Natural parallelism: We merge sub-arrays independently, which makes this algorithm
suitable for parallel processing.

15
2. Disadvantages

- Space complexity: Merge sort requires additional memory to store the merged sub-
arrays during the sorting process.
- Not in-place: Merge sort is not an in-place sorting algorithm, which means it requires
additional memory to store the sorted data. This can be a disadvantage in applications
where memory usage is a concern.
- It's slower than QuickSort in general. QuickSort is more cache-friendly because it works
in place.

VI. Conclusion

In summary, Merge Sort is an efficient, reliable sorting algorithm that uses a divide-and-
conquer approach to break down and merge arrays, achieving consistent O(n log n)
performance across all cases. While it requires extra space, its predictable efficiency
makes it ideal for large datasets and offers key insights into recursion and algorithmic
design.

VII. References

1. Merge Sort – Data Structure and Algorithms Tutorials, Updated : 17 Sep, 2024,
Geeksforgeeks.org, Available at:https://www.geeksforgeeks.org/merge-sort/
2. DSA Merge Sort Time Complexity, Copyright 1999-2024 by Refsnes Data, Available
at: https://www.w3schools.com/dsa/dsa_timecomplexity_mergesort.php
3. DSA Merge Sort, by w3schools.com , Available
at:https://www.w3schools.com/dsa/dsa_algo_mergesort.php
4. What is the Time Complexity of Merge Sort Algorithm?, 12th June, 2024, by Arunav
Goswami, Available at: https://www.almabetter.com/bytes/articles/merge-sort-
time-complexity
5. Merge Sort Algorithm - Java, C, and Python Implementation, Published on August 4,
2022, digitalocean.com, Available at:
https://www.digitalocean.com/community/tutorials/merge-sort-algorithm-java-c-
python
6. Merge Sort Explained: A Data Scientist’s Algorithm Guide, Mar 31, 2022, By
Richmond Alake, Available at: Merge Sort Explained: A Data Scientist’s Algorithm
Guide | NVIDIA Technical Blog

16
Contribution
Members Student’s ID Content Contribution
percentage
Tran Van Anh 22070395 Algorithm 25%
complexity analysis,
Edit slide
Do Huyen Trang 22070377 How Merge Sort 25%
algorithm works,
Conclusion, Edit
report
Le Thi Bich Ngoc 22070439 Run code, Code 25%
explanation, Edit
report
Vu Thi Tu Chau 22070310 Algorithms 25%
introduction,
Advantages and
disadvantages of
algorithms, Edit
slide

17

You might also like