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

10b Sorting

Uploaded by

swethajason816
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
16 views

10b Sorting

Uploaded by

swethajason816
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 29

Sorting

CS10003 PROGRAMMING AND DATA STRUCTURES

INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR


The Basic Problem
Given an array: x[0], x[1], ... , x[size-1] reorder the elements so that
x[0] <= x[1] <= ... <= x[size-1]

• That is, reorder entries so that the list is in increasing (non-decreasing) order.

We can also sort a list of elements in decreasing (non-increasing) order.

We prefer not to use additional arrays for the element rearrangement.

2
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Example
Original list:
10, 30, 20, 80, 70, 10, 60, 40, 70

Sorted in non-decreasing order:


10, 10, 20, 30, 40, 60, 70, 70, 80

Sorted in non-increasing order:


80, 70, 70, 60, 40, 30, 20, 10, 10

3
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Selection Sort

4
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
SELECTION SORT: The idea
General situation :
0 k size-1
x: smallest elements, sorted remainder, unsorted

Steps:
• Initialize k = 0.
• Find smallest element, mval, in the array segment x[k...size-1]
• Swap smallest element with x[k], then increase k.
0 k mval size-1

swap
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
5
Subproblem
/* Find index of smallest element in x[k...size-1] */

int min_loc (int x[ ], int k, int size)


{
int j, pos;

pos = k;
for (j=k+1; j<size; j++)
if (x[j] < x[pos])
pos = j;
return pos;
}

6
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Selection Sort Function
/* Sort x[0..size-1] in non-decreasing order */

int sel_sort (int x[], int size) {


int k, m, temp;

for (k = 0; k < size-1; k++) {


m = min_loc (x, k, size);
/* Swap x[k], x[m]*/
temp = x[k];
x[k] = x[m];
x[m] = temp;
}
}
7
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Example

x: 3 12 -5 6 142 21 -17 45 x: -17 -5 3 6 12 21 142 45

x: -17 12 -5 6 142 21 3 45 x: -17 -5 3 6 12 21 142 45

x: -17 -5 12 6 142 21 3 45 x: -17 -5 3 6 12 21 45 142

x: -17 -5 3 6 142 21 12 45 x: -17 -5 3 6 12 21 45 142

x: -17 -5 3 6 142 21 12 45

8
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Bubble Sort

9
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
BUBBLE SORT: The idea
General situation:

x:
In every pass, we go on comparing x:
0 0
neighboring pairs, and swap them if out
of order.
unsorted unsorted
for j = 0 to k-1
k-1
if (x[j] > x[j+1])
k k
interchange them.
At the end of this iteration, the ‘next
largest’ element (among the unsorted
sorted part) will settle at x[k]. sorted

Lighter elements bubble up.


size-1 Heavier elements settle down. size-1

10
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Bubble Sort

void bubble_sort (int x[], int size) {


int t;
How do the passes proceed?
for (i = 0; i < size; i++)
for (j = 0; j < size-i-1; j++)
In pass 1, we consider index 0 to size-1
if (x[j] > x[j+1]) {
In pass 2, we consider index 0 to size-2
// swap a[j] and a[j+1]
In pass 3, we consider index 0 to size-3
t = a[j]; ……
a[j] = a[j+1]; ……
a[j+1] = t; In pass size-1, we consider index 0 to 1.
}
}

11
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
A more efficient sorting method:
Mergesort

12
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
A popular sorting algorithm based on the divide-and-conquer approach.

Basic idea (divide-and-conquer method)


sort (list)
{
if the list has length greater than 1
{
Partition the list into lowlist and highlist;
sort (lowlist);
sort (highlist);
combine (lowlist, highlist);
}
}

13
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Merge Sort
Input Array

Part-I Part-II

Part-I Part-II Part-I Part-II

Merge
Split
Sorted Arrays

14
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
void merge_sort (int *A, int n)
{
int i, j, k, m;
int *B, *C;

if (n > 1) {
k = n/2; m = n - k;
B = (int *) malloc (k * sizeof(int));
C = (int *) malloc (m * sizeof(int));
for (i=0; i<k; i++) B[i] = A[i];
for (j=k; j<n; j++) C[j-k] = A[j];
// B contains first half of A
// C contains second half of A
merge_sort (B, k);
merge_sort (C, m);
merge (B, C, A, k, m); // destination array is A
free(B); free(C);
}
}

15
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Merging two sorted arrays
i j

Array a Sorted Array Array b Sorted Array


0 m 0 n

Array c Merged sorted array

0 m+n-1
k
Copy element from a (indexed by i) if its value is smaller than the element in b pointed by j ; otherwise,
copy the element from b (indexed by j).
If one of the arrays a or b get exhausted, simply copy the rest of the other array.

16
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
void merge (int *a, int *b, int *c, int m, int n)
// c is the destination array
{
int i=0, j=0, k=0, p;

// loop as long as neither array a nor array b is completed


while ((i<m) && (j<n)) {
if (a[i] < b[j])
{ c[k] = a[i]; i++; }
else
{ c[k] = b[j]; j++; }
k++;
}

if (i == m) { // array a completed; copy rest of array b to array c


for (p=j; p<n; p++)
{ c[k] = b[p]; k++; }
} else { // array b completed; copy rest of array a to array c
for (p=i; p<m; p++)
{ c[k] = a[p]; k++; }
}
}
17
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Example: showing the merge phase only
Initial array A contains 16 elements:
• 66, 33, 40, 22, 55, 88, 60, 11, 80, 20, 50, 44, 77, 30, 47, 23
Pass 1 :: Merge each pair of elements
• (33, 66) (22, 40) (55, 88) (11, 60) (20, 80) (44, 50) (30, 70) (23, 47)
Pass 2 :: Merge each pair of pairs
• (22, 33, 40, 66) (11, 55, 60, 88) (20, 44, 50, 80) (23, 30, 47, 77)
Pass 3 :: Merge each pair of sorted quadruplets
• (11, 22, 33, 40, 55, 60, 66, 88) (20, 23, 30, 44, 47, 50, 77, 80)
Pass 4 :: Merge the two sorted subarrays to get the final list
• (11, 20, 22, 23, 30, 33, 40, 44, 47, 50, 55, 60, 66, 77, 80, 88)

18
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
void merge_sort (int *A, int n) void merge (int *a, int *b, int *c, int m, int n)
{ {
int i, j, k, m; int i=0, j=0, k=0, p;
int *B, *C;
if (n > 1) { while ((i < m) && (j < n)) {
k = n/2; m = n - k; if (a[i] < b[j])
B = (int *) malloc (k * sizeof(int)); { c[k] = a[i]; i++; }
C = (int *) malloc (m * sizeof(int)); else
{ c[k] = b[j]; j++; }
for (i=0; i<k; i++)
k++;
B[i] = A[i];
}
for (j=k; j<n; j++)
C[j-k] = A[j];
if (i == m) {
// B contains first half of A for (p=j; p<n; p++)
// C contains second half of A { c[k] = b[p]; k++; }
merge_sort (B, k); } else {
merge_sort (C, m); for (p=i; p<m; p++)
merge (B, C, A, k, m); // dest A { c[k] = a[p]; k++; }
free(B); free(C); }
} }
} 19
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Time complexity of merge sort
If n denotes the number of elements to be sorted, then the number of comparisons required in
merge sort is approximately proportional to n log n.

We need extra storage space as we have to temporarily create space for the arrays B and C.

20
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Practically best sorting method:
Quicksort

21
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Introduction to Quick Sort
● Merge sort is a theoretically best (optimal) sorting algorithm.
● Quick sort is the practically best general-purpose sorting algorithm.
● Problems of merge sort:
■ Extra space requirement
■ Merging step is difficult to carry out without extra arrays.
● Quick sort is another recursive sorting algorithm.
● Quick sort takes a divide-and-conquer approach.
● In merge sort, the main work (merging) is done after the recursive calls return.
● In quick sort, the main work (partitioning) is done before the recursive calls are made.
● Basic idea of quick sort
■ Choose an element p of the array A as the pivot.
■ Decompose the array in three parts: L consisting the elements of A less than (or equal
to) p, R consisting of the elements of A larger than p, and the single element p.
■ Recursively sort L and R.
■ Output sorted(L) followed by p followed by sorted(R).
■ If partitioning is done in A itself, then there is no task left after the recursive calls.
22
Quick sort: Skeleton of the algorithm

void quicksort ( int A[], int n ) Original array


{
int pivotidx; Partitioning

if (n <= 1) return; L p R
pivotidx = partition (A, n);
quicksort (A, pivotidx);
Recursive calls
quicksort (A+pivotidx+1, n-pivotidx-1);
}
Sorted array

23
Partitioning using extra arrays
int partition ( int A[], int n )
{
int *L, *R, p, i, j, l, r;

if (n <= 1) return n-1;

L = (int *)malloc(n * sizeof(int));


R = (int *)malloc(n * sizeof(int));
p = A[n-1]; // Choose the last element of A as pivot
l = r = 0; // Initialize the sizes of L and R
for (i=0; i<=n-2; ++i)
if (A[i] <= p) L[l++] = A[i]; else R[r++] = A[i];
for (i=0; i<l; ++i) A[i] = L[i]; // Copy L to A
A[i++] = p; // Append p to A
for (j=0; j<r; ++j) A[i++] = R[j]; // Append R to A
free(L); free(R); // No further needs for L and R
return l;
} 24
In-place partitioning

● Possibility of partitioning A without any extra arrays make quick sort attractive and efficient.
● There are many variants of the in-place partitioning algorithm.
● We follow the CLRS variant:
Cormen , Leiserson, Rivest, and Stein, Introduction to Algorithms, 4th Edition, MIT Press
● We take p = A[n–1] as the pivot.
● The array A is always maintained as the concatenation LRUp, where
■ L consists of elements <= p
■ R consists of elements > p
■ U is the unprocessed part (elements in U are not yet classified to go to L or R)
● Each iteration processes one element from U, and sends that element to L or R as appropriate.
● After n – 1 iterations, there are no unprocessed elements, so the array is of the form LRp.
● It is then converted to the form LpR.
● Blocks (L and R) are never fully shifted. Only element swaps are used.
● This may destroy the order of the (equal) keys in the partitioned array.
25
In-place partitioning
i i
<= p >p Unprocessed p <= p >p Unprocessed p

Case 1: A[i] > p Case 2: A[i] <= p


i i
<= p >p Unprocessed p <= p >p Unprocessed p

i
<= p >p Unprocessed p

After end of loop


<= p >p p <= p p >p
26
In-place partitioning: The code
int partition ( int A[], int n )
{
int lend = -1, i;
int p, t;

p = A[n-1]; // Last element of A is the pivot


for (i=0; i<=n-2; ++i) {
if (A[i] <= p) { // Region L grows
++lend;
t = A[lend]; A[lend] = A[i]; A[i] = t;
}
// else Region R grows, ++i will do it
}
i = lend + 1; // i is the first index of Region R
t = A[i]; A[i] = A[n-1]; A[n-1] = t;
return i;
}
27
In-place partitioning: An example

28
Performance of quick sort
● Running times are specified as “roughly proportional to a function of the input size.”
● No (comparison-based) sorting algorithm can run faster than n log n is the worst case.
● For merge sort:
■ All cases are the same. No specific best / worst / average case.
■ Each case has running time n log n for merge sort.
● For quick sort:
■ Best case: Partitioning divides the array roughly into two equal halves
■ Worst case: Partitioning always gives one subarray of size one less than the array.
■ Average case: The pivot is any one element (smallest to largest) with equal probability.
● Example of worst case: The array is already sorted in ascending or descending order.
● Running time of quick sort:
■ Best and average case: n log n
■ Worst case: n2
● Quick sort is not theoretically optimal.
● In practice, quick sort is considered the fastest sorting algorithm for “general” arrays.
29

You might also like