Sorting
Sorting
• Given a set (container) of n elements
• E.g. array, set of words, etc.
• Suppose there is an order relation that can be
set across the elements
• Goal Arrange the elements in ascending order
• Start 🡪 1 23 2 56 9 8 10 100
• End 🡪 1 2 8 9 10 23 56 100
Bubble Sort
• Simplest sorting algorithm
• Idea:
• 1. Set flag = false
• 2. Traverse the array and compare pairs of two
elements
• 1.1 If E1 ≤ E2 - OK
• 1.2 If E1 > E2 then Switch(E1, E2) and set flag = true
• 3. If flag = true goto 1.
• What happens?
Bubble Sort
1 1 23 2 56 9 8 10 100
2 1 2 23 56 9 8 10 100
3 1 2 23 9 56 8 10 100
4 1 2 23 9 8 56 10 100
5 1 2 23 9 8 10 56 100
---- finish the first traversal ---- Why Bubble Sort ?
---- start again ----
1 1 2 23 9 8 10 56 100
2 1 2 9 23 8 10 56 100
3 1 2 9 8 23 10 56 100
4 1 2 9 8 10 23 56 100
---- finish the second traversal ----
---- start again ----
………………….
Implement Bubble Sort
with an Array
void bubbleSort (Array S, length n) {
boolean isSorted = false;
int j=1;
while(!isSorted) {
isSorted = true;
for(i = 0; i<n-j; i++) {
if(S[i] > S[i+1]) {
int aux = S[i];
S[i] = S[i+1]; S[i+1] = aux;
isSorted = false;
}
}
j++
}
Running Time for Bubble Sort
• One traversal = move the maximum element
at the end
• Traversal #i : n – i + 1 operations
• Running time:
(n – 1) + (n – 2) + … + 1 = (n – 1) n / 2 = O(n
2
)
• When does the worst case occur ?
• Best case ?
Sorting Algorithms Using Priority
Queues
• Remember Priority Queues = queue where the dequeue operation
always removes the element with the smallest key 🡪 removeMin
• Selection Sort
• insert elements in a priority queue implemented with an
unsorted sequence
• remove them one by one to create the sorted sequence
• Insertion Sort
• insert elements in a priority queue implemented with a
sorted sequence
• remove them one by one to create the sorted sequence
Selection Sort
• insertion: O(1 + 1 + … + 1) = O(n)
• selection: O(n + (n-1) + (n-2) + … + 1) = O(n2)
void selectionSort(int arr[], int n) {
int i, j, minIndex, tmp;
for (i = 0; i < n - 1; i++) {
minIndex = i;
for (j = i + 1; j < n; j++)
if (arr[j] < arr[minIndex])
minIndex = j;
if (minIndex != i) {
tmp = arr[i];\
arr[i] = arr[minIndex];
arr[minIndex] = tmp;
}
}
}
Insertion Sort
• insertion: O(1 + 2 + … + n) = O(n2)
• selection: O(1 + 1 + … + 1) = O(n)
void insertionSort(int arr[], int length) {
int i, j, tmp;
for (i = 1; i < length; i++) {
j = i;
while (j > 0 && arr[j - 1] > arr[j]) {
tmp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = tmp;
j--;
}
}
}
Sorting with Binary Trees
• Using heaps (see slides on heaps)
• How to sort using a minHeap ?
• Using binary search trees
• How to sort using BST?
Heap Sorting
• Step 1: Build a heap
• Step 2: removeMin( )
Recall: Building a Heap
• build (n + 1)/2 trivial one-element heaps
• build three-element heaps on top of them
Recall: Heap Removal
• Remove element
from priority queues?
removeMin( )
Recall: Heap Removal
• Begin downheap
Sorting with BST
• Use binary search trees for sorting
• Start with unsorted sequence
• Insert all elements in a BST
• Traverse the tree…. how ?
• Running time?
Next
• Sorting algorithms that rely on the “DIVIDE
AND CONQUER” paradigm
• One of the most widely used paradigms
• Divide a problem into smaller sub problems, solve
the sub problems, and combine the solutions
• Learned from real life ways of solving problems
Divide-and-Conquer
• Divide and Conquer is a method of algorithm
design that has created such efficient algorithms as
Merge Sort.
• In terms or algorithms, this method has three distinct
steps:
• Divide: If the input size is too large to deal with in
a straightforward manner, divide the data into two
or more disjoint subsets.
• Recur: Use divide and conquer to solve the
subproblems associated with the data subsets.
• Conquer: Take the solutions to the subproblems
and “merge” these solutions into a solution for the
original problem.
Merge-Sort
• Algorithm:
• Divide: If S has at leas two elements (nothing needs to be done if S
has zero or one elements), remove all the elements from S and put
them into two sequences, S1 and S2, each containing about half of the
elements of S. (i.e. S1 contains the first ⎡n/2⎤ elements and S2
contains the remaining ⎣n/2⎦ elements.
• Recur: Recursive sort sequences S1 and S2.
• Conquer: Put back the elements into S by merging the sorted
sequences S1 and S2 into a unique sorted sequence.
• Merge Sort Tree:
• Take a binary tree T
• Each node of T represents a recursive call of the merge sort
algorithm.
• We associate with each node v of T a the set of input passed to the
invocation v represents.
• The external nodes are associated with individual elements of S,
upon which no recursion is called.
Merge-Sort
Merge-Sort(cont.)
Merge-Sort (cont’d)
Merging Two Sequences
Quick-Sort
• Another divide-and-conquer sorting algorihm
• To understand quick-sort, let’s look at a high-level description
of the algorithm
1) Divide : If the sequence S has 2 or more elements, select an
element x from S to be your pivot. Any arbitrary element, like
the last, will do. Remove all the elements of S and divide them
into 3 sequences:
L, holds S’s elements less than x
E, holds S’s elements equal to x
G, holds S’s elements greater than x
2) Recurse: Recursively sort L and G
3) Conquer: Finally, to put elements back into S in order, first
inserts the elements of L, then those of E, and those of G.
Here are some diagrams....
Idea of Quick Sort
1) Select: pick an element
2) Divide: rearrange elements
so that x goes to its final
position E
3) Recurse and Conquer:
recursively sort
Quick-Sort Tree
In-Place Quick-Sort
Divide step: l scans the sequence from the left, and r from the right.
A swap is performed when l is at an element larger than the pivot and r is at one
smaller than the pivot.
In Place Quick Sort (cont’d)
A final swap with the pivot completes the divide step
Running time analysis
• Average case analysis
• Worst case analysis
• What is the worst case for quick-sort?
• Running time?