Searching and Sorting.docx
Searching and Sorting.docx
Unit 4: Sorting
Sorting refers to arranging data in a particular format. Sorting algorithm specifies the way to
arrange data in a particular order. Most common orders are in numerical or lexicographical
order.
The importance of sorting lies in the fact that data searching can be optimized to a very
high level, if data is stored in a sorted manner. Sorting is also used to represent data in
more readable formats. Following are some of the examples of sorting in real-life scenarios
−
● Telephone Directory − the telephone directory stores the telephone numbers of
people sorted by their names, so that the names can be searched easily.
● Dictionary − the dictionary stores words in an alphabetical order so that searching
of any word becomes easy.
Increasing Order:
A sequence of values is said to be in increasing order, if the successive element is greater
than the previous one. For example, 1, 3, 4, 6, 8, 9 are in increasing order, as every next
element is greater than the previous element.
Decreasing Order:
A sequence of values is said to be in decreasing order, if the successive element is less than
the current one. For example, 9, 8, 6, 4, 3, 1 are in decreasing order, as every next element
is less than the previous element.
Efficiency parameters:
This sorting method that is to be implemented depends on how it behaves in each situation.
For a given problem, it is important to know which method will be best suited.
Some parameters:
Execution time: it is the time required for the execution of the program.
Space or Memory: it is the amount of space required to store data or variables.
Coding time: it is the time required to develop a sorting technique for the given
problems.
Complexity function f(n):
It is the function which gives the running time of the algorithm in terms of size of the input
data ‘n’.
There are 3 cases for finding the complexity:
Worst case: the maximum number of comparison are made or maximum value of
f(n).
Average case: the average number of comparison are made or average value of f(n)
is determined. 1 0 -2 -3 5 6 -3 -2 0 1 5 6
Best Case: minimum number of comparison are made or minimum value of f(n).
Bubble Sort: In Bubble sort, Each element of the array is compared with its adjacent
element. The algorithm processes the list in passes. A list with n elements requires n-1
passes for sorting. Consider an array A of n elements whose elements are to be sorted by
using Bubble sort. The algorithm processes like following.
age | 2
1. In Pass 1, A[0] is compared with A[1], A[1] is compared with A[2], A[2] is compared
with A[3] and so on. At the end of pass 1, the largest element of the list is placed at
the highest index of the list.
2. In Pass 2, A[0] is compared with A[1], A[1] is compared with A[2] and so on. At the
end of Pass 2 the second largest element of the list is placed at the second highest
index of the list.
3. In pass n-1, A[0] is compared with A[1], A[1] is compared with A[2] and so on. At the
end of this pass. The smallest element of the list is placed at the first index of the list.
Algorithm:
Step 1: Repeat Step 2 For i = 0 to N-1
Step 2: Repeat For J = i + 1 to N - I
Step 3: IF A[J] > A[i]
SWAP A[J] and A[i]
[END OF INNER LOOP]
[END OF OUTER LOOP
Step 4: EXIT
Example:
#include<stdio.h>
void main ()
{
int i, j,temp; 0 1 2 3 4 5 6 7 8 9
int a[10] = { 10, 9, 7, 101, 23, 44, 12, 78, 34, 23};
for(i = 0; i<10; i++) // 10
{
for(j = i+1; j<10; j++) // 9
{
if(a[j] > a[i]) 10>9
{
temp = a[i]; t=10
a[i] = a[j]; 9= a[j]
a[j] = temp; a[j]=10
}
}
} 9 10 7 101 23 44 12 78 34 23
printf("Printing Sorted Element List ...\n");
for(i = 0; i<10; i++)
{
printf("%d\n",a[i]);
}
}
Output:
Printing Sorted Element List . . .
age | 3
7
9
10
12
23
34
44
78
101
Insertion Sort:
Insertion sort is the simple sorting algorithm which is commonly used in the daily lives while
ordering a deck of cards. In this algorithm, we insert each element onto its proper place in
the sorted array. This is less efficient than the other sort algorithms like quick sort, merge
sort, etc.
Technique:
Consider an array A whose elements are to be sorted. Initially, A[0] is the only
element on the sorted set. In pass 1, A[1] is placed at its proper index in the array.
In pass 2, A[2] is placed at its proper index in the array. Likewise, in pass n-1, A[n-1] is
placed at its proper index into the array.
To insert an element A[k] to its proper index, we must compare it with all other
elements i.e. A[k-1], A[k-2], and so on until we find an element A[j] such that,
A[j]<=A[k].
All the elements from A[k-1] to A[j] need to be shifted and A[k] will be moved to
A[j+1].
Algorithm:
Step 1: Repeat Steps 2 to 5 for K = 1 to N-1
Step 2: SET TEMP = ARR[K]
Step 3: SET J = K - 1
Step 4: Repeat while TEMP <=ARR[J]
SET ARR[J + 1] = ARR[J]
SET J = J - 1
[END OF INNER LOOP]
Step 5: SET ARR[J + 1] = TEMP
[END OF LOOP]
Step 6: EXIT
age | 4
Example:
#include<stdio.h>
void main ()
{
int i,j, k,temp;
int a[10] = { 10, 9, 7, 101, 23, 44, 12, 78, 34, 23};
printf("\nprinting sorted elements...\n");
for(k=1; k<10; k++)
{
temp = a[k]; // temp=a[1]
j= k-1; //j=1-1=0
while(j>=0 && temp <= a[j]) //while(0>=0 && 1<=0)//while(0>=0 && a[1]=9 <= a[0]=10)
{
a[j+1] = a[j]; // a[0+1]=a[0]= 10=9
j = j-1; //
}
a[j+1] = temp; a[1]=10
}
for(i=0;i<10;i++) //traverse
{
printf("\n%d\n",a[i]); //values present in a[i]= 7 9 10 12 23 23 34 44 78 101
}
}
Output:
Printing Sorted Elements . . .
7
9
10
12
23
23
34
44
78
101
Selection Sort:
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.
age | 5
First, find the smallest element of the array and place it on the first position. Then, find the
second smallest element of the array and place it on the second position. The process
continues until we get the sorted array.
The array with n elements is sorted by using n-1 pass of selection sort algorithm.
Technique:
In 1st pass, smallest element of the array is to be found along with its index pos.
then, swap A[0] and A[pos]. Thus A[0] is sorted, we now have n -1 elements
which are to be sorted.
In 2nd pas, position pos of the smallest element present in the sub-array A[n-1] is
found. Then, swap, A[1] and A[pos]. Thus A[0] and A[1] are sorted, we now left
with n-2 unsorted elements.
In n-1th pass, position pos of the smaller element between A[n-1] and A[n-2] is to
be found. Then, swap, A[pos] and A[n-1].
Algorithm:
SELECTION SORT(ARR, N)
o Step 1: Repeat Steps 2 and 3 for K = 1 to N-1
o Step 2: CALL SMALLEST(ARR, K, N, POS)
o Step 3: SWAP A[K] with ARR[POS]
[END OF LOOP]
o Step 4: EXIT
SMALLEST (ARR, K, N, POS)
o Step 1: [INITIALIZE] SET SMALL = ARR[K]
o Step 2: [INITIALIZE] SET POS = K
o Step 3: Repeat for J = K+1 to N -1
IF SMALL > ARR[J]
SET SMALL = ARR[J]
SET POS = J
[END OF IF]
[END OF LOOP]
o Step 4: RETURN POS
Example:
Consider the following array with 6 elements. Sort the elements of the array by using
selection sort.
A
10 2 3 90 43 56
=
1 1 2 10 3 90 43 56
2 2 2 3 10 90 43 56
3 2 2 3 10 90 43 56
4 4 2 3 10 43 90 56
5 5 2 3 10 43 56 90
{10, 2, 3, 90, 43, 56}.
Sorted A = {2, 3, 10, 43, 56, 90}
#include<stdio.h>
int smallest(int[],int,int);
void main ()
{
int a[10] = {10, 9, 7, 101, 23, 44, 12, 78, 34, 23};
int i,j,k,pos,temp;
for(i=0;i<10;i++)
{
pos = smallest(a,10,i);
temp = a[i];
a[i]=a[pos];
a[pos] = temp;
}
printf("\nprinting sorted elements...\n");
for(i=0;i<10;i++)
{
printf("%d\n",a[i]);
}
}
int smallest(int a[], int n, int i)
{
int small,pos,j;
small = a[i];
pos = i;
for(j=i+1;j<10;j++)
{
if(a[j]<small) // (10<2)
{
small = a[j];
pos=j;
}
}
age | 7
return pos;
}
Output:
printing sorted elements...
7
9
10
12
23
23
34
44
78
101
Space o(1)
Shell Sort:
Shell sort is the generalization of insertion sort, which overcomes the drawbacks of insertion
sort by comparing elements separated by a gap of several positions.
It is a sorting algorithm that is an extended version of insertion sort. Shell sort has improved
the average time complexity of insertion sort. As similar to insertion sort, it is a
comparison-based and in-place sorting algorithm. Shell sort is efficient for medium-sized
data sets.
Algorithm:
1. ShellSort(a, n) // 'a' is the given array, 'n' is the size of array
2. for (interval = n/2; interval > 0; interval /= 2)
3. for ( i = interval; i < n; i += 1)
4. temp = a[i];
5. for (j = i; j >= interval && a[j - interval] > temp; j -= interval)
6. a[j] = a[j - interval];
7. a[j] = temp;
8. End ShellSort
In the first loop, n is equal to 8 (size of the array), so the elements are lying at the interval of
4 (n/2 = 4). Elements will be compared and swapped if they are not in order.
Here, in the first loop, the element at the 0th position will be compared with the element at
4th position. If the 0th element is greater, it will be swapped with the element at 4th position.
Otherwise, it remains the same. This process will continue for the remaining elements.
At the interval of 4, the sublists are {33, 12}, {31, 17}, {40, 25}, {8, 42}.
33 31 40 8 12 17 25 42: list
List=n/2; 8/2=4;
33 31 40 8: list 1== 33
12 17 25 42: list 2== 12
List[1] > list2[1]:
if(list[1]> list2[1])// (33>12) tru (31>17)true(40>25)true(8>42)false
{
Temp= list1[1];//swapping logic
List1[1]=list[2];
List[2]=temp;
}
33 31 40 8: list 1
12 17 25 42: list 2
12 17 25 8 33 31 40 42: updated list
Now, we have to compare the values in every sub-list. After comparing, we have to swap
them if required in the original array. After comparing and swapping, the updated array will
look as follows -
age | 9
In the second loop, elements are lying at the interval of 2 (n/4 = 2), where n = 8.
Now, we are taking the interval of 2 to sort the rest of the array. With an interval of 2, two
sublists will be generated - {12, 25, 33, 40}, and {17, 8, 31, 42}.
12 17 25 8 33 31 40 42
12>25wrong
17>8 true swapping logix will be implemented
25>33wrong
31>42 wrong
33>40wrong
12 8 25 17 33 31 40 42
Now, we again have to compare the values in every sub-list. After comparing, we have to
swap them if required in the original array. After comparing and swapping, the updated
array will look as follows -
In the third loop, elements are lying at the interval of 1 (n/8 = 1), where n = 8. At last, we use
the interval of value 1 to sort the rest of the array elements. In this step, shell sort uses
insertion sort to sort the array elements.
age | 10
Time Complexity
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 Shell 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 Shell 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 Shell sort is O(n2).
age | 11
Space Complexity
Stable NO
C program Example:
#include <stdio.h>
void print(int a[], int s) {
int i;
for (i = 0; i < s; ++i) {
printf( "%d ", a[i]);
}
}
void shell_Sort(int a[], int s) {
int gap, i;
for (gap = s / 2; gap > 0; gap /= 2) (gap=s/2;gap>0;gap=gap/2)
{
for ( i = gap; i < s; i += 1) //for(i=2;2<8;i=2+1)//fro(i=1;2<8;i=3
{
int temp = a[i];
int j;
for (j = i; j >= gap && a[j - gap] > temp; j -= gap) {
a[j] = a[gap-j];//a[1]=a[4-1]==a[1]=a[3]
}
a[j] = temp;
}
}
}
int main() {
int n,array[] = { 8, 2, 5, 9, 3, 1, 0 };
int size = n/2;
shell_Sort(array, size);//fun calling
printf("The sorted array is : \n");
print(array, size);
}
Divide And Conquer technique can be divided into the following three parts:
age | 12
MergeSort(arr[], l, r)
If r > l
1. Find the middle point to divide the array into two halves:
middle m = l+ (r-l)/2
2. Call mergeSort for first half:
Call mergeSort(arr, l, m)
3. Call mergeSort for second half:
Call mergeSort(arr, m+1, r)
4. Merge the two halves sorted in step 2 and 3:
Call merge(arr, l, m, r)
age | 13
In the above image, we’ve shown the actual subarray in black and the resultant sorted
subarray in blue. Let us understand the detailed steps involved in performing a merge sort in
the above array:
Observe one important point - we need a separate array in order to store the data of the
final merged array. This means that merge sort requires additional space.
o, that’s how merge sort works. Here is an animation that explains the same.
Conquer Phase:
In this phase, divide linked list is sorted by comparing them by one and sorted list is passed
further.
age | 15
Algorithm:
MergeSort(headRef)
1) If head is NULL or there is only one element in the Linked List
then return.
2) Else divide the linked list into two halves.
FrontBackSplit(head, &a, &b); /* a and b are two halves */
3) Sort the two halves a and b.
MergeSort(a);
MergeSort(b);
4) Merge the sorted a and b (using SortedMerge() discussed here)
and update the head pointer using headRef.
*headRef = SortedMerge(a, b);
10 5 1 2 8 9 1 5 7 11 5 6
10/5 1/2 8/ 9 1/5 7/11 5/6
10 5 1 2 8 9 1 5 7 11 5 6
5/10 1/2 8/9 1/5 7/11 /5/6
1 2 5 8 9 10 1 5 5 6 7 11
Combine both:
1 1 2 5 5 5 6 7 8 9 10 11
#include <stdio.h>
#include <stdlib.h>
struct node {
int number;
struct node *next;
};
int main(void)
{
struct node *head;
struct node *current;
struct node *next;
int n,i;
int test[n];
head = NULL;
/* insert some numbers into the linked list */
for(i = 0; i < n; i++)//i=0
age | 17
/* done... */
return 0;
}
if(tnode != NULL) {
tnode->number = number;
tnode->next = next;
}
return tnode;
}
head_one = head;
head_two = head->next;
while((head_two != NULL) && (head_two->next != NULL)) {
head = head->next;
head_two = head->next->next;
}
head_two = head->next;
age | 18
head->next = NULL;
if(head_one == NULL)
return head_two;
if(head_two == NULL)
return head_one;
return head_three;
}
Output:
Enter elements:
Enter 1 element: 5
Enter 2 element: 2
Enter 3 element: 1
Enter 4 element: 4
Enter 5 element: 7
Enter 6 element: 9
Enter 7 element: 0
Before: 5 2 1 4 7 9 0
After: 0 1 2 4 5 7 9
smaller than the specified value, say pivot, based on which the partition is made and
another array holds values greater than the pivot value.
Quicksort partitions an array and then calls itself recursively twice to sort the two resulting
subarrays. This algorithm is quite efficient for large-sized data sets as its average and
worst-case complexity are O(n2), respectively.
Partition in Quick Sort:
Following animated representation explains how to find the pivot value in an array.
#include <stdio.h>
// function to swap elements
void swap(int *a, int *b) {
int t = *a;
*a = *b;
*b = t;
}
// function to find the partition position
int partition(int array[], int low, int high) {
// select the rightmost element as pivot
int pivot = array[high];
// pointer for greater element
int i = (low - 1);
// traverse each element of the array
// compare them with the pivot
for (int j = low; j < high; j++) {
if (array[j] <= pivot) {
// if element smaller than pivot is found
// swap it with the greater element pointed by i
i++;
age | 21
// main function
int main() {
int data[] = {8, 7, 2, 1, 0, 9, 6};
printf("Unsorted Array\n");
printArray(data, n);
Quicksort Complexity:
Time Complexity:
Best: O(n*log n)
Worst: O(n2)
Average: O(n*log n)
Space Complexity: O(log n)
Stability: No
1. Time Complexities
Worst Case Complexity [Big-O]: O(n2)
It occurs when the pivot element picked is either the greatest or the smallest element.
This condition leads to the case in which the pivot element lies in an extreme end of the
sorted array. One sub-array is always empty and another sub-array contains n - 1 elements.
Thus, quicksort is called only on this sub-array.
However, the quicksort algorithm has better performance for scattered pivots.
2. Space Complexity
The space complexity for quicksort is O(log n).
Searching is an operation or a technique that helps finds the place of a given element or
value in the list. Any search is said to be successful or unsuccessful depending upon whether
the element that is being searched is found or not.
Some of the standard searching technique that is being followed in the data structure is
listed below:
Linear Search or Sequential Search
a. Iterative Method
b. Recursive method
Binary Search
a. Iterative Method
b. Recursive method
Linear Search:
● Linear Search is the simplest searching algorithm.
● It traverses the array sequentially to locate the required element.
● It searches for an element by comparing it with each element of the array one by one.
● So, it is also called as Sequential Search.
age | 23
As against this, searching in case of unsorted list also begins from the 0th element and
continues until the element or the end of the list is reached.
The list given below is the list of elements in an unsorted array. The array contains ten
elements. Suppose the element to be searched is '46', so 46 is compared with all the
elements starting from the 0th element, and the searching process ends where 46 is found,
or the list ends.
The performance of the linear search can be measured by counting the comparisons done to
find out an element. The number of comparison is 0(n).
Algorithm:
Linear Search ( Array A, Value x)
Step 1: Set i to 1
Step 2: if i > n then go to step 7
Step 3: if A[i] = x then go to step 6
Step 4: Set i to i + 1
Step 5: Go to Step 2
Step 6: Print Element x Found at index i and go to step 8
Step 7: Print element not found
Step 8: Exit
Example:
#include <stdio.h>
int main()
{
int array[100], search, c, n;
printf("Enter number of elements in array\n");
scanf("%d", &n);
printf("Enter %d integer(s)\n", n);
for (c = 0; c < n; c++)
scanf("%d", &array[c]);
printf("Enter a number to search\n");
scanf("%d", &search);
for (c = 0; c < n; c++)
{
if (array[c] == search) /* If required element is found */
{
printf("%d is present at location %d.\n", search, c+1);
age | 24
break;
}
}
if (c == n)
printf("%d isn't present in the array.\n", search);
return 0;
}
Output:
Enter number of elements in array
5
Enter 5 integer(s)
2
5
6
9
4
Enter a number to search
4
4 is present at location 5.
Worst Case:
In the worst possible case,
● The element being searched may be present at the last position or not present in the
array at all.
● In the former case, the search terminates in success with n comparisons.
● In the later case, the search terminates in failure with n comparisons.
● Thus in worst case, linear search algorithm takes O(n) operations.
Binary Search:
Binary search is the search technique which works efficiently on the sorted lists. Hence, in
order to search an element into some list by using binary search technique, we must ensure
that the list is sorted.
Binary search follows 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 middle element is returned otherwise, we search into either of the
halves depending upon the result produced through the match.
age | 25
Algorithm:
BINARY_SEARCH (A, lower_bound, upper_bound, VAL)
o Step 1: [INITIALIZE] SET BEG = lower_bound
END = upper_bound, POS = - 1
o Step 2: Repeat Steps 3 and 4 while BEG <=END
o Step 3: SET MID = (BEG + END)/2
o Step 4: IF A[MID] = VAL
SET POS = MID
PRINT POS
Go to Step 6
ELSE IF A[MID] > VAL
SET END = MID - 1
ELSE
SET BEG = MID + 1
[END OF IF]
[END OF LOOP]
o Step 5: IF POS = -1
PRINT "VALUE IS NOT PRESENT IN THE ARRAY"
[END OF IF]
o Step 6: EXIT
Complexity:
SN Performance Complexity
Example:
#include<stdio.h>
int binarySearch(int[], int, int, int);
void main ()
{
int arr[10] = {16, 19, 20, 23, 45, 56, 78, 90, 96, 100};
int item, location=-1;
printf("Enter the item which you want to search ");
scanf("%d",&item);
location = binarySearch(arr, 0, 9, item);
age | 26
if(location != -1)
{
printf("Item found at location %d",location);
}
else
{
printf("Item not found");
}
}
int binarySearch(int a[], int beg, int end, int item)
{
int mid;
if(end >= beg)
{
mid = (beg + end)/2;
if(a[mid] == item)
{
return mid+1;
}
else if(a[mid] < item)
{
return binarySearch(a,mid+1,end,item);
}
else
{
return binarySearch(a,beg,mid-1,item);
}
}
return -1;
}
Output:
Enter the item which you want to search
19
Item found at location 2
BASIS FOR
LINEAR SEARCH BINARY SEARCH
COMPARISON
Worst case for N N comparisons are Can conclude after only log2N
number of elements required comparisons
Insert operation Easily inserted at the end Require processing to insert at its
of list proper place to maintain a sorted
list.