TIC2001 Data Structures and Algorithms
Lecture Note #3
Sorting
Objectives
• To learn some classic sorting algorithms
1
• To analyse the running time of these
2 algorithms
• To learn concepts such as in-place sorts and
3 stable sorts
• Using C++ algorithm to perform sorting
4
[CS2040 AY2020/21 S1] 1
Why Study Sorting?
When an input is sorted by some sort key, many
problems become easy (eg. searching, min,
max, kth smallest, etc.)
Q: What is a sort key?
Sorting has a variety of interesting algorithmic
solutions, which embody many ideas:
Internal sort vs external sort
Iterative vs recursive
Comparison vs non-comparison based
Divide-and-conquer
Best/worst/average case time complexity bounds
[TIC2001 AY2023/24 S1] 3
Sorting applications
Uniqueness testing
Deleting duplicates
Frequency counting
Efficient searching
Dictionary
Telephone/street directory
Index of book
Author index of conference proceedings
etc.
[TIC2001 AY2023/24 S1] 4
Outline
Comparison based and Iterative algorithms
1. Selection Sort
2. Bubble Sort
3. Insertion Sort
Comparison based and Recursive algorithms
4. Merge Sort
5. Quick Sort
Non-comparison based
6. Radix Sort
7. Comparison of Sort Algorithms
In-place sort
Stable sort
8 std::sort() in C++ STL Note: In the lecture, we consider
only sorting in ascending order of
data unless otherwise stated.
[TIC2001 AY2023/24 S1] 5
1 Selection Sort
1 Idea of Selection Sort
Given an array of n items
1. Find the largest item.
2. Swap it with the item at the end of the array.
3. Go to step 1 by excluding the largest item
from the array.
[TIC2001 AY2023/24 S1] 6
1 Selection Sort of 5 integers
37 is the largest, swap it with
29 10 14 37 13 the last element, i.e. 13.
Q: How to find the largest?
29 10 14 13 37
13 10 14 29 37
13 10 14 29 37
10 13 14 29 37 Sorted!
[TIC2001 AY2023/24 S1] 7
1 Code of Selection Sort
// Algorithm, not complete c++ code
for (i = n-1; i > 0; i--) {
max = i; // set current element as maximum
// loop to get the maximum element
for (int j = 0; j < i; j++) {
if (a[j] > a[max])
max = j; // j is the current largest item
}
// Swap the largest item a[max] with the last item a[i]
int temp = a[max];
a[max] = a[i];
a[i] = temp;
}
}
[TIC2001 AY2023/24 S1] 8
1 Analysis of Selection Sort
Number of times the
statement is executed:
for (int i=n-1; i>=1; i--) { n-1
int index = i; n-1
for (int j=0; j<i; j++) { (n-1)+(n-2)+…+1
if (a[j] > a[index]) = n×(n-1)/2
index = j;
}
SWAP( ... ) n-1
}
Total = t1×(n-1)
+ t2×n×(n-1)/2
= O(n2)
t1 and t2 = costs of statements in outer and inner blocks.
[TIC2001 AY2023/24 S1] 9
2 Bubble Sort
[TIC2001 AY2023/24 S1]
2 Idea of Bubble Sort
“Bubble” down the largest item to the end of the
array in each iteration by examining the i-th and
(i+1)-th items
If their values are not in the correct order, i.e.
a[i] > a[i+1], swap them.
1 4 6 9 1 7 5 9
Inversion
i i+1 i i+1
// no need to swap // not in order, need to swap
[TIC2001 AY2023/24 S1] 10
2 Example of Bubble Sort
The first two passes of Bubble Sort for an array of 5
integers
At the end of pass 2, the second
largest item 29 is at the second
At the end of pass 1, the largest last position.
item 37 is at the last position.
[TIC2001 AY2023/24 S1] 11
2 Code of Bubble Sort
void bubbleSort(int a[]) {
for (int i = 1; i < n; i++) {
for (int j = 0; j < n - i; j++) {
if (a[j] > a[j+1]) { // the larger item bubbles down (swap)
int temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
}
}
[TIC2001 AY2023/24 S1] 12
2 Analysis of Bubble Sort
1 iteration of the inner loop (test and swap) requires time
bounded by a constant c
void bubbleSort(int[ a[]) {
Doubly nested loops: for (int i = 1; i < n; i++) {
Outer loop: exactly n-1 iterations for (int j = 0; j < n - i; j++) {
if (a[j] > a[j+1]) { // (swap)
Inner loop: int temp = a[j];
a[j] = a[j+1];
When i=1, (n-1) iterations a[j+1] = temp;
When i=2, (n-2) iterations }
}
… }
When i=(n-1), 1 iteration }
Total number of iterations = (n-1) + (n-2) + … + 1
= n×(n-1)/2
Total time = c × n × (n-1)/2 = O(n2)
[TIC2001 AY2023/24 S1] 13
2 Bubble Sort can be improved
Given a sorted input, Bubble Sort still
requires O(n2) to sort.
It does not make an effort to check
whether the input has been sorted.
Thus it can be improved by using a flag,
isSorted, as follows (next slide):
[TIC2001 AY2023/24 S1] 14
2 Code of Bubble Sort (Improved version)
void bubbleSort2(int a[]) {
for (int i = 1; i < n; i++) {
bool isSorted = true; // isSorted = true if a[] is sorted
for (int j = 0; j < n-i; j++) {
if (a[j] > a[j+1]) { // the larger item bubbles up
int temp = a[j]; // and isSorted is set to false,
a[j] = a[j+1]; // i.e. the data was not sorted
a[j+1] = temp;
isSorted = false;
}
}
if (isSorted) return; // Why?
}
}
[TIC2001 AY2023/24 S1] 15
2 Analysis of Bubble Sort (Improved version)
Worst case
Input in descending order (any other situation?)
How many iterations in the outer loop are needed?
Answer: n-1 iterations
Running time remains the same: O(n2)
Best case
Input is already in ascending order
The algorithm returns after a single iteration in the
outer loop. (Why?)
Running time: O(n)
[TIC2001 AY2023/24 S1] 16
3 Insertion Sort
[TIC2001 AY2023/24 S1]
3 Idea of Insertion Sort
Arranging a hand of poker cards
Start with one card in your hand
Pick the next card and insert it into its proper sorted
order
Repeat previous step for all the rest of the cards
[TIC2001 AY2023/24 S1] 17
3 Example of Insertion Sort
n=4 S1 S2
Given a seq: 40 13 20 8
i=1 13 40 20 8
i=2 13 20 40 8
i=3 8 13 20 40
n = no of items to be sorted
S1 = sub-array sorted so far
S2 = elements yet to be processed
In each iteration, how to insert the next element into
S1 efficiently?
[TIC2001 AY2023/24 S1] 18
3 Code of Insertion Sort
void insertionSort(int a[]) {
for (int i=1;i<n;i++) { //Q: Why i starts from 1?
// a[i] is the next data to insert
int next = a[i];
// Scan backwards to find a place. Q: Why not scan forwards?
int j; // Q: Why is j declared here?
// Q: What if a[j] <= next?
for (j=i-1; j>=0 && a[j]>next; j--)
a[j+1] = a[j];
// Now insert the value next after index j at the end of loop
a[j+1] = next;
}
}
Q: Can we replace these two “next” with a[i]?
Ans: No! (Why?)
[TIC2001 AY2023/24 S1] 19
3 Analysis of Insertion Sort
Outer loop executes exactly n-1 times
Number of times inner loop executes depends on the
inputs:
Best case: array already sorted, hence (a[j] > next) is always false
No shifting of data is necessary; Inner loop not executed at all.
Worst case: array reversely sorted, hence (a[j] > next) is always
true
Need i shifts for i = 1 to n-1.
Insertion always occurs at the front.
... insertionSort(int[] a) {
Therefore, the best case for (int i=1;i<n;i++) {
running time is O(n). int next = a[i];
int j;
(Why?) for (j=i-1; j>=0 && a[j]>next; j--)
a[j+1] = a[j];
The worst case running
a[j+1] = next;
time is O(n2). (Why?) }
}
[TIC2001 AY2023/24 S1] 20
4 Merge Sort
4 Idea of Merge Sort (1/3)
Suppose we only know how to merge two sorted
lists of elements into one combined list
Given an unsorted list of n elements
Since each element is a sorted list, we can
repeatedly…
Merge each pair of lists, each list containing one
element, into a sorted list of 2 elements.
Merge each pair of sorted lists of 2 elements into a
sorted list of 4 elements.
…
The final step merges 2 sorted lists of n/2 elements to
obtain a sorted list of n elements.
[TIC2001 AY2023/24 S1] 21
4 Idea of Merge Sort (2/3)
Divide-and-conquer method solves problem by
three steps:
Divide Step: divide the larger problem into smaller
problems.
(Recursively) solve the smaller problems.
Conquer Step: combine the results of the smaller
problems to produce the result of the larger problem.
[TIC2001 AY2023/24 S1] 22
4 Idea of Merge Sort (3/3)
Merge Sort is a divide-and-conquer sorting
algorithm
Divide Step: Divide the array into two (equal) halves.
(Recursively) Merge sort the two halves.
Conquer Step: Merge the two sorted halves to form a
sorted array.
Q: What are the base cases?
[TIC2001 AY2023/24 S1] 23
4 Example of Merge Sort
7 2 6 3 8 4 5
Divide into
two halves 7 2 6 3 8 4 5
Recursively
sort the halves 2 3 6 7 4 5 8
Merge the halves 2 3 4 5 6 7 8
[TIC2001 AY2023/24 S1] 24
4 Code of Merge Sort
... mergeSort(int a[], int i, int j) {
// to sort data from a[i] to a[j], where i<j
if (i < j) { // Q: What if i >= j?
int mid = (i+j)/2; // divide
mergeSort(a, i, mid); // recursion
mergeSort(a, mid+1, j);
merge(a,i,mid,j); //conquer: merge a[i..mid] and
//a[mid+1..j] back into a[i..j]
}
}
[TIC2001 AY2023/24 S1] 25
4 Merge Sort of a 6-element Array (1/2)
mergeSort(a,i,mid);
mergeSort(a,mid+1,j);
merge(a,i,mid,j);
38 16 27 39 12 27
38 16 27 39 12 27
38 16 27 39 12 27
38 16 39 12
16 38 12 39
16 27 38 12 27 39
12 16 27 27 38 39
[TIC2001 AY2023/24 S1] 26
4 Merge Sort of a 6-element Array (2/2)
mergeSort(a,i,mid);
mergeSort(a,mid+1,j);
merge(a,i,mid,j);
38 16 27 39 12 27
38 16 27 39 12 27 Divide phase:
Recursive call to
38 16 27 39 12 27 mergeSort
38 16 39 12
16 38 12 39
Conquer phase:
16 27 38 12 27 39 Merge steps
The sorting is done
here
12 16 27 27 38 39
[TIC2001 AY2023/24 S1] 27
4 How to Merge 2 Sorted Subarrays?
Temp array
t[0..5] a[0..2] a[3..5]
245 378
2 245 378
2 3 245 378
2 3 4 245 378
2 3 4 5 245 378
2 3 4 5 7 8 245 378
[TIC2001 AY2023/24 S1] 28
4 Merge Algorithm (1/2)
... merge(int a[], int i, int mid, int j) {
// Merges the 2 sorted sub-arrays a[i..mid] and
// a[mid+1..j] into one sorted sub-array a[i..j]
int temp[] = new int[j-i+1]; // temp storage
int left = i, right = mid+1, it = 0;
// it = next index to store merged item in temp[]
// Q: What are left and right?
while (left<=mid && right<=j) { // output the smaller
if (a[left] <= a[right])
temp[it++] = a[left++];
else
temp[it++] = a[right++];
}
[TIC2001 AY2023/24 S1] 29
4 Merge Algorithm (2/2)
// Copy the remaining elements into temp. Q: Why?
while (left<=mid) temp[it++] = a[left++];
while (right<=j) temp[it++] = a[right++];
// Q: Will both the above while statements be executed?
// Copy the result in temp back into
// the original array a
for (int k = 0; k < temp.length; k++)
a[i+k] = temp[k];
}
[TIC2001 AY2023/24 S1] 30
4 Analysis of Merge Sort (1/3)
In Merge Sort, the bulk of work is done in the Merge step
merge(a, i, mid, j)
Total number of items = k = j – i + 1
Number of comparisons k – 1 (Q: Why not = k – 1?)
Number of moves from original array to temp array = k
Number of moves from temp array to original array = k
In total, number of ... mergeSort(int a[], int i, int j) {
if (i < j) {
operations 3k – 1 = O(k) int mid = (i+j)/2;
mergeSort(a, i, mid);
How many times is mergeSort(a, mid+1, j);
merge(a,i,mid,j);
merge() called? }
}
31
4 Analysis of Merge Sort (2/3)
Level 0: Level 0:
Mergesort n items n 0 call to Merge
Level 1: Level 1:
2 calls to Mergesort n/2 items n/2 n/2 1 calls to Merge
Level 2: Level 2:
4 calls to Mergesort n/22 items n/22 n/22 n/22 n/22 2 calls to Merge
…
Level (log n):
2(log n) -1(= n/2)
Level (log n):
n calls to Mergesort 1 item 1 1 …………………… 1 1 calls to Merge
Let h be the maximum level, ie. Mergesort 1 item.
n/(2h ) = 1 n = 2h h = log n
32
4 Analysis of Merge Sort (3/3)
Level 0: 0 call to Merge
Level 1: 1 call to Merge with n/2 items each,
O(1 2 n/2) = O(n) time
Level 2: 2 calls to Merge with n/22 items each,
O(2 2 n/22) = O(n) time
Level 3: 22 calls to Merge with n/23 items each,
O(22 2 n/23) = O(n) time
…
Level (log n): 2(log n)-1(= n/2) calls to Merge with n/2log n
(= 1) item each,
O(n/2 2 x 1) = O(n) time
In total, running time = (log n)*O(n) = O(n log n)
[TIC2001 AY2023/24 S1] 33
4 Drawbacks of Merge Sort
Implementation of merge() is not
straightforward
Requires additional temporary arrays and
to copy the merged sets stored in the
temporary arrays to the original array
Hence, additional space complexity = O(n)
[TIC2001 AY2023/24 S1] 34
5 Quick Sort
5 Idea of Quick Sort
Quick Sort is a divide-and-conquer algorithm
Divide Step: Choose a pivot item p and partition the
items of a[i..j] into 2 parts so that
Items in the first part are < p, and
Items in the second part are p.
Recursively sort the 2 parts
Conquer Step: Do nothing! No merging is needed.
What are the base cases?
[TIC2001 AY2023/24 S1] 35
5 Example of Quick Sort
Pivot
Choose the 1st item as pivot 27 38 12 39 27 16
Pivot
Partition a[] about
the pivot 27 16 12 27 39 27 38
Pivot
Recursively sort
the two parts 12 16 27 27 38 39
Note that after the partition,
the pivot is moved to its final position!
No merge phase is needed.
[TIC2001 AY2023/24 S1] 36
5 Code of Quick Sort
... quickSort(int a[], int i, int j) {
if (i < j) { // Q: What if i >= j?
int pivotIdx = partition(a, i, j);
quickSort(a, i, pivotIdx-1);
quickSort(a, pivotIdx+1, j);
// No conquer part!
}
}
[TIC2001 AY2023/24 S1] 37
5 Partition algorithm idea (1/4)
To partition a[i..j], we choose a[i] as the pivot p.
Why choose a[i]? Are there other choices?
The remaining items (i.e. a[i+1..j]) are divided into
3 regions:
S1 = a[i+1..m] where items < p
S2 = a[m+1..k-1] where item p
Unknown (unprocessed) = a[k..j], where items are yet to
be assigned to S1 or S2.
p <p p ?
i m k j
S1 S2 Unknown
[TIC2001 AY2023/24 S1] 38
5 Partition algorithm idea (2/4)
Initially, regions S1 and S2 are empty. All items
excluding p are in the unknown region.
Then, for each item a[k] (for k=i+1 to j) in the unknown
region, compare a[k] with p:
If a[k] p, put a[k] into S2.
Otherwise, put a[k] into S1.
Q: How about if we change to > in the condition
part?
[TIC2001 AY2023/24 S1] 39
5 Partition algorithm idea (3/4)
Case 1:
S1 S2
If a[k] =y p, p <p x p y ?
i m k j
S1 S2
Increment k p <p x p y ?
i m k j
[TIC2001 AY2023/24 S1] 40
5 Partition algorithm idea (4/4)
Case 2: S1 S2
If a[k]=y < p p <p x p y ?
i m k j
Increment m p <p x p y ?
i m k j
Swap x and y p <p y p x ?
i m k j
Increment k p <p y p x ?
i m k j
[TIC2001 AY2023/24 S1] 41
5 Code of Partition Algorithm
... partition(int a[], int i, int j) {
// partition data items in a[i..j]
int p = a[i]; // p is the pivot, the ith item
int m = i; // Initially S1 and S2 are empty
for (int k=i+1; k<=j; k++) { //process unknown region
if (a[k] < p) { // case 2: put a[k] to S1
m++;
swap(a,k,m);
} else { // case 1: put a[k] to S2. Do nothing!
} // else part should be removed since it is empty
}
swap(a,i,m); // put the pivot at the right place
return m; // m is the pivot’s final position
}
As there is only one ‘for’ loop and the size of the array is
n = j – i + 1, so the complexity for partition() is O(n)
[TIC2001 AY2023/24 S1] 42
5 Partition Algorithm: Example
Same value, no need to swap them.
[TIC2001 AY2023/24 S1] 43
5 Analysis of Quick Sort: Worst Case (1/2)
When a[0..n-1] is in increasing order:
10 13 14 29 37
p S2
S1 is empty
What is the index returned by partition()?
swap(a,i,m) will swap the pivot with itself!
The left partition (S1) is empty and
The right partition (S2) is the rest excluding the pivot.
What if the array is in decreasing order?
[TIC2001 AY2023/24 S1] 44
5 Analysis of Quick Sort: Worst Case (2/2)
1 n-1
Total no. of
1 n-2 levels = n
……
As each partition takes
linear time, the
algorithm in its worst
1 1
case has n levels and
hence it takes time
contains the pivot only! n+(n-1)+...+1 = O(n2)
[TIC2001 AY2023/24 S1] 45
5 Analysis of Quick Sort: Best/Average case
Best case occurs when partition always splits the
array into 2 equal halves
Depth of recursion is log n.
Each level takes n or fewer comparisons, so the time
complexity is O(n log n)
In practice, worst case is rare, and on the average,
we get some good splits and some bad ones
Average time is O(n log n) *especially true if using
randomized pivoting (randomly choose the pivot rather than keep using the 1st
element). Can get even better theoretical bounds if use median as pivot
(outside scope of this course).
[TIC2001 AY2023/24 S1] 46
6 Radix Sort
6 Idea of Radix Sort
Treats each data to be sorted as a character
string.
It is not using comparison, i.e., no comparison
among the data is needed.
Hence it is a non-comparison based sort (the
preceding sorting algorithms are called comparison based
sorts)
In each iteration, organize the data into groups
according to the next character in each data.
[TIC2001 AY2023/24 S1] 47
6 Radix Sort of Eight Integers
[TIC2001 AY2023/24 S1] 48
6 Pseudocode and Analysis of Radix Sort
radixSort(int array[], int n, int d) {
// Sorts n d-digit numeric strings in the array.
for (j = d down to 1) { // for digits in last position to 1st position
initialize 10 groups (queues) to empty // Q: why 10 groups?
for (i=0 through n-1) {
k = jth digit of array[i]
place array[i] at the end of group k
}
Replace array with all items in group 0, followed by all items
in group 1, and so on.
}
} Complexity is O(d×n) where d is the
maximum number of digits of the n numeric
strings in the array. Since d is fixed or
bounded, so the complexity is O(n).
[TIC2001 AY2023/24 S1] 49
7 Comparison of Sorting
Algorithms
7 In-place Sort
A sorting algorithm is said to be an in-place sort if
it requires only a constant amount, i.e. O(1), of
extra space during the sorting process.
Merge Sort is not in-place. (Why?)
How about Quick Sort?
[TIC2001 AY2023/24 S1] 50
7 Stable Sort
A sorting algorithm is stable if the relative order of
elements with the same key value is preserved by
the algorithm.
Example 1 – An application of stable sort:
Assume that names have been sorted in alphabetical
order.
Now, if this list is sorted again by tutorial group number,
a stable sort algorithm would ensure that all students in
the same tutorial groups still appear in alphabetical order
of their names.
Quick Sort and Selection Sort are not stable. (Why?)
[TIC2001 AY2023/24 S1] 51
7 Non-Stable Sort
Example 2 – Quick Sort and Selection Sort are not stable:
Quick sort:
1285 150 5* 4746 602 5+ 8356 // pivot in bold
1285 (150 5* 602 5+) (4746 8356)
5+ 150 5* 602 1285 4746 8356 //pivot swapped with the last one in S1
// the 2 5’s are in different order of the initial list
Selection sort: select the largest element and swap with the last one
4746 1285 5* 602 8356 5+ 277
4746 1285 5* 602 277 5+ (8356)
5+ 1285 5* 602 277 (4746 8356)
// the 2 5’s are in different order of the initial list
[TIC2001 AY2023/24 S1] 52
7 Summary of Sorting Algorithms
Worst Case Best Case In-place? Stable?
Selection Sort O(n2) O(n2) Yes No
Insertion Sort O(n2) O(n) Yes Yes
Bubble Sort O(n2) O(n2) Yes Yes
Bubble Sort 2 O(n2) O(n) Yes Yes
(improved with flag)
Merge Sort O(n log n) O(n log n) No Yes
Radix Sort (non- O(dn) O(dn) No Yes
comparison based)
Quick Sort O(n2) O(n log n) Yes No
Notes: 1. O(dn) for Radix Sort is due to non-comparison based sorting.
2. O(n log n) is the best possible for comparison based sorting.
[TIC2001 AY2023/24 S1] 53
Comparing n log n and dn
One Million One Billion
One Triillion One Quadrillion
63
8 Use of C++ Sorting algorithm
[TIC2001 AY2023/24 S1]
8 std::sort() in C++ STL
• C++ STL provides a function sort that sorts
a vector or array (items with random
access)
• It generally takes two parameters:
• The first one being the point of the
array/vector from where the sorting
needs to begin, and
• the second parameter being the length
up to which we want the array/vector to
get sorted.
[TIC2001 AY2023/24 S1] 54
8 std::sort() in C++ STL
• There is an optional third parameter
which can be used in cases such as if
we want to sort the elements
lexicographically.
• By default, the sort() function sorts
the elements in ascending order.
[TIC2001 AY2023/24 S1] 54
8 std::sort() in C++ STL
• A simple program to show the working of sort()
#include <algorithm>
using namespace std;
int main() {
int arr[] = { 1, 5, 8, 9, 6, 7, 3, 4, 2, 0 };
int n = sizeof(arr) / sizeof(arr[0]);
sort(arr, arr + n); /*two parameters, the beginning of the array
and the length n up to */
cout << "\nArray after sorting using "
"default sort is : \n";
for (int i = 0; i < n; ++i)
cout << arr[i] << " ";
return 0; Output:
} Array after sorting using default sort is :
0 1 2 3 4 5 6 7 8 9
[TIC2001 AY2023/24 S1] 54
8 std::sort() in C++ STL
• How to sort in descending order?
• sort() takes a third parameter that is used
to specify the order in which elements are
to be sorted.
• We can pass the “greater()” function
to sort in descending order.
• This function does a comparison
in a way that puts greater elements before.
[TIC2001 AY2023/24 S1] 54
8 std::sort() in C++ STL
• A simple program to show the working of sort()
#include <algorithm>
using namespace std;
int main() {
int arr[] = { 1, 5, 8, 9, 6, 7, 3, 4, 2, 0 };
int n = sizeof(arr) / sizeof(arr[0]);
sort(arr, arr + n, greater<int>());
cout << "\nArray after sorting is : \n";
for (int i = 0; i < n; ++i)
cout << arr[i] << " ";
return 0;
} Output:
Array after sorting using is :
9 8 7 6 5 4 3 2 1 0
[TIC2001 AY2023/24 S1] 54
8 std::sort() in C++ STL
• Sort the array only in the given range
• To deal with such types of problems we just have to
mention the range inside the sort function.
#include <algorithm>
using namespace std;
int main() {
int arr[] = { 1, 5, 8, 9, 6, 7, 3, 4, 2, 0 };
int n = sizeof(arr) / sizeof(arr[0]);
// sort the elements which lies in the range of 2 to (n-1)
sort(arr+2, arr + n);
cout << "\nArray after sorting is : \n";
for (int i = 0; i < n; ++i)
cout << arr[i] << " ";
Output:
return 0; Array after sorting using is :
} 1 5 0 2 3 4 6 7 8 9
[TIC2001 AY2023/24 S1] 54
8 std::sort() in C++ STL
• How to sort in a particular order?
• We can also write our own comparator function and
pass it as a third parameter.
• This “comparator” function returns a value;
convertible to bool, which basically tells us whether
the passed “first” argument should be placed before
the passed “second” argument or not.
[TIC2001 AY2023/24 S1] 54
8 std::sort() in C++ STL
• How to sort in a particular order?
• For eg:
In the code below, suppose intervals {6,8} and {1,9}
are passed as arguments in the “compareInterval”
function(comparator function).
• Now as i1.first (=6) < i2.first (=1), so our function
returns “false”, which tells us that “first” argument
should not be placed before “second” argument and
so sorting will be done in order like {1,9} first and
then {6,8} as next.
[TIC2001 AY2023/24 S1] 54
8 std::sort() in C++ STL
struct Interval { // An interval has a start time and end time
int start, end;
};
// Compares two intervals according to starting times.
bool compareInterval(Interval i1, Interval i2) {
return (i1.start < i2.start);
} Output:
Intervals sorted by start time :
int main() { [1,9] [2,4] [4,7] [6,8]
Interval arr[]
= { { 6, 8 }, { 1, 9 }, { 2, 4 }, { 4, 7 } };
int n = sizeof(arr) / sizeof(arr[0]);
// sort the intervals in increasing order of start time
sort(arr, arr + n, compareInterval);
cout << "Intervals sorted by start time : \n";
for (int i = 0; i < n; i++)
cout << "[" << arr[i].start << "," << arr[i].end
<< "] ";
return 0;
}
[TIC2001 AY2023/24 S1] 54
8 std::sort() in C++ STL
#include <algorithm>
#include <iostream>
using namespace std;
template <class T>
class Comparator { // we pass an object of this class as
// third arg to sort function...
public:
bool operator()(T x1, T x2){
return x1 < x2;
}
};
// return type is bool
template <class T> bool funComparator(T x1, T x2){
return x1 <= x2;
}
void show(int a[], int array_size) {
for (int i = 0; i < array_size; i++) {
cout << a[i] << " ";
}
}[TIC2001 AY2023/24 S1] 54
8 std::sort() in C++ STL
int main(){
int a[] = { 1, 5, 8, 9, 6, 7, 3, 4, 2, 0 };
int asize = sizeof(a) / sizeof(int);
cout << "The array before sorting is : ";
show(a, asize);
cout << endl << "The array after sorting is(asc) :";
sort(a, a + asize);
show(a, asize);
cout << endl << "The array after sorting is(desc) :";
sort(a, a + asize, greater<int>());
show(a, asize);
cout << endl
<< "The array after sorting is(asc but our "
"comparator class) :";
sort(a, a + asize, Comparator<int>());
show(a, asize);
cout << endl
<< "The array after sorting is(asc but our "
"comparator function) :";
sort(a, a + asize, funComparator<int>);
show(a, asize);
return 0;
}
[TIC2001 AY2023/24 S1] 54
8 std::sort() in C++ STL
Output
The array before sorting is : 1 5 8 9 6 7 3 4 2 0
The array after sorting is(asc) : 0 1 2 3 4 5 6 7 8 9
The array after sorting is(desc) : 9 8 7 6 5 4 3 2 1 0
The array after sorting is(asc but our comparator class) :
0 1 2 3 4 5 6 7 8 9
The array after sorting is(asc but our comparator function) :
0 1 2 3 4 5 6 7 8 9
[TIC2001 AY2023/24 S1] 54
Summary
We have introduced and analysed some classic sorting
algorithms.
Merge Sort and Quick Sort are in general faster than
Selection Sort, Bubble Sort and Insertion Sort.
The sorting algorithms discussed here are comparison
based sorts, except for Radix Sort which is non-
comparison based.
O(n log n) is the best possible worst-case running time for
comparison based sorting algorithms.
There exist C++ algorithm to perform sorting.
[TIC2001 AY2023/24 S1] 66
End of file
[TIC2001 AY2023/24 S1]