You are on page 1of 20

1

Sorting and Searching

6.2 Search Algorithms (Linear and Binary)


Searching is a process of identifying a particular item or a record among a set of items or
records. If the item is found then search is said to be successful; otherwise unsuccessful. A
general searching algorithm accepts two arguments – the target ‘item’ and the list to be
searched. The searching algorithm will indicate whether it has found ‘item’ or not.

Searching – a process of finding an item from a set of numbers or a list

6.2.1 Sequential (Linear) Searching

In sequential searching, a given ‘item’ is found in the list (array) by examining its elements
one by one. Initially the process starts with comparing the ‘item’ with the first element. If both
do not match then it proceeds to the next element. This process continues until either the
desired item is found or the list is exhausted.

Sequential Searching – a process of finding an item from a set of items in linear


way, i.e. one by one

Let us assume that ‘A’ is an array of 10 elements (A[0], A[1], through A[9]), as shown in
figure 6.1(a), and let we want to find the item ‘16’. The sequential searching works as:

1. The first element of the list A[0] is compared with 16. Since A[0] is not equal to 16,
the next element A[1] is taken (as shown in figure-6.1(b))
2. A[1] is compared with 16. Again A[1] is not equal to 16, therefore the next element,
A[2] is taken (as shown in figure-6.1(c))
3. A[2] is compared with 16. Again A[2] is not equal to 16, therefore the next element,
A[3] is taken (as shown in figure-6.1(c))
4. This process goes on until the item is found or the entire list is searched.

Figure-6.1 shows that the item is found at 5th location.

A[0] 48 A[0] 48  Item=16 A[0] 48


A[1] 33 A[1] 33 A[1] 33  Item=16
A[2] 20 A[2] 20 A[2] 20
A[3] 98 A[3] 98 A[3] 98
A[4] 16 A[4] 16 A[4] 16
A[5] 75 A[5] 75 A[5] 75
A[6] 40 A[6] 40 A[6] 40
A[7] 61 A[7] 61 A[7] 61
A[8] 55 A[8] 55 A[8] 55
A[9] 79 A[9] 79 A[9] 79

(a) (b) First Pass (c) Second Pass


2
A[0] 48 A[0] 48 A[0] 48
A[1] 33  Item=16 A[1] 33 A[1] 33
A[2] 20 A[2] 20 A[2] 20
A[3] 98 A[3] 98  Item=16 A[3] 98
A[4] 16 A[4] 16 A[4] 16  Item=16

A[5] 75 A[5] 75 A[5] 75


A[6] 40 A[6] 40 A[6] 40
A[7] 61 A[7] 61 A[7] 61
A[8] 55 A[8] 55 A[8] 55
A[9] 79 A[9] 79 A[9] 79

(d) Third Pass (e) Fourth Pass (f) Fifth Pass

Figure-6.1- Sequential (Linear) Searching

Algorithm : SequentialSearch

SequentialSearch(A, N, Item)
Here A is an array of ‘N’ number of elements and ‘Item’ represents the
item to be searched in array ‘A’

1. Set Flag = 0
2. Initialize I = 0
3. Repeat through Step-4 while (I < N)
4. Compare A[I] and Item
If (A[I] = = Item) Then set Flag = 1 and go to Step-6
Otherwise Increment ‘I’ as: I = I +1
5. Check Flag.
If Flag = 1 Then Display – “Item found”;
Otherwise Display – “Item not found”;
6. Exit

The C implementation of this sequential search algorithm is as:

Implementation : SequentialSearch

SequentialSearch(int a[], int n, int item)


{
int i, flag;
flag = 0;
i = 0;
while (i < n)
{
if (a[i] == item)
{
flag = 1;
break;
}
else
i++;
}
if (flag == 1)
printf(“\nItem is found”);
else
printf(“\nItem is not found”);
}
3
Analysis - In linear search the number of comparisons required for a successful search is
not fixed. It all depends upon the position of desired item within the array. The target ‘item’
will be the first element in the array, the last or some where between. If it is the first element
then only one comparison is sufficient and if it is the last element then ‘n’ comparison are
required, where ‘n’ is the length of the list. If the search is unsuccessful then ‘n’ number of
comparisons is required. Thus best case has 1 comparison and the worst case has ‘n’
comparison. And in average case it is n/2 comparisons.

6.2.2 Binary Searching

The limitation of sequential search technique is that we have to search the entire list even
when the item is not in the list. This problem is solved by an efficient technique called binary
searching. The condition for binary search is that all the data should be in sorted order.

In binary search, we first compare the key with the item in the middle position of the sorted
array. If there's a match, we can return immediately. If the key is less than the middle key,
then the item sought must lie in the lower half of the array; if it's greater then the item sought
must lie in the upper half of the array. So we repeat the procedure on the lower (or upper)
half of the array.

Binary Searching – a process of finding an item from a sorted array using divide
and conquer method.

For this we take three variables – Start, End and Middle, which will keep track of the start,
end and middle value of the portion of the array. The value of middle will be as:

Middle = (Start + End) / 2

The binary search works as:

(i) If (Item == A[Middle] Then Display – Item is found”


(ii) if (Item < A[Middle]) Then the ‘Item’ may be in the first (upper) portion of the array
(iii) if (Item > A[Middle) Then the ‘Item’ may be in the second (lower) portion of the array

Thus in the length of the list to be searched is reduced by half. And this process continues
until we find the element or middle element has no left or right portion to search.

Let we have a list of numbers as shown in figure 6.2(a) and let we want to find item 62. For
this we use two integer variables – Start and End. Initially Start = 0, End = 9 and Middle = 5.
The binary searching works as:

(i) The middle element A[5] is compared with ‘62’, as shown in figure 6.2(b). Since A[5]
is less than item ‘62’, therefore the upper portion of the list is ignored
(ii) For lower portion, Start is set to 6 (i.e. Middle + 1) and End remains same (i.e. 9).
With these new values of Start and End, the new Middle value (i.e. 8)
(iii) Now A[8] is compared with ‘62’. Since A[8] is greater than 62, therefore lower portion
of this subdivided list is ignored.

And this process goes on until the item is found or there is no upper or lower portion to
search. Figure-6.2 shows that the item is found at 6th location.
4
A[0] 21 A[0] 21 A[0] 21
A[1] 33 A[1] 33 A[1] 33
A[2] 39 A[2] 39 A[2] 39
A[3] 46 A[3] 46 A[3] 46
A[4] 55 A[4] 55 A[4] 55
A[5] 60 A[5] 60  Item=62 A[5] 60
A[6] 62 A[6] 62 A[6] 62
A[7] 73 A[7] 73 A[7] 73
A[8] 81 A[8] 81 A[8] 81  Item=62
A[9] 89 A[9] 89 A[9] 89
(a) (b) First Pass (c) Second Pass
Start = 0, End = 9 Start = 6, End = 9
Middle = 5 Mid = 8

A[0] 21 A[0] 21
A[1] 33 A[1] 33
A[2] 39 A[2] 39
A[3] 46 A[3] 46
A[4] 55 A[4] 55
A[5] 60 A[5] 60
A[6] 62 A[6] 62  Item=62
A[7] 73  Item=62 A[7] 73
A[8] 81 A[8] 81
A[9] 89 A[9] 89
(c) Third Pass (c) Fourth Pass
Start = 6, End = 8 Start = 6, End = 6
Middle = 7 Middle = 6

Figure 6.2 Binary Searching

Algorithm : BinarySearch

BinarySearch(A, N, Item)

Here ‘A’ is an array of ‘N’ number of elements and ‘Item’ represents the
item to be searched in array ‘A’

1. Set Flag = 0
2. Set Start = 0 and End = N-1
3. Repeat through Step-5 While (Start <= End)
4. Calculate Middle as: Middle = (Start + End) / 2
5. Compare A[Middle] and Item
If (A[Middle] == Item) then set Flag = 1 and go to step-6
if (A[Middle] > Item ) then update as End = Middle -1
Else update Start as Start = Middle +1
6. Check Flag.
If Flag = 1 Then Display – “Item found”;
Otherwise Then Display – “Item not found”;
7. Exit

The C implementation of this Binary search algorithm is as:


5
Implementation : BinarySearch

BinarySearch(int a[], int n, int item)


{
int mid, start, end, flag;
flag = 0;
start = 0;
end = n-1;
while (start <= end)
{
mid = (start + end)/2;
if (a[mid] == item)
{
flag = 1;
break;
}
else if (a[mid] > item)
end = mid-1;
else
start = mid+1;
}
if (flag == 1)
printf(“\nItem is found”);
else
printf(“\nItem is not found”);
}

Analysis – In binary searching, after each comparison either the search terminates
successfully or the size of the array is reduced about one half of the original size. It means
that each comparison reduces the number of possible comparisons by a factor of 2. Thus
after ‘k’ key comparison, the array remaining is of size at most n/2k. And in worst case, the
expected number of comparison require O(log 2n) to search the desired ‘item’, even if the
search is unsuccessful.

6.3 Concept of Sorting and Sorting Algorithms


Sorting is an important operation. Sorting is formally defined a list of elements A1, A2, A3,…,
An if there is binary relation ‘<’ defined for any two distinct elements Ai and Aj of that list, that
is either Ai = Aj or Ai < Aj or Ai > Aj. There are large numbers of sorting methods.

Sorting – a process of arranging a set of numbers in either ascending order or in


descending order

6.3.1 Bubble Sort


Bubble sort is probably the most widely known sorting technique for the beginners. It is very
easy to understand and program. The basic idea underlying the bubble sort is to compare
the adjacent elements and moves the largest element to the bottom of the list.

Bubble Sorting – a sorting technique in which two adjacent elements are


compared and their values are interchanged if 1st number is greater than 2nd number

Let we have an array of 6 numbers:


6
A[0] 29
A[1] 36
A[2] 11
A[3] 24
A[4] 55
A[5] 22

The Bubble sort works as:

(i) In first pass A[0] is compared with A[1]. If A[0] > A[1], their values are interchanged
(ii) After this A[1] is compared with A[2]. If A[1] > A[2], their values are interchanged
(iii) Next A[2] is compared with A[3]. If A[2] > A[3], their values are interchanged
(iv) And this process continues until we compare A[4] with A[5].

Algorithm: BubbleSort

BubbleSort(A, N)
Here ‘A’ is an array of elements and ‘N’ represents the number of
elements in the array ‘A’.

1. Set Flag=1
2. Initialize I = 0
3. Repeat through Step-9 While (I < N) and Flag=1
4. Reset Flag = 0
5. Initialize J = 0
6. Repeat through Step-8 While (J < N-I-1)
7. Compare A[J] and A[J+1].
If (A[J] > A[J+1]) then set the Flag = 1 and
interchange A[J] and A[J+1]
8. Increment ‘J’ as J = J+1
9. Increment ‘I’ as I = I+1
10. Exit

The C implementation of this bubble sort algorithm is as:

Implementation : BubbleSort

BubbleSort(int a[], int n)


{
int i, j, t, flag;
flag=1;
for(i=0; i<n && flag == 1; i++)
{
flag=0;
for(j=0; j<n-i-1; j++)
{
if (a[j] > a[j+1])
{
flag = 1;
t = a[j]; /* Interchange a[j] and a[j+1] */
a[j] = a[j+1];
a[j+1] = t;
}
}
}
}
7
Analysis – In Bubble sorting, (n-1) comparisons will be done in 1st pass, (n-2) in 2nd pass,
(n-3) in 3rd pass, and so on. So it is very simple to find the total number of comparison. Thus
the total number of comparisons is n*(n-1)/2, which is O(n2). In the best case, that is when
the array is already sorted, only one pass is required. In worst case, when the given array is
sorted in the reverse order, we need all the passes to be performed, thus the total number of
comparisons is O(n2). Similarly the average number of iteration is O(n 2).

6.4.2 Selection Sort


A selection sort is a sorting technique that is typically used for sequencing small lists. It
starts by comparing the entire list for the lowest item and moves it to the #1 position. It then
compares the rest of the list for the next-lowest item and places it in the #2 position and so
on until all items are in the required order. Selection sorts perform numerous comparisons,
but fewer data movements than other methods.

Selection Sorting – a sorting technique that starts by finding the minimum value
in the array and moving it to the first position and this step is then repeated for the
second lowest value, then the third, and so on until the array is sorted.

A selection sort starts from the first element and it is compared with all the remaining
elements of the list one by one and finds the smallest element. Next, the second element is
taken and searches for the second smallest element. This process continues until the
complete list is sorted. Let we have an array of 6 numbers:

A[0] 29
A[1] 36
A[2] 11
A[3] 24
A[4] 55
A[5] 22

In first pass, the following steps take place:

(i) A[0] is compared with A[1]. If A[0] > A[1] then interchange them.
(ii) After this A[0] is compared with A[2]. If A[0] > A[2] then interchange them.
(iii) A[0] is compared with A[3]. If A[0] > A[3] then interchange them.
(iv) And this process continues until we compare A[0] with A[5].

Thus the following comparisons are made on the first pass:

A[0] 29 A[0] 29 A[0] 11 A[0] 11 A[0] 11


A[1] 36 A[1] 36 A[1] 36 A[1] 36 A[1] 36
A[2] 11 A[2] 11 A[2] 29 A[2] 29 A[2] 29
A[3] 24 A[3] 24 A[3] 24 A[3] 24 A[3] 24
A[4] 55 A[4] 55 A[4] 55 A[4] 55 A[4] 55
A[5] 22 A[5] 22 A[5] 22 A[5] 22 A[5] 22

(a) (b) (c) (d) (e)


8
Figure 6.4 : Execution of 1st Pass

From this pass it is clear that the smallest element is placed in the proper position within the
array. Similarly in second pass, it places the second smallest element in its proper position.
Figure-6.5 illustrates the complete operations performed on this above array.

Algorithm : SelectionSort

SelectionSort(A, N)
Here ‘A’ is an array of elements and ‘N’ represents the number of
elements in the array ‘A’.

1. Initialize I = 0
2. Repeat through Step-7 while (I < N-1)
3. Set J = I+1
4. Repeat through Step-6 while (J < N)
5. Compare A[I] and A[J].
If (A[I] > A[J]) then interchange A[I] and A[J]
6. Increment ‘J’ as J = J+1
7. Increment ‘I’ as I = I+1
8. Exit

Analysis – In Selection sorting, there are N-1 passes and for each pass there are N-I
comparisons. The first pass makes (n-1) comparisons; the second pass makes (n-2)
comparisons and so on. Therefore the total number of maximum comparisons required to
sort an array of ‘n’ elements by this method is n*(n-1)/2. We can say that the total number of
comparisons is O(n2).

6.4.3 Insertion Sort


Insertion sort is an elementary sorting algorithm that sorts one element at a time. Most
humans, when sorting a deck of cards, will use a strategy similar to insertion sort. The
algorithm takes an element from the list and places it in the correct location in the list. This
process is repeated until there are no more unsorted items in the list.

Insertion Sorting – a sorting technique which moves elements one at a time into
the correct position, i.e. one element at a time into the previously sorted part of the
array, moving higher ranked elements down as necessary

Suppose ‘A’ is an array of ‘N’ numbers. The insertion sort techniques scans the array from
A[0] to A[n-1], inserting each element into its proper position in the previously sorted
subarray A[0], A[1], A[2], …., A[I-1].

In other words, the insertion sort is carried out with the help of following sequences:

(i) Since A[0] is the very first element, therefore it is already sorted.
(ii) A[1] is inserted before or after A[0] in such a way that A[0] and A[1] is sorted.
(iii) Same way A[2] is inserted in such a way that A[0], A[1] and A[2] is sorted.
(iv) This process continues until A[0], A[1], A[2], …., A[n-1] becomes sorted.
9
Algorithm – InsertionSort

InsertionSort(A, N)
Here ‘A’ is an array of elements and ‘N’ represents the number of
elements in the array ‘A’.

1. Initialize J =1
2. Repeat through Step-8 while (J < N)
3. Set Item = A[J]
4. Set I = J-1
5. Repeat through step-7 while (I >= 0 && Item < A[I])
6. A[I+1] = A[I];
7. Increment ‘I’ as I = I - 1
8. Increment ‘J’ as J = J + 1
9. Exit

The C implementation of this insertion sort algorithm is as:

Implementation : InsertionSort

InsertionSort(int a[], int n)


{
int i, j, item;

for(j = 1; j < n; j++)


{
item = a[j];
for(i = j-1; i >= 0 && item < a[i] ; i--)
a[i+1] = a[i];
a[i+1] = item;
}
}

Analysis - The best case for insertion sort occurs when the list is already sorted. In such
case the insertion sort will make (n-1) comparison of keys. So we can say that the sort is
O(n) in the best case. On the other hand, in worst case, when the list is initially sorted in the
reverse order, the sort is O(n 2). Similarly in the average case, the insertion sort is O(n2).

6.4.4 Merge Sort

Merge sort is a sorting algorithm that sorts data items into ascending or descending order,
which comes under the category of comparison-based sorting. Here we apply the divide-
and-conquer strategy to sort a given sequence of data items, which can be described as
follows:

1. Recursively split the sequence into two halves (i.e. subsequences) until the subsequence
contains only a single data item (i.e. singleton subsequence)
2. Now, recursively merge these subsequences back together preserving their required
order (i.e. ascending or descending order)

Merge Sorting – a sorting technique that sequences data by continuously merging


items in the list. Every single item in the original unordered list is merged with
another, creating groups of two. Every two-item group is merged, creating groups of
four and so on until there is one ordered list
10
In merge sorting, an unsorted array A[Lower : Upper] is split around its middle element,
Mid such that Mid = (Lower + Upper)/2, into two unsorted arrays A[Lower : Mid] and A[Mid+1
: Upper]. The same procedure is applied recursively on two unsorted arrays A[Lower : Mid]
and A[Mid+1 : Upper] and finally when there are only one element left in the array, they are
merged.

Let we have following list of numbers:

(29 36 61 24 55 22 67 42)

The merge sort works as:

(i) Initially lower = 1, upper = 8 and the value of mid is 4. Thus the above array is split
into two sub-lists, as shown below:

(29 36 61 24) (55 22 67 42)

(ii) Take the first sublist and apply the same procedure again:

((29 36) (61 24)) (55 22 67 42)

(iii) Once again the list (29 36) is divided into two sublists ((29) (36)).

(iv) Now the list is not further subdivided and they are individually sorted, therefore these
two sublists (29) and (36) are merged into one. On merging the resultant list becomes
(29, 36).

(v) So the sorting on sublist (29 36) is over. Next we take (61 24).

(vi) To do the same so we subdivide it into two sublists ((61) (24)). These sublists are
already sorted because they contain only one element, therefore they are merged to
form (24 61).

(vii) Now the task is to merge these two sublists (29 36) and (24 61) and to form a new
list (24 29 36 61). This completes the first task of sorting the original sublist.

(viii) Now the same procedure is applied to second original sublist (55 22 67 42).
This sublist becomes (22 42 55 67). Now the merging operation is applied on
these two original sublists (24 29 36 61) and (22 42 55 67) to form a new list (22
24 29 36 42 55 61 67).

Here is the Merge Sort Algorithm.

Algorithm : MergeSort

MergeSort(A, Lower, Upper)


Here ‘A’ is an array of Lower as lower limit and Upper as upper limit.

Perform the following steps if Upper > Lower


1. Calculate Mid = (Lower + Upper)/2
2. Call MergeSort(A, Lower, Mid)
3. Call MergeSort(A, Mid+1, Upper)
4. Call Merge(A, Lower, Mid, Mid+1, Upper)
5. Exit

This algorithm calls another algorithm Merge() whose task is to merge two sublists A[Lower
: Mid] and A[Mid+1 : Upper] into one new sorted list. The Merge() algorithm maintains two
counter variables ‘I’ and ‘J’ to mark the beginning of two arrays. The Merge() algorithm
works as:
11

(i) The elements A[I] and A[J] are compared.


(ii) If A[I] < A[J] then T[K] = A[I] and the value of ‘I’ and ‘K’ is incremented;
otherwise T[K] = A[J] and the value of ‘J’ and ‘K’ is incremented
(iii) The first two steps are repeated until either the first or the second array is exhausted.
(iv) And then the remaining elements of either array is copied into temporary array T[ ].
(v) Finally we copy back all the elements of temporary array T[ ] into original array A[ ].

Here is the Merge Algorithm.

Algorithm : Merge

Merge(A, Lower1, Upper1, Lower2, Upper2)


Here ‘A’ is an array. Lower1 and Lower2 are the lower limits and
Upeer1 and Upper2are the upper limits of two sublists respectively.

1. Consider an array T[50] to hold the merging of two sorted sublists -


A[Lower1 : Upper1] and A[Lower2 : Upper2]. Here size 50 is taken
arbitrarily, you can take any number such that it can hold
elements of both lists.
2. Set I = Lower1 and J = Lower2
3. Set K =0
4. Repeat through step-6 while (I <= Upper1) and (J <= Upper2)
5. If A[I] < A[J] then T[K] = A[I] and Increment ‘I’ as: I = I+1
Else if A[I] > A[J] then T[K] = A[J] and Increment ‘J’ as: J = J + 1
Else assign T[K] = A[I] and Increment the value of ‘I’ and ‘J’ as:
I = I+1 and J = J+1
6. Increment ‘K’ as K = K+1
7. Repeat through step-8 while (I <= Upper1)
8. Assign T[K] = A[I] and Increment the value of ‘I’ and ‘K’ as:
I = I+1 and K = K+1
9. Repeat through step-10 while (J <= Upper2)
10. Assign T[K] = A[J] and Increment the value of ‘J’ and ‘K’ as:
J = J+1 and K = K+1 respectively
11. Copy all elements of array T[ ] back to original array A[ ].
12. Initialize I = Lower1 and J = Lower2
13. Initialize K = 0
14. Repeat through step-15 while (I <= Upper1)
15. Assign A[I] = T[I] and Increment the value of ‘I’ and ‘K’ as:
I = I+1 and K = K+1
16. Repeat through step-17 while (J <= Upper2)
17. Assign A[J] = T[K] and Increment the value of ‘J’ and ‘K’ as
J = J+1 and K = K+1 respectively
18. Exit

6.4.5Quick Sort
Quick sorting is a natural example of recursion sorting technique developed by C.A.B. Hoare
in 1962. Quick Sort is a sorting algorithm that sorts data items into ascending or descending
order, which comes under the category of comparison-based sorting. This algorithm works
as follows:

1. Reorder by splitting the sequence into left and right halves with a pivot data item in
between. Here, pivot data item is identified by comparison i.e. a data item must be greater
than or equal to every data item in the left half and less than or equal to every data item in
the right half.
2. Now, recursively sort the two half's separately.

Quick Sorting – a sorting algorithm that picks an element from the list, and
reorder the list so that all elements which are less than the chosen element come
before the chosen element
12

In Quick sorting, let A[First : Last] be an array to be sorted. Here we will assume two counter
variables ‘I’ and ‘J’ as: I = First+1 and J = Last. The variable ‘I’ moves towards left for
searching for an element, which is greater than A[First] and the counter variable ‘J’ moves
towards left for an element, which is smaller than A[First]. This process ends whenever the
counter variable ‘I’ and “J” meet or cross over. Consider an array of 12 elements as shown
below:

0 1 2 3 4 5 6 7 8 9 10 11
22 29 11 18 34 7 14 46 35 8 56 26

List of 12 numbers

The Quick sorts works as:

(i) Here I = 1, J = 11and the first element A[First] is 22. In this we use two counter
variables ‘I’ and ‘J’ which are set I = 1 and J = 11

0 1 2 3 4 5 6 7 8 9 10 11
22 29 11 18 34 7 14 46 35 8 56 26

First I J
element

(ii) Now we move ‘I’ towards right until A[I] > 22. Since A[I] > 22, therefore ‘I’ does not
move further to the right and stops immediately. Now we move ‘J’ towards left until
A[J] < 22. Here ‘J moves 2 units to the left and the scene may be as shown below:

0 1 2 3 4 5 6 7 8 9 10 11
22 29 11 18 34 7 14 46 35 8 56 26

First I J
element

(iii) At this point, we exchange A[I] and A[J] as shown below:

0 1 2 3 4 5 6 7 8 9 10 11
22 8 11 18 34 7 14 46 35 29 56 26

First I J
element

(iv) The movement of ‘I’ and ‘J’ resume until A[I] > 22 and A[J] < 22 are found . Now ‘I’
moves 3 units to the right and ‘J’ moves 3 units to left as shown below:

0 1 2 3 4 5 6 7 8 9 10 11
22 8 11 18 34 7 14 46 35 29 56 26

I J
13

First
element

(v) Once again A[I] and A[J] are exchanged as shown below:

0 1 2 3 4 5 6 7 8 9 10 11
22 8 11 18 14 7 34 46 35 29 56 26

First I J
element

(vi) The movement of ‘I’ and ‘J’ resume until A[I] > 22 and A[J] < 22 are found. Now ‘I’
moves 2 units to the right and ‘J’ moves 1 unit to the left as shown below:

0 1 2 3 4 5 6 7 8 9 10 11
22 8 11 18 14 7 34 46 35 29 56 26

First J I
element

(vii) Since the index of ‘I’ becomes greater than ‘J’, the process ends after exchanging
A[J] and A[First]. The resultant array looks like the following:

0 1 2 3 4 5 6 7 8 9 10 11
7 8 11 18 14 22 34 46 35 29 56 26

Now the element 22 is placed at index ‘5’. All elements of array A[ ], which are left to ‘5’ are
less than 22 and all elements which are right to ‘5’ are greater than 22. Thus the element 22
is placed correctly. Now the above procedure is applied on these two subarrays A[First : J-
1] and A[J+1 : Last].

Here is the quick sort algorithm.

Algorithm : QuickSort

QuickSort(A, First, Last)


Here ‘A’ is an array of elements and ‘First’ and ‘Last’ represent the first
index and last index of the array ‘A’.

Perform the following steps only if (I < J)


1. Set I = First+1;
2. Set J = Last
3. Repeat through step-8 while (I < J)
4. Repeat through step-5 while (A[I] < A[First])
5. Increment the value of ‘I’ as I = I+1
6. Repeat through step-7 while (A[J] > A[First])
7. Decrement the value of ‘J’ as J = J - 1
8. If (I < J) then exchange the value of A[I] and A[J]
9. Exchange the value of A[First] and A[J]
10. Call QuickSort (A, First, J-1);
11. Call QuickSort (A, J+1, Last);
12. Exit
14
The C implementation of this Quick sort algorithm is as:

Implementation : QuickSort

QuickSort (int a [],int first, int last)


{
int i, j, temp;
if (first < last)
{
i = first;
j = last+1;

do
{
do
{
i++;
}
while (a[i] < a[first] ) ;
do
{
j--;
}
while (a[j] > a[first]) ;

if (i < j)
{
temp = a[i];
a[i] = a[j] ;
a[j] = temp;
}
} while (i < j) ;
temp =a[first];
a[first] = a[j];
a[j]=temp;
QuickSort (a, first, j-1);
QuickSort (a, j+1, last);
}
}

Analysis – In quick sorting, the worst case behavior is O(n2). However each time an
element is correctly positioned in the middle of the array such that the subarray to its left will
be of the same size as that of its right. So if an array has size ‘n’, then it is split into two
subarrays each of size n/2 approximately, thus having approximately n/2 comparisons. And
this process goes on until there are ‘n’ subarrays of size ‘1’. Thus the total number of
comparison for the entire list is

n+2*(n/2)+4*(n/4)+….+n*(n/n) or (n+n+n+…..n)

It has been shown that the average computing time for this sort is O(n*log 2n). And as far as
the average complexity time is concerned, the quick sort is the best of internal sorting
methods we shall be studying.
15
6.4.7 Heaps and Heap Sorting

Before studying heap sorting, we must know what a heap is and how it is created?

Heap
A heap is defined to a complete binary tree ‘H’ such that each node of ‘H’ has the following
property – the value at any node, say ‘i’ is greater than or equal to the value of any of its
descendants. Such a heap is called as maxheap. Opposite to it, if the value at any node, say
‘i’ is less than or equal to the value of any of its descendants then it is called as minheap.

Heap – a balanced, left-justified binary tree in which no node has a value greater than
the value in its parent

For example, let we have a complete tree as shown in figure-6.10


91
28

82 65
43 59

74 43 28 59
74 82 65 91

Max-heap Min-heap

Figure 6.10 Heaps

In an array representation of a binary tree the left and right children of node A[I] are at A[2.I]
and A[2I+1] respectively. Alternatively the parent of any node A[J] is at A[J/2]. Note that the
nodes of a heap H on the same level appears one after the other in the array A[]. Here is the
sequential representation of above maxheap by the array a[].

Index 1 2 3 4 5 6 7
Value 91 82 65 74 43 28 59

Now we will study various operations that can be operated on heaps.

Inserting into a Heap


When a new element ‘item’ is inserted into the heap, two steps are followed:

(i) In first step, ‘item’ is inserted at the end of ‘H’ so that ‘H’ is still a complete binary tree
but not necessarily a heap.
(ii) And in second step, ‘item’ is placed at its appropriate place in the heap so that the ‘H’
is finally a heap.
Let us understand this procedure by using the heap as shown in figure-6.11

91

82 65

74 43 28 59

Figure 6.11
16

Let we want to insert a new item ‘89’. Initially it is placed in the last to make it a complete
tree, that is we set a[8]=89. Figure 6.12(a) shows that 89 is the left child of a[4]. Now the
item 85 is compared with its parent at a[4], that is 74. Since 89 is greater than 74, so we will
interchange them. The new complete tree is as shown in figure-6.12(b). Now the item 89 is
again compared with its parent 82. Since 89 is greater than 82, so we will interchange them.
The new complete tree is as shown in figure-6.12 (c). Now again 89 is compared with its
parent 90. Since 89 is not greater than 90, so item=89 has now placed its appropriate place
in it. The new complete tree is as shown in figure-6.12 (d).

Finally we get a heap as a final tree.

91 91

82 65 82 65

74 43 28 59 89 43 28 59

89 74

(a) (b)

91 91

82 65 89 64

89 43 28 59 82 43 28 59

74 74

(c) (d)

Figure 6.12
Here is this insertion algorithm.

Algorithm: InsertHeap

InsertHeap(A, N, Item)
Here ‘A’ is an array of ‘N’ number of elements and ‘Item’ represents the
item to be inserted into a heap

1. Set I = N;
2. Repeat through step-7 while (I > 1)
3. Assign Parent = I/2
4. Compare item with A[Parent]
5. If (Item <= A[Parent]) then A[I] = Item and go to step-7;
otherwise A[I] = A[Parent] and I = Parent;
6. Set A[1] = Item;
7. Exit
17
Here is the C implementation of this insertion algorithm.

Implementation : InsertHeap

InsertHeap(int a[], int n, int item)


{
int i, parent;
n++;
i=n;
while (i>1)
{
parent = i/2; /* location of parent node */
if (item <= a[parent])
{
a[i] = item;
return;
}
else
{
a[i] = a[parent];
i = parent;
}
}
a[1] = item; /* assign item as the root node of the heap */
}

Deleting the Root of the Heap

Whenever a deletion operation is made on a Heap, it is always the root node which is to be
deleted. Let H is a heap with ‘n’ elements. When we delete the root node of a heap we divide
the process into three steps:

(i) In first step we assign the root node R to some variable, say Item.
(ii) In second step we replace the deleted node R by the last node L of H so that it is still
a complete binary tree, but not necessarily a heap.
(iii) Finally we will reheap by placing the L to its appropriate place in H so that H is finally
a heap.

Let us understand this procedure by using the heap as shown in figure-6.13

91

82 65

74 43 28 59

Figure 6.13

Here A[R] = 91 is the root node and A[L] = 59 is the last node of the tree. First we access the
root node as:

Item = A[1];

and then we replace 91 with 51 as shown in figure-6.14 (a).


18

51 51

82 65 82 65

74 43 28 91 74 43 28

(a) (b)

82 82

51 65 74 65

74 43 28 51 43 28

(c) (d)

Figure 6.14

Now we will reheap this complete binary tree. First we compare 51 with its two children. And
since 51 is lesser than the larger child 82, so we will interchange them. The new binary tree
is as shown in figure-6.14(c). Now again 51 is compared with its two children. And since 51
is lesser than the left child 74, so we will interchange them. The new binary tree is as shown
in figure-6.14(d). Since there is no further element in the tree, therefore item 51 has placed
to its appropriate place in H.

Here is the deletion algorithm from the heap.

Algorithm : DeleteHeap

DeleteHeap(A, N)
Here ‘A’ is an array of ‘N’ number of elements

1. Set Item = A[1], Last = A[N] and Left = 2, Right = 3


2. Decrement ‘N’ as N = N - 1
3. Initialize I=1;
4. Repeat through step-7 while (Right <= N)
5. If ((Last >= A[Left]) && (Last >= A[Right])) then A[I] = last and
and go to step-10
Else If (A[Left] >= A[Right]) then Set A[I] = A[Left] and I = Left
Else A[I] = A[Right] and I = Right
6. Update Left as Left = 2 * I
7. Increment Right as Right = Left+1;
8. If (Left == N) && (Last < A[left]) then Set I = Left
9. Set A[I] = Last
10. Exit
19
Here is the C implementation of this deletion algorithm.

Implementation : DeleteHeap

DeleteHeap(int a[], int n)


{
int item, last, left, right, i;
item = a[1];
last = a[n];
i=1;
left = 2;
right = 3;
n--;

while (right <= n)


{
if ((last>=a[left])&&(last >= a[right]))
{
a[i] = last;
return (item);
}
else if (a[left] >= a[right])
{
a[i] = a[left];
i = left;
}
else
{
a[i] = a[right];
i = right;
}
left = 2*i;
right = left+1;
}
if ((left == n) && (last < a[left]))
i = left;
a[i] = last;
return (item);
}

Heap Sorting
The process of heap sorting is divided into two parts:

(i) In first part we build a heap H out of the elements of array using an InsertHeap()
algorithm.
(ii) In second part we repeatedly delete the root element of H using DeleteHeap()
algorithm and move it to the last position.

Heap Sorting – a sorting technique in which a list can be sorted by first building it
into a heap and then iteratively deleting the root node from the heap until the heap is
empty. If the deleted roots are stored in reverse order in an array they will be sorted in
ascending order (if a max heap is used)
20
The algorithm of heap sorting is as:

Algorithm : HeapSort

HeapSort(A, N)
Here ‘A’ is an array of ‘N’ number of elements

1. Set J = 1
2. Repeat through step-4 while (J <= N-1)
3. Call InsertHeap(A, J, A[J+1])
4. Increment the value of ‘J’ as J = J+1
5. Repeat through step-7 while (N >= 1)
6. Call DeleteHeap() as
Item = DeleteHeap(A, N)
7. Set A[N] = item
8. Decrement ‘N’ as N = N-1
9. Exit

Here is the C implementation of heap sorting.

Implementation : HeapSort

HeapSort(int a[], int n)


{
int i, j, item;
for(j=1; j<=n-1; j++) /* creating a heap */
InsertHeap(a, j, a[j+1]);

while (n >= 1)
{
item = DeleteHeap(a, n);
a[n] = item;
n--;
}
}

Analysis – As stated earlier, the heap sorting process is divided into two phases, therefore
we analyze the complexity of each phase separately. In first phase we assume that there are
‘n’ number of elements in an array and number of comparison to find the appropriate place
of a new element in H can not exceed the depth of H. The depth of a complete binary tree is
bounded by log2n, where n is the number of element in H. You can say that the running time
of first phase of heap sort is proportional to (n log 2n).

You might also like