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

UNIT-5 Notes Data Structures.docx

The document discusses various searching and sorting algorithms, including Linear Search, Binary Search, Insertion Sort, and Selection Sort. It provides detailed explanations of how each algorithm works, their time and space complexities, and examples to illustrate their functionality. Linear Search is a simple method for finding elements in an unordered list, while Binary Search is more efficient for sorted lists, and both Insertion and Selection Sort are basic sorting techniques with O(n^2) complexity in average and worst cases.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views

UNIT-5 Notes Data Structures.docx

The document discusses various searching and sorting algorithms, including Linear Search, Binary Search, Insertion Sort, and Selection Sort. It provides detailed explanations of how each algorithm works, their time and space complexities, and examples to illustrate their functionality. Linear Search is a simple method for finding elements in an unordered list, while Binary Search is more efficient for sorted lists, and both Insertion and Selection Sort are basic sorting techniques with O(n^2) complexity in average and worst cases.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 44

UNIT-5

Linear Search Algorithm


Searching is the process of finding some particular element in the list. If the element is
present in the list, then the process is called successful, and the process returns the location of
that element; otherwise, the search is called unsuccessful.
Two popular search methods are Linear Search and Binary Search. So, here we will discuss
the popular searching technique, i.e., Linear Search Algorithm.
Linear search is also called as sequential search algorithm. It is the simplest searching
algorithm. In Linear search, we simply traverse the list completely and match each element of
the list with the item whose location is to be found. If the match is found, then the location of
the item is returned; otherwise, the algorithm returns NULL.
It is widely used to search an element from the unordered list, i.e., the list in which items are
not sorted. The worst-case time complexity of linear search is O(n).
The steps used in the implementation of Linear Search are listed as follows -
o First, we have to traverse the array elements using a for loop.
o In each iteration of for loop, compare the search element with the current array
element, and -
o If the element matches, then return the index of the corresponding array
element.
o If the element does not match, then move to the next element.
o If there is no match or the search element is not present in the given array, return -1.
Now, let's see the algorithm of linear search.
Algorithm
1. Linear_Search(a, n, val) // 'a' is the given array, 'n' is the size of given array, 'val' is the
value to search
2. Step 1: set pos = -1
3. Step 2: set i = 1
4. Step 3: repeat step 4 while i <= n
5. Step 4: if a[i] == val
6. set pos = i
7. print pos
8. go to step 6
9. [end of if]
10. set ii = i + 1
11. [end of loop]
12. Step 5: if pos = -1
13. print "value is not present in the array "
14. [end of if]
15. Step 6: exit
Working of Linear search
Now, let's see the working of the linear search Algorithm.
To understand the working of linear search algorithm, let's take an unsorted array. It will be
easy to understand the working of linear search with an example.
Let the elements of array are -

Let the element to be searched is K = 41


Now, start from the first element and compare K with each element of the array.

The value of K, i.e., 41, is not matched with the first element of the array. So, move to the
next element. And follow the same process until the respective element is found.

Now, the element to be searched is found. So algorithm will return the index of the element
matched.
Linear Search complexity
Now, let's see the time complexity of linear search in the best case, average case, and worst

Case Time Complexity

Best Case O(1)

Average Case O(n)

Worst Case O(n)

case. We will also see the space complexity of linear search.


1. Time Complexity
o Best Case Complexity - In Linear search, best case occurs when the element we are
finding is at the first position of the array. The best-case time complexity of linear
search is O(1).
o Average Case Complexity - The average case time complexity of linear search
is O(n).
o Worst Case Complexity - In Linear search, the worst case occurs when the element
we are looking is present at the end of the array. The worst-case in linear search could
be when the target element is not present in the given array, and we have to traverse
the entire array. The worst-case time complexity of linear search is O(n).
The time complexity of linear search is O(n) because every element in the array is compared
only once.
2. Space Complexity

Space Complexity O(1)

o The space complexity of linear search is O(1).

Binary Search Algorithm


In this article, we will discuss the Binary Search Algorithm. Searching is the process of
finding some particular element in the list. If the element is present in the list, then the
process is called successful, and the process returns the location of that element. Otherwise,
the search is called unsuccessful.
Linear Search and Binary Search are the two popular searching techniques. Here we will
discuss the Binary Search Algorithm.
Binary search is the search technique that works efficiently on sorted lists. Hence, to search
an element into some list using the binary search technique, we must ensure that the list is
sorted.
Binary search follows the divide and conquer approach in which the list is divided into two
halves, and the item is compared with the middle element of the list. If the match is found
then, the location of the middle element is returned. Otherwise, we search into either of the
halves depending upon the result produced through the match.
NOTE: Binary search can be implemented on sorted array elements. If the list elements are
not arranged in a sorted manner, we have first to sort them.
Now, let's see the algorithm of Binary Search.
Algorithm
1. Binary_Search(a, lower_bound, upper_bound, val) // 'a' is the given array, 'lower_bou
nd' is the index of the first array element, 'upper_bound' is the index of the last array e
lement, 'val' is the value to search
2. Step 1: set beg = lower_bound, end = upper_bound, pos = - 1
3. Step 2: repeat steps 3 and 4 while beg <=end
4. Step 3: set mid = (beg + end)/2
5. Step 4: if a[mid] = val
6. set pos = mid
7. print pos
8. go to step 6
9. else if a[mid] > val
10. set end = mid - 1
11. else
12. set beg = mid + 1
13. [end of if]
14. [end of loop]
15. Step 5: if pos = -1
16. print "value is not present in the array"
17. [end of if]
18. Step 6: exit
Working of Binary search
Now, let's see the working of the Binary Search Algorithm.
To understand the working of the Binary search algorithm, let's take a sorted array. It will be
easy to understand the working of Binary search with an example.
There are two methods to implement the binary search algorithm -
o Iterative method
o Recursive method
The recursive method of binary search follows the divide and conquer approach.
Let the elements of array are -

Let the element to search is, K = 56


We have to use the below formula to calculate the mid of the array -
1. mid = (beg + end)/2
So, in the given array -
beg = 0
end = 8
mid = (0 + 8)/2 = 4. So, 4 is the mid of the array.

Now, the element to search is found. So algorithm will return the index of the element
matched.
Binary Search complexity
Now, let's see the time complexity of Binary search in the best case, average case, and worst
case. We will also see the space complexity of Binary search.
1. Time Complexity

Case Time Complexity

Best Case O(1)

Average Case O(logn)

Worst Case O(logn)

o Best Case Complexity - In Binary search, best case occurs when the element to
search is found in first comparison, i.e., when the first middle element itself is the
element to be searched. The best-case time complexity of Binary search is O(1).
o Average Case Complexity - The average case time complexity of Binary search
is O(logn).
o Worst Case Complexity - In Binary search, the worst case occurs, when we have to
keep reducing the search space till it has only one element. The worst-case time
complexity of Binary search is O(logn).
2. Space Complexity

Space Complexity O(1)

o The space complexity of binary search is O(1).

Insertion Sort Algorithm


In this article, we will discuss the Insertion sort Algorithm. The working procedure of
insertion sort is also simple. This article will be very helpful and interesting to students as
they might face insertion sort as a question in their examinations. So, it is important to
discuss the topic.
Insertion sort works similar to the sorting of playing cards in hands. It is assumed that the
first card is already sorted in the card game, and then we select an unsorted card. If the
selected unsorted card is greater than the first card, it will be placed at the right side;
otherwise, it will be placed at the left side. Similarly, all unsorted cards are taken and put in
their exact place.
The same approach is applied in insertion sort. The idea behind the insertion sort is that first
take one element, iterate it through the sorted array. Although it is simple to use, it is not
appropriate for large data sets as the time complexity of insertion sort in the average case and
worst case is O(n2), where n is the number of items. Insertion sort is less efficient than the
other sorting algorithms like heap sort, quick sort, merge sort, etc.
Insertion sort has various advantages such as -
o Simple implementation
o Efficient for small data sets
o Adaptive, i.e., it is appropriate for data sets that are already substantially sorted.
Now, let's see the algorithm of insertion sort.
Algorithm
The simple steps of achieving the insertion sort are listed as follows -
Step 1 - If the element is the first element, assume that it is already sorted. Return 1.
Step2 - Pick the next element, and store it separately in a key.
Step3 - Now, compare the key with all elements in the sorted array.
Step 4 - If the element in the sorted array is smaller than the current element, then move to
the next element. Else, shift greater elements in the array towards the right.
Step 5 - Insert the value.
Step 6 - Repeat until the array is sorted.
Working of Insertion sort Algorithm
Now, let's see the working of the insertion sort Algorithm.
To understand the working of the insertion sort algorithm, let's take an unsorted array. It will
be easier to understand the insertion sort via an example.
Let the elements of array are -

Initially, the first two elements are compared in insertion sort.

Here, 31 is greater than 12. That means both elements are already in ascending order. So, for
now, 12 is stored in a sorted sub-array.

Now, move to the next two elements and compare them.


Here, 25 is smaller than 31. So, 31 is not at correct position. Now, swap 31 with 25. Along
with swapping, insertion sort will also check it with all elements in the sorted array.
For now, the sorted array has only one element, i.e. 12. So, 25 is greater than 12. Hence, the
sorted array remains sorted after swapping.

Now, two elements in the sorted array are 12 and 25. Move forward to the next elements that
are 31 and 8.

Both 31 and 8 are not sorted. So, swap them.

After swapping, elements 25 and 8 are unsorted.

So, swap them.

Now, elements 12 and 8 are unsorted.

So, swap them too.

Now, the sorted array has three items that are 8, 12 and 25. Move to the next items that are 31
and 32.

Hence, they are already sorted. Now, the sorted array includes 8, 12, 25 and 31.
Move to the next elements that are 32 and 17.

17 is smaller than 32. So, swap them.

Swapping makes 31 and 17 unsorted. So, swap them too.

Now, swapping makes 25 and 17 unsorted. So, perform swapping again.

Now, the array is completely sorted.


Insertion sort complexity
Now, let's see the time complexity of insertion sort in best case, average case, and in worst
case. We will also see the space complexity of insertion sort.
1. Time Complexity

Case Time Complexity

Best Case O(n)

Average Case O(n2)

Worst Case O(n2)

o Best Case Complexity - It occurs when there is no sorting required, i.e. the array is
already sorted. The best-case time complexity of insertion sort is O(n).
o Average Case Complexity - It occurs when the array elements are in jumbled order
that is not properly ascending and not properly descending. The average case time
complexity of insertion sort is O(n2).
o Worst Case Complexity - It occurs when the array elements are required to be sorted
in reverse order. That means suppose you have to sort the array elements in ascending
order, but its elements are in descending order. The worst-case time complexity of
insertion sort is O(n2).
2. Space Complexity

Space Complexity O(1)

Stable YES

o The space complexity of insertion sort is O(1). It is because, in insertion sort, an extra
variable is required for swapping.

Selection Sort Algorithm


In this article, we will discuss the Selection sort Algorithm. The working procedure of
selection sort is also simple. This article will be very helpful and interesting to students as
they might face selection sort as a question in their examinations. So, it is important to
discuss the topic.
In selection sort, the smallest value among the unsorted elements of the array is selected in
every pass and inserted to its appropriate position into the array. It is also the simplest
algorithm. It is an in-place comparison sorting algorithm. In this algorithm, the array is
divided into two parts, first is sorted part, and another one is the unsorted part. Initially, the
sorted part of the array is empty, and unsorted part is the given array. Sorted part is placed at
the left, while the unsorted part is placed at the right.
In selection sort, the first smallest element is selected from the unsorted array and placed at
the first position. After that second smallest element is selected and placed in the second
position. The process continues until the array is entirely sorted.
The average and worst-case complexity of selection sort is O(n2), where n is the number of
items. Due to this, it is not suitable for large data sets.
Selection sort is generally used when -
o A small array is to be sorted
o Swapping cost doesn't matter
o It is compulsory to check all elements
Now, let's see the algorithm of selection sort.
Algorithm
1. SELECTION SORT(arr, n)
2.
3. Step 1: Repeat Steps 2 and 3 for i = 0 to n-1
4. Step 2: CALL SMALLEST(arr, i, n, pos)
5. Step 3: SWAP arr[i] with arr[pos]
6. [END OF LOOP]
7. Step 4: EXIT
8.
9. SMALLEST (arr, i, n, pos)
10. Step 1: [INITIALIZE] SET SMALL = arr[i]
11. Step 2: [INITIALIZE] SET pos = i
12. Step 3: Repeat for j = i+1 to n
13. if (SMALL > arr[j])
14. SET SMALL = arr[j]
15. SET pos = j
16. [END OF if]
17. [END OF LOOP]
18. Step 4: RETURN pos
Working of Selection sort Algorithm
Now, let's see the working of the Selection sort Algorithm.
To understand the working of the Selection sort algorithm, let's take an unsorted array. It will
be easier to understand the Selection sort via an example.
Let the elements of array are -

Now, for the first position in the sorted array, the entire array is to be scanned sequentially.
At present, 12 is stored at the first position, after searching the entire array, it is found
that 8 is the smallest value.

So, swap 12 with 8. After the first iteration, 8 will appear at the first position in the sorted
array.
For the second position, where 29 is stored presently, we again sequentially scan the rest of
the items of unsorted array. After scanning, we find that 12 is the second lowest element in
the array that should be appeared at second position.

Now, swap 29 with 12. After the second iteration, 12 will appear at the second position in the
sorted array. So, after two iterations, the two smallest values are placed at the beginning in a
sorted way.

The same process is applied to the rest of the array elements. Now, we are showing a pictorial
representation of the entire sorting process.

Now, the array is completely sorted.


Selection sort complexity
Now, let's see the time complexity of selection sort in best case, average case, and in worst
case. We will also see the space complexity of the selection sort.
1. Time Complexity
Case Time Complexity

Best Case O(n2)

Average Case O(n2)

Worst Case O(n2)

o Best Case Complexity - It occurs when there is no sorting required, i.e. the array is
already sorted. The best-case time complexity of selection sort is O(n2).
o Average Case Complexity - It occurs when the array elements are in jumbled order
that is not properly ascending and not properly descending. The average case time
complexity of selection sort is O(n2).
o Worst Case Complexity - It occurs when the array elements are required to be sorted
in reverse order. That means suppose you have to sort the array elements in ascending
order, but its elements are in descending order. The worst-case time complexity of
selection sort is O(n2).
2. Space Complexity

Space Complexity O(1)

Stable YES

o The space complexity of selection sort is O(1). It is because, in selection sort, an extra
variable is required for swapping.

Bubble sort Algorithm


In this article, we will discuss the Bubble sort Algorithm. The working procedure of bubble
sort is simplest. This article will be very helpful and interesting to students as they might face
bubble sort as a question in their examinations. So, it is important to discuss the topic.
Bubble sort works on the repeatedly swapping of adjacent elements until they are not in the
intended order. It is called bubble sort because the movement of array elements is just like the
movement of air bubbles in the water. Bubbles in water rise up to the surface; similarly, the
array elements in bubble sort move to the end in each iteration.
Although it is simple to use, it is primarily used as an educational tool because the
performance of bubble sort is poor in the real world. It is not suitable for large data sets. The
average and worst-case complexity of Bubble sort is O(n2), where n is a number of items.
Bubble short is majorly used where -
o complexity does not matter
o simple and shortcode is preferred
Algorithm
In the algorithm given below, suppose arr is an array of n elements. The
assumed swap function in the algorithm will swap the values of given array elements.
1. begin BubbleSort(arr)
2. for all array elements
3. if arr[i] > arr[i+1]
4. swap(arr[i], arr[i+1])
5. end if
6. end for
7. return arr
8. end BubbleSort
Working of Bubble sort Algorithm
Now, let's see the working of Bubble sort Algorithm.
To understand the working of bubble sort algorithm, let's take an unsorted array. We are
taking a short and accurate array, as we know the complexity of bubble sort is O(n2).
Let the elements of array are -

First Pass
Sorting will start from the initial two elements. Let compare them to check which is greater.

Here, 32 is greater than 13 (32 > 13), so it is already sorted. Now, compare 32 with 26.

Here, 26 is smaller than 36. So, swapping is required. After swapping new array will look
like -

Now, compare 32 and 35.


Here, 35 is greater than 32. So, there is no swapping required as they are already sorted.
Now, the comparison will be in between 35 and 10.

Here, 10 is smaller than 35 that are not sorted. So, swapping is required. Now, we reach at the
end of the array. After first pass, the array will be -

Now, move to the second iteration.


Second Pass
The same process will be followed for second iteration.

Here, 10 is smaller than 32. So, swapping is required. After swapping, the array will be -

Now, move to the third iteration.


Third Pass
The same process will be followed for third iteration.
Here, 10 is smaller than 26. So, swapping is required. After swapping, the array will be -

Now, move to the fourth iteration.


Fourth pass
Similarly, after the fourth iteration, the array will be -

Hence, there is no swapping required, so the array is completely sorted.


Bubble sort complexity
Now, let's see the time complexity of bubble sort in the best case, average case, and worst
case. We will also see the space complexity of bubble sort.
1. Time Complexity

Case Time Complexity

Best Case O(n)

Average Case O(n2)

Worst Case O(n2)

o Best Case Complexity - It occurs when there is no sorting required, i.e. the array is
already sorted. The best-case time complexity of bubble sort is O(n).
o Average Case Complexity - It occurs when the array elements are in jumbled order
that is not properly ascending and not properly descending. The average case time
complexity of bubble sort is O(n2).
o Worst Case Complexity - It occurs when the array elements are required to be sorted
in reverse order. That means suppose you have to sort the array elements in ascending
order, but its elements are in descending order. The worst-case time complexity of
bubble sort is O(n2).
2. Space Complexity

Space Complexity O(1)

Stable YES

o The space complexity of bubble sort is O(1). It is because, in bubble sort, an extra
variable is required for swapping.
o The space complexity of optimized bubble sort is O(2). It is because two extra
variables are required in optimized bubble sort.

Quick Sort Algorithm

In this article, we will discuss the Quicksort Algorithm. The working procedure of Quicksort
is also simple. This article will be very helpful and interesting to students as they might face
quicksort as a question in their examinations. So, it is important to discuss the topic.

Sorting is a way of arranging items in a systematic manner. Quicksort is the widely used
sorting algorithm that makes n log n comparisons in average case for sorting an array of n
elements. It is a faster and highly efficient sorting algorithm. This algorithm follows the
divide and conquer approach. Divide and conquer is a technique of breaking down the
algorithms into subproblems, then solving the subproblems, and combining the results back
together to solve the original problem.

Divide: In Divide, first pick a pivot element. After that, partition or rearrange the array into
two sub-arrays such that each element in the left sub-array is less than or equal to the pivot
element and each element in the right sub-array is larger than the pivot element.

Conquer: Recursively, sort two subarrays with Quicksort.

Backward Skip 10sPlay VideoForward Skip 10s

Combine: Combine the already sorted array.

Quicksort picks an element as pivot, and then it partitions the given array around the picked
pivot element. In quick sort, a large array is divided into two arrays in which one holds values
that are smaller than the specified value (Pivot), and another array holds the values that are
greater than the pivot.
After that, left and right sub-arrays are also partitioned using the same approach. It will
continue until the single element remains in the sub-array.

Choosing the pivot

Picking a good pivot is necessary for the fast implementation of quicksort. However, it is
typical to determine a good pivot. Some of the ways of choosing a pivot are as follows -

o Pivot can be random, i.e. select the random pivot from the given array.

o Pivot can either be the rightmost element of the leftmost element of the given array.

o Select median as the pivot element.

Algorithm

Algorithm:

1. QUICKSORT (array A, start, end)


2. {
3. 1 if (start < end)
4. 2{
5. 3 p = partition(A, start, end)
6. 4 QUICKSORT (A, start, p - 1)
7. 5 QUICKSORT (A, p + 1, end)
8. 6}
9. }

Partition Algorithm:

The partition algorithm rearranges the sub-arrays in a place.

1. PARTITION (array A, start, end)


2. {
3. 1 pivot ? A[end]
4. 2 i ? start-1
5. 3 for j ? start to end -1 {
6. 4 do if (A[j] < pivot) {
7. 5 then i ? i + 1
8. 6 swap A[i] with A[j]
9. 7 }}
10. 8 swap A[i+1] with A[end]
11. 9 return i+1
12. }

Working of Quick Sort Algorithm

Now, let's see the working of the Quicksort Algorithm.

To understand the working of quick sort, let's take an unsorted array. It will make the concept
more clear and understandable.

Let the elements of array are -

In the given array, we consider the leftmost element as pivot. So, in this case, a[left] = 24,
a[right] = 27 and a[pivot] = 24.

Since, pivot is at left, so algorithm starts from right and move towards left.

Now, a[pivot] < a[right], so algorithm moves forward one position towards left, i.e. -

Now, a[left] = 24, a[right] = 19, and a[pivot] = 24.

Because, a[pivot] > a[right], so, algorithm will swap a[pivot] with a[right], and pivot moves
to right, as -
Now, a[left] = 19, a[right] = 24, and a[pivot] = 24. Since, pivot is at right, so algorithm starts
from left and moves to right.

As a[pivot] > a[left], so algorithm moves one position to right as -

Now, a[left] = 9, a[right] = 24, and a[pivot] = 24. As a[pivot] > a[left], so algorithm moves
one position to right as -

Now, a[left] = 29, a[right] = 24, and a[pivot] = 24. As a[pivot] < a[left], so, swap a[pivot] and
a[left], now pivot is at left, i.e. -

Since, pivot is at left, so algorithm starts from right, and move to left. Now, a[left] = 24,
a[right] = 29, and a[pivot] = 24. As a[pivot] < a[right], so algorithm moves one position to
left, as -
Now, a[pivot] = 24, a[left] = 24, and a[right] = 14. As a[pivot] > a[right], so, swap a[pivot]
and a[right], now pivot is at right, i.e. -

Now, a[pivot] = 24, a[left] = 14, and a[right] = 24. Pivot is at right, so the algorithm starts
from left and move to right.

Now, a[pivot] = 24, a[left] = 24, and a[right] = 24. So, pivot, left and right are pointing the
same element. It represents the termination of procedure.

Element 24, which is the pivot element is placed at its exact position.

Elements that are right side of element 24 are greater than it, and the elements that are left
side of element 24 are smaller than it.

Now, in a similar manner, quick sort algorithm is separately applied to the left and right
sub-arrays. After sorting gets done, the array will be -
Quicksort complexity

Now, let's see the time complexity of quicksort in best case, average case, and in worst case.
We will also see the space complexity of quicksort.

1. Time Complexity

Case Time Complexity

Best Case O(n*logn)

Average Case O(n*logn)

Worst Case O(n2)

o Best Case Complexity - In Quicksort, the best-case occurs when the pivot element is
the middle element or near to the middle element. The best-case time complexity of
quicksort is O(n*logn).

o Average Case Complexity - It occurs when the array elements are in jumbled order
that is not properly ascending and not properly descending. The average case time
complexity of quicksort is O(n*logn).

o Worst Case Complexity - In quick sort, worst case occurs when the pivot element is
either greatest or smallest element. Suppose, if the pivot element is always the last
element of the array, the worst case would occur when the given array is sorted
already in ascending or descending order. The worst-case time complexity of
quicksort is O(n2).

Though the worst-case complexity of quicksort is more than other sorting algorithms such
as Merge sort and Heap sort, still it is faster in practice. Worst case in quick sort rarely
occurs because by changing the choice of pivot, it can be implemented in different ways.
Worst case in quicksort can be avoided by choosing the right pivot element.

2. Space Complexity

Space Complexity O(n*logn)

Stable NO
o The space complexity of quicksort is O(n*logn).

Merge Sort Algorithm

In this article, we will discuss the merge sort Algorithm. Merge sort is the sorting technique
that follows the divide and conquer approach. This article will be very helpful and interesting
to students as they might face merge sort as a question in their examinations. In coding or
technical interviews for software engineers, sorting algorithms are widely asked. So, it is
important to discuss the topic.

Merge sort is similar to the quick sort algorithm as it uses the divide and conquer approach to
sort the elements. It is one of the most popular and efficient sorting algorithm. It divides the
given list into two equal halves, calls itself for the two halves and then merges the two sorted
halves. We have to define the merge() function to perform the merging.

The sub-lists are divided again and again into halves until the list cannot be divided further.
Then we combine the pair of one element lists into two-element lists, sorting them in the
process. The sorted two-element pairs is merged into the four-element lists, and so on until
we get the sorted list.

Now, let's see the algorithm of merge sort.

Algorithm

In the following algorithm, arr is the given array, beg is the starting element, and end is the
last element of the array.

1. MERGE_SORT(arr, beg, end)


2.
3. if beg < end
4. set mid = (beg + end)/2
5. MERGE_SORT(arr, beg, mid)
6. MERGE_SORT(arr, mid + 1, end)
7. MERGE (arr, beg, mid, end)
8. end of if
9.
10. END MERGE_SORT

The important part of the merge sort is the MERGE function. This function performs the
merging of two sorted sub-arrays that are A[beg…mid] and A[mid+1…end], to build one
sorted array A[beg…end]. So, the inputs of the MERGE function are A[], beg,
mid, and end.

Working of Merge sort Algorithm

Now, let's see the working of merge sort Algorithm.

To understand the working of the merge sort algorithm, let's take an unsorted array. It will be
easier to understand the merge sort via an example.
Let the elements of array are -

According to the merge sort, first divide the given array into two equal halves. Merge sort
keeps dividing the list into equal parts until it cannot be further divided.

As there are eight elements in the given array, so it is divided into two arrays of size 4.

Now, again divide these two arrays into halves. As they are of size 4, so divide them into new
arrays of size 2.

Now, again divide these arrays to get the atomic value that cannot be further divided.

Now, combine them in the same manner they were broken.

In combining, first compare the element of each array and then combine them into another
array in sorted order.

So, first compare 12 and 31, both are in sorted positions. Then compare 25 and 8, and in the
list of two values, put 8 first followed by 25. Then compare 32 and 17, sort them and put 17
first followed by 32. After that, compare 40 and 42, and place them sequentially.

In the next iteration of combining, now compare the arrays with two data values and merge
them into an array of found values in sorted order.
Now, there is a final merging of the arrays. After the final merging of above arrays, the array
will look like -

Now, the array is completely sorted.

Merge sort complexity

Now, let's see the time complexity of merge sort in best case, average case, and in worst case.
We will also see the space complexity of the merge sort.

1. Time Complexity

Case Time Complexity

Best Case O(n*logn)

Average Case O(n*logn)

Worst Case O(n*logn)

o Best Case Complexity - It occurs when there is no sorting required, i.e. the array is
already sorted. The best-case time complexity of merge sort is O(n*logn).

o Average Case Complexity - It occurs when the array elements are in jumbled order
that is not properly ascending and not properly descending. The average case time
complexity of merge sort is O(n*logn).

o Worst Case Complexity - It occurs when the array elements are required to be sorted
in reverse order. That means suppose you have to sort the array elements in ascending
order, but its elements are in descending order. The worst-case time complexity of
merge sort is O(n*logn).

2. Space Complexity

Space Complexity O(n)

Stable YES
o The space complexity of merge sort is O(n). It is because, in merge sort, an extra
variable is required for swapping.

Two-way merge sort

Overview of Merge Sort

Merge Sort is an efficient and easy-to-implement sorting algorithm that uses the
divide-and-conquer approach. It breaks down the problem into smaller sub-problems to
process them individually and then joins them to make one complete sorted list.

The divide step in Merge Sort entails dividing the array in half and recursively sorting each
half. The conquer step involves merging the sorted sub-arrays to get the final sorted array.
The merging stage of Merge Sort, which combines two sorted sub-arrays into a single sorted
array, takes the longest.

Two-Way Merge Sort

Two-way merge Sort merges two sorted lists into one sorted list. In Merge Sort, it is
commonly used to produce the smallest item in each step-given list sorted by length and to
produce a sorted list that contains all the items in any input list proportionate to the total
length of the input lists.

Unlike K-Way Merge Sort, which merges K-sorted lists, Two-Way Merge Sort merges only
two sorted lists.

Backward Skip 10sPlay VideoForward Skip 10s

How Two-Way Merge Sort Works

The Two-Way Merge Sort algorithm divides, sorts, and merges a list to create a complete
sorted list. It selects the smaller element during the merging process.

Here are the steps for the implementation of two-way merge sort:

1. Set the chunk size to 1


2. Loop over the list in chunks of the current size
3. Merge adjacent pairs of chunks
4. Increase the chunk size to 2
5. Repeat the process until the chunk size is greater than or equal to the length of the list
This code sorts an input array using the merge sort algorithm. It checks if the array has one or
zero elements and returns them as is. For arrays with more than one element, the code splits
them into two halves and sorts each half using merge_Sort(). The sorted halves are merged
using the merge() function, which adds the smaller element of each half to the output array
until all elements are added. The sorted array is then returned.

Merge_Sort() sorts an unsorted array in ascending order. You can modify merge() to sort in
descending order.

Advantages:

1. Efficient for extensive data: Two-way merge sort is very efficient for large datasets.
The time complexity is O(nlogn), which makes it suitable for sorting large datasets.
2. Stable: It is a stable sort, which means that equal elements remain in their relative
positions after sorting.
3. Divide and Conquer: It uses the divide and conquer approach, which makes it easier
to understand and implement.

Disadvantages:

1. Space Complexity: Two-way merge sort requires additional space for the temporary
arrays used during the merging process. This can be a disadvantage when dealing with
large datasets.
2. Not efficient for small arrays: It may not be the most efficient choice for small
arrays or partially sorted arrays.
3. Complexity: The algorithm is more complex compared to simple sorting algorithms
like bubble sort and insertion sort.

Merge sort is efficient with a time complexity of O(n log n), making it ideal for large
datasets. However, it requires extra space for temporary arrays during merging, which can be
a disadvantage when dealing with large datasets.

Heap Sort Algorithm


In this article, we will discuss the Heapsort Algorithm. Heap sort processes the elements by
creating the min-heap or max-heap using the elements of the given array. Min-heap or
max-heap represents the ordering of array in which the root element represents the minimum
or maximum element of the array.

Heap sort basically recursively performs two main operations -

o Build a heap H, using the elements of array.

o Repeatedly delete the root element of the heap formed in 1st phase.

Before knowing more about the heap sort, let's first see a brief description of Heap.

What is a heap?

A heap is a complete binary tree, and the binary tree is a tree in which the node can have the
utmost two children. A complete binary tree is a binary tree in which all the levels except the
last level, i.e., leaf node, should be completely filled, and all the nodes should be
left-justified.

What is heap sort?

Heapsort is a popular and efficient sorting algorithm. The concept of heap sort is to eliminate
the elements one by one from the heap part of the list, and then insert them into the sorted
part of the list.

Heapsort is the in-place sorting algorithm.

Now, let's see the algorithm of heap sort.

Algorithm

1. HeapSort(arr)
2. BuildMaxHeap(arr)
3. for i = length(arr) to 2
4. swap arr[1] with arr[i]
5. heap_size[arr] = heap_size[arr] ? 1
6. MaxHeapify(arr,1)
7. End

BuildMaxHeap(arr)

1. BuildMaxHeap(arr)
2. heap_size(arr) = length(arr)
3. for i = length(arr)/2 to 1
4. MaxHeapify(arr,i)
5. End

MaxHeapify(arr,i)
1. MaxHeapify(arr,i)
2. L = left(i)
3. R = right(i)
4. if L ? heap_size[arr] and arr[L] > arr[i]
5. largest = L
6. else
7. largest = i
8. if R ? heap_size[arr] and arr[R] > arr[largest]
9. largest = R
10. if largest != i
11. swap arr[i] with arr[largest]
12. MaxHeapify(arr,largest)
13. End

Working of Heap sort Algorithm

Now, let's see the working of the Heapsort Algorithm.

In heap sort, basically, there are two phases involved in the sorting of elements. By using the
heap sort algorithm, they are as follows -

o The first step includes the creation of a heap by adjusting the elements of the array.

o After the creation of heap, now remove the root element of the heap repeatedly by
shifting it to the end of the array, and then store the heap structure with the remaining
elements.

Now let's see the working of heap sort in detail by using an example. To understand it more
clearly, let's take an unsorted array and try to sort it using heap sort. It will make the
explanation clearer and easier.

First, we have to construct a heap from the given array and convert it into max heap.

After converting the given heap into max heap, the array elements are -
Next, we have to delete the root element (89) from the max heap. To delete this node, we
have to swap it with the last node, i.e. (11). After deleting the root element, we again have to
heapify it to convert it into max heap.

After swapping the array element 89 with 11, and converting the heap into max-heap, the
elements of array are -

In the next step, again, we have to delete the root element (81) from the max heap. To delete
this node, we have to swap it with the last node, i.e. (54). After deleting the root element, we
again have to heapify it to convert it into max heap.

After swapping the array element 81 with 54 and converting the heap into max-heap, the
elements of array are -

In the next step, we have to delete the root element (76) from the max heap again. To delete
this node, we have to swap it with the last node, i.e. (9). After deleting the root element, we
again have to heapify it to convert it into max heap.
After swapping the array element 76 with 9 and converting the heap into max-heap, the
elements of array are -

In the next step, again we have to delete the root element (54) from the max heap. To delete
this node, we have to swap it with the last node, i.e. (14). After deleting the root element, we
again have to heapify it to convert it into max heap.

After swapping the array element 54 with 14 and converting the heap into max-heap, the
elements of array are -

In the next step, again we have to delete the root element (22) from the max heap. To delete
this node, we have to swap it with the last node, i.e. (11). After deleting the root element, we
again have to heapify it to convert it into max heap.

After swapping the array element 22 with 11 and converting the heap into max-heap, the
elements of array are -
In the next step, again we have to delete the root element (14) from the max heap. To delete
this node, we have to swap it with the last node, i.e. (9). After deleting the root element, we
again have to heapify it to convert it into max heap.

After swapping the array element 14 with 9 and converting the heap into max-heap, the
elements of array are -

In the next step, again we have to delete the root element (11) from the max heap. To delete
this node, we have to swap it with the last node, i.e. (9). After deleting the root element, we
again have to heapify it to convert it into max heap.

After swapping the array element 11 with 9, the elements of array are -

Now, heap has only one element left. After deleting it, heap will be empty.

After completion of sorting, the array elements are -


Now, the array is completely sorted.

Heap sort complexity

Now, let's see the time complexity of Heap sort in the best case, average case, and worst case.
We will also see the space complexity of Heapsort.

1. Time Complexity

Case Time Complexity

Best Case O(n logn)

Average Case O(n log n)

Worst Case O(n log n)

o Best Case Complexity - It occurs when there is no sorting required, i.e. the array is
already sorted. The best-case time complexity of heap sort is O(n logn).

o Average Case Complexity - It occurs when the array elements are in jumbled order
that is not properly ascending and not properly descending. The average case time
complexity of heap sort is O(n log n).

o Worst Case Complexity - It occurs when the array elements are required to be sorted
in reverse order. That means suppose you have to sort the array elements in ascending
order, but its elements are in descending order. The worst-case time complexity of
heap sort is O(n log n).

The time complexity of heap sort is O(n logn) in all three cases (best case, average case, and
worst case). The height of a complete binary tree having n elements is logn.

2. Space Complexity

Space Complexity O(1)

Stable N0

o The space complexity of Heap sort is O(1).

Radix Sort Algorithm

Radix sort is the linear sorting algorithm that is used for integers. In Radix sort, there is digit
by digit sorting is performed that is started from the least significant digit to the most
significant digit.
The process of radix sort works similar to the sorting of students names, according to the
alphabetical order. In this case, there are 26 radix formed due to the 26 alphabets in English.
In the first pass, the names of students are grouped according to the ascending order of the
first letter of their names. After that, in the second pass, their names are grouped according to
the ascending order of the second letter of their name. And the process continues until we
find the sorted list.

Now, let's see the algorithm of Radix sort.

Algorithm

1. radixSort(arr)
2. max = largest element in the given array
3. d = number of digits in the largest element (or, max)
4. Now, create d buckets of size 0 - 9
5. for i -> 0 to d
6. sort the array elements using counting sort (or any stable sort) according to the digits
at
7. the ith place

Working of Radix sort Algorithm

Now, let's see the working of Radix sort Algorithm.

The steps used in the sorting of radix sort are listed as follows -

o First, we have to find the largest element (suppose max) from the given array.
Suppose 'x' be the number of digits in max. The 'x' is calculated because we need to
go through the significant places of all elements.

o After that, go through one by one each significant place. Here, we have to use any
stable sorting algorithm to sort the digits of each significant place.

Now let's see the working of radix sort in detail by using an example. To understand it more
clearly, let's take an unsorted array and try to sort it using radix sort. It will make the
explanation clearer and easier.

In the given array, the largest element is 736 that have 3 digits in it. So, the loop will run up
to three times (i.e., to the hundreds place). That means three passes are required to sort the
array.

Now, first sort the elements on the basis of unit place digits (i.e., x = 0). Here, we are using
the counting sort algorithm to sort the elements.

Pass 1:
In the first pass, the list is sorted on the basis of the digits at 0's place.

After the first pass, the array elements are -

Pass 2:

In this pass, the list is sorted on the basis of the next significant digits (i.e., digits at
10th place).

After the second pass, the array elements are -

Pass 3:
In this pass, the list is sorted on the basis of the next significant digits (i.e., digits at
100th place).

After the third pass, the array elements are -

Now, the array is sorted in ascending order.

Radix sort complexity

Now, let's see the time complexity of Radix sort in best case, average case, and worst case.
We will also see the space complexity of Radix sort.

1. Time Complexity

Case Time Complexity

Best Case Ω(n+k)

Average Case θ(nk)

Worst Case O(nk)

o Best Case Complexity - It occurs when there is no sorting required, i.e. the array is
already sorted. The best-case time complexity of Radix sort is Ω(n+k).
o Average Case Complexity - It occurs when the array elements are in jumbled order
that is not properly ascending and not properly descending. The average case time
complexity of Radix sort is θ(nk).

o Worst Case Complexity - It occurs when the array elements are required to be sorted
in reverse order. That means suppose you have to sort the array elements in ascending
order, but its elements are in descending order. The worst-case time complexity of
Radix sort is O(nk).

Radix sort is a non-comparative sorting algorithm that is better than the comparative sorting
algorithms. It has linear time complexity that is better than the comparative algorithms with
complexity O(n logn).

2. Space Complexity

Space Complexity O(n + k)

Stable YES

o The space complexity of Radix sort is O(n + k).

Hash Functions and Types of Hash functions

Hash functions are a fundamental concept in computer science and play a crucial role in
various applications such as data storage, retrieval, and cryptography. In data structures and
algorithms (DSA), hash functions are primarily used in hash tables, which are essential for
efficient data management. This article delves into the intricacies of hash functions, their
properties, and the different types of hash functions used in DSA.

What is a Hash Function?

A hash function is a function that takes an input (or ‘message’) and returns a fixed-size
string of bytes. The output, typically a number, is called the hash code or hash value. The
main purpose of a hash function is to efficiently map data of arbitrary size to fixed-size
values, which are often used as indexes in hash tables.

Key Properties of Hash Functions

● Deterministic: A hash function must consistently produce the same output for the
same input.

● Fixed Output Size: The output of a hash function should have a fixed size, regardless
of the size of the input.

● Efficiency: The hash function should be able to process input quickly.

● Uniformity: The hash function should distribute the hash values uniformly across the
output space to avoid clustering.
● Pre-image Resistance: It should be computationally infeasible to reverse the hash
function, i.e., to find the original input given a hash value.

● Collision Resistance: It should be difficult to find two different inputs that produce
the same hash value.

● Avalanche Effect: A small change in the input should produce a significantly


different hash value.

Applications of Hash Functions

● Hash Tables: The most common use of hash functions in DSA is in hash tables,
which provide an efficient way to store and retrieve data.

● Data Integrity: Hash functions are used to ensure the integrity of data by generating
checksums.

● Cryptography: In cryptographic applications, hash functions are used to create


secure hash algorithms like SHA-256.

● Data Structures: Hash functions are utilized in various data structures such as Bloom
filters and hash sets.

Types of Hash Functions

There are many hash functions that use numeric or alphanumeric keys. This article focuses on
discussing different hash functions:

1. Division Method.

2. Multiplication Method

3. Mid-Square Method

4. Folding Method

5. Cryptographic Hash Functions

6. Universal Hashing

7. Perfect Hashing

Let’s begin discussing these methods in detail.

1. Division Method

The division method involves dividing the key by a prime number and using the remainder as
the hash value.

h(k)=k mod m
Where k is the key and 𝑚m is a prime number.

Advantages:

● Simple to implement.

● Works well when 𝑚m is a prime number.

Disadvantages:

● Poor distribution if 𝑚m is not chosen wisely.

2. Multiplication Method

In the multiplication method, a constant 𝐴A (0 < A < 1) is used to multiply the key. The
fractional part of the product is then multiplied by 𝑚m to get the hash value.

h(k)=⌊m(kAmod1)⌋

Where ⌊ ⌋ denotes the floor function.

Advantages:

● Less sensitive to the choice of 𝑚m.

Disadvantages:

● More complex than the division method.

3. Mid-Square Method

In the mid-square method, the key is squared, and the middle digits of the result are taken as
the hash value.

Steps:

1. Square the key.

2. Extract the middle digits of the squared value.

Advantages:

● Produces a good distribution of hash values.

Disadvantages:

● May require more computational effort.

4. Folding Method
The folding method involves dividing the key into equal parts, summing the parts, and then
taking the modulo with respect to 𝑚m.

Steps:

1. Divide the key into parts.

2. Sum the parts.

3. Take the modulo 𝑚m of the sum.

Advantages:

● Simple and easy to implement.

Disadvantages:

● Depends on the choice of partitioning scheme.

5. Cryptographic Hash Functions

Cryptographic hash functions are designed to be secure and are used in cryptography.
Examples include MD5, SHA-1, and SHA-256.

Characteristics:

● Pre-image resistance.

● Second pre-image resistance.

● Collision resistance.

Advantages:

● High security.

Disadvantages:

● Computationally intensive.

6. Universal Hashing

Universal hashing uses a family of hash functions to minimize the chance of collision for any
given set of inputs.

h(k)=((a⋅k+b)modp)modm

Where a and b are randomly chosen constants, p is a prime number greater than m, and k is
the key.
Advantages:

● Reduces the probability of collisions.

Disadvantages:

● Requires more computation and storage.

7. Perfect Hashing

Perfect hashing aims to create a collision-free hash function for a static set of keys. It
guarantees that no two keys will hash to the same value.

Types:

● Minimal Perfect Hashing: Ensures that the range of the hash function is equal to the
number of keys.

● Non-minimal Perfect Hashing: The range may be larger than the number of keys.

Advantages:

● No collisions.

Disadvantages:

● Complex to construct.

Collision Resolution Techniques

Languages like English or Spanish are not understood by computers, users must
communicate with computers using a set of languages called programming languages. A
computer can be programmed using a variety of language families. Computers are
instruments created to address complicated issues, but only when a programming language
and programmer are used. Computer software is what powers the various browsers, games,
emails, operating systems, and applications. Any problem can be solved creatively through
programming.

Computational language is used in programming to provide the computer with a set of


instructions for a task. With the right instruction groups and specialized software, any
complexity issue can be resolved. There are three fundamental ideas in computer
programming design. They are repetition, selection, and sequence. The series is the first
essential idea that tells you to execute the instructions in a specific order; choosing the right
command comes next. The repetition of the same action, often known as iteration, is the
fourth idea. In the creative process of programming, the programmer chooses the appropriate
commands to address any issue.

Programming Languages
We require a variety of programming languages because no human language can be
understood by computers. Every language has advantages and disadvantages, and some are
more appropriate for a given task than others. Many diverse specialists, including software
developers, computer system engineers, web designers, app developers, etc., require a
programming language to do a variety of jobs; there are many programming languages. More
than 50 programming languages are used to perform different tasks and the most commonly
used languages are HTML, JAVA, and C- language.

Computation Thinking

Using four fundamental patterns, computational thinking is a method for solving any
problem. If we effectively comprehend and use the four fundamental patterns, computational
thinking for programming becomes simple. The first step in effectively understanding an
issue is to break it down into smaller components. We can more effectively use other
computational thinking components when we divide the problems into smaller, more
manageable pieces. The second component in this process is pattern recognition; the
problems are reviewed to see if there is any sequence. If there are any patterns, they have
been categorized appropriately. If no patterns are found, further simplification of that issue is
not necessary. An abstraction or generalization of the issue serves as the third component.
When you stand back from the specifics of a problem, you can develop a more general
answer that can be useful in a number of different ways. The Algorithm, the fourth and final
component, is where problems are incrementally addressed. Making a plan for your solution
is crucial. A method for figuring out step-by-step directions on how to tackle any problem is
to use an algorithm.

The purpose of collision resolution during insertion is to locate an open location in the hash
table when the record’s home position is already taken. Any collision resolution technique
may be thought of as creating a series of hash table slots that may or may not contain the
record. The key will be in its home position in the first position in the sequence. The collision
resolution policy shifts to the following location in the sequence if the home position is
already occupied. Another slot needs to be sought if this is also taken, and so on. The probe
sequence is a collection of slots that is produced by a probe function that we will refer to as p.
This is how insertion operates.

Collision in Hashing

In this, the hash function is used to find the index of the array. The hash value is used to
create an index for the key in the hash table. The hash function may return the same hash
value for two or more keys. When two or more keys have the same hash value, a collision
happens. To handle this collision, we use collision resolution techniques.

Collision Resolution Techniques

There are two types of collision resolution techniques.

● Separate chaining (open hashing)

● Open addressing (closed hashing)


Separate chaining: This method involves making a linked list out of the slot where the
collision happened, then adding the new key to the list. Separate chaining is the term used to
describe how this connected list of slots resembles a chain. It is more frequently utilized
when we are unsure of the number of keys to add or remove.

Time complexity

● Its worst-case complexity for searching is o(n).

● Its worst-case complexity for deletion is o(n).

Advantages of separate chaining

● It is easy to implement.

● The hash table never fills full, so we can add more elements to the chain.

● It is less sensitive to the function of the hashing.

Disadvantages of separate chaining

● In this, the cache performance of chaining is not good.

● Memory wastage is too much in this method.

● It requires more space for element links.

Open addressing: To prevent collisions in the hashing table, open addressing is employed as
a collision-resolution technique. No key is kept anywhere else besides the hash table. As a
result, the hash table’s size is never equal to or less than the number of keys. Additionally
known as closed hashing.

The following techniques are used in open addressing:

● Linear probing

● Quadratic probing

● Double hashing

Linear probing: This involves doing a linear probe for the following slot when a collision
occurs and continuing to do so until an empty slot is discovered.
The worst time to search for an element in linear probing is O. The cache performs best with
linear probing, but clustering is a concern. This method’s key benefit is that it is simple to
calculate.

Disadvantages of linear probing:

● The main problem is clustering.


● It takes too much time to find an empty slot.

Quadratic probing: When a collision happens in this, we probe for the i2-nd slot in the
ith iteration, continuing to do so until an empty slot is discovered. In comparison to linear
probing, quadratic probing has a worse cache performance. Additionally, clustering is less of
a concern with quadratic probing.

Double hashing: In this, you employ a different hashing algorithm, and in the ith iteration,
you look for (i * hash 2(x)). The determination of two hash functions requires more time.
Although there is no clustering issue, the performance of the cache is relatively poor when
using double probing.

You might also like