Chapter 7
Sorting
Sorting
Applications of sorting:
- searching
- list verification
Given a list of records (R0, R1,…., Rn-1),
- each record, Ri, has a key value Ki
- ordering relation (<) on the keys
Sorting is to find a permutation such that
K(i-1) <= K(i) , 0 < i <= n-1
Structure of records
typedef struct element{
int key;
/* other field */
} element;
Characteristics of sorting
• Internal sort: the list is small enough to sort
entirely in main memory
- bubble sort, insertion sort, quick sort,
heap sort, merge sort
External sort: too much information to fit
into main memory
- the file must be brought into the main
memory in pieces until the entire file is
sorted
For i=2 to n,
for the sequence of already ordered records,
R
1, R
2,….,R
i-1, insert R
iso that the resulting
sequence is also ordered
-
n = 5, input sequence (3, 2, 5, 4, 1)
Insertion Sort
i [1] [2] [3] [4] [5] - 2 3 4 5 3 2 2 2 1 2 3 3 3 2 5 5 5 4 3 4 4 4 5 4 1 1 1 1 5Insertion Sort
void insertion_sort(element a[ ], int n) {
/* sort a[1:n] into nondecreasing order */
int i, j; element temp; for (i = 2; i <=n; i++) {
temp = a[i];
for (j = i - 1; j >= 1 && temp.key < a[j].key; j--) a[j + 1] = a[j];
a[j + 1] = temp; }
}
Example
- Worst case behavior of insertion sort n = 5, input sequence: (5, 4, 3, 2, 1)
• Good to use when only a few records are out of order
ex) n = 5, input sequence: (2, 3, 4, 5, 1) • Also good for small lists
Divide and Conquer
Three steps in Divide and Conquer method
Divide
the problem into a number of subprolems
Conquer
the subproblems. If it is not still difficult,
then solve them recursively
Combine
the solutions to the subproblems into the
solution for the original problem
Quick Sort
• divide and conquer
• use recursion
• Best, average time - O(n·log
2n)
• Worst time: O(n
2)
• Don’t need additional space
X
pivot elements smaller than
or equal to pivot
elements larger than or equal to pivot
X’ X X : pivot
0 1 n-1
swap
the first element greater than pivot
the first element smaller than pivot
new pivot X’ X · · · X
Quick Sort
sortedinput file: 10 records
- (26,5,37,1,61,11,59,15,48,19)
Example of Quick Sort
pivot i j
26 5 37 1 61 11 59 15 48 19
26 5 19 1 61 11 59 15 48 37
i j26 5 19 1 15 11 59 61 48 37
i j26 5 19 1 15 11 59 61 48 37
i j
Example of Quick Sort
11 5 19 1 15
26
59 61 48 37
· · ·
void quicksort(element a[ ], int left, int right) { int pivot, i, j; element temp; if (left < right) { i = left; j = right + 1; pivot = a[left].key; do { : } while (i < j);
swap(a[left], a[j], temp); quicksort(a, left, j-1); quicksort(a, j+1, right); }
}
do { do
i++;
while (a[i].key < pivot); do
j--;
while (a[j].key > pivot); if (i < j)
swap(a[i], a[j], temp); } while (i < j);
R1 26 11 1 1 1 1 1 1 R2 5 5 5 5 5 5 5 5 R3 37 19 11 11 11 11 11 11 R4 1 1 19 19 15 15 15 15 R5 61 15 15 15 19 19 19 19 R6 11 26 26 26 26 26 26 26 R7 59 59 59 59 59 48 37 37 R8 15 61 61 61 61 37 48 48 R9 48 48 48 48 48 59 59 59 R10 19 37 37 37 37 61 61 61 left 1 1 1 4 7 7 10 right 10 5 2 5 10 8 10
input file: 10 records
- (26,5,37,1,61,11,59,15,48,19)
time complexity
- average case: O(n·log2n) split into “equal size”
T(n): average time to sort n records T(n) <= c·n + 2·T(n/2) <= c·n + 2(c·n/2 + 2·T(n/4)) <= 2·c·n + 4·T(n/4) ··· <= log2n·c·n + n·T(1) = O(n·log2n)
- worst case: O(n2)
Quick Sort
Merge Sort
Use divide and conquer method
divide
divide
divide
combine
int rmerge(element list[ ], int lower, int upper){
int middle;
if (lower >= upper)
return lower;
else {
middle =(lower+upper)/2;
return listmerge(list, rmerge(list, lower,
middle), rmerge(list, middle+1, upper);
}
}
/* rmerge returns the index of the first
element in the sorted chain */
Merging two ordered lists
2 5 7 8 1 3 4 6 1 2 5 7 8 3 4 6 1 2 5 7 8 3 4 6 1 2 3 5 7 8 4 6 1 2 3 4 5 7 8 6 1 2 3 4 5 7 8 6 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8Merge Sort
Need additional space for the merge step
Complexity: O(nlogn)
If linked list is used for merging,
Heap Sort
utilize the max heap structure
- implement max heap by using array
time complexity
- average case : O(n·log
2n)
- worst case : O(n·log
2n)
Heap Sort
• Construct a max heap with n records - program 7.12 adjust
* takes a binary tree T whose left and right subtrees satisfy the heap property but
whose root may not
* adjusts T so that the entire binary tree satisfies the heap property
• Exchange the first record in the heap with the last record
• Decrement the heap size and readjust the heap • Repeat n-1 passes
program 7.12
• adjust the binary tree to establish the heap
- time: O(d) where d: depth of tree
1 48 5 61 15 19 1 48 61 5 15 19 1 48 61 15 5 19
adjust
void adjust(element a[ ], int root, int n) { int child, rootkey;
element temp = a[root]; rootkey = a[root].key;
child = 2*root; /* left child */ while (child <= n){
if ( (child <n) && (a[child].key < a[child+1].key) ) child++;
if (rootkey > a[child].key) break;
else { a[child/2] = a[child]; child *=2; } }
a[child/2] = temp;
Heap Sort
void heapsort(element a[ ], int n) {
int i, j;
element temp;
for (i = n / 2; i > 0; i--)
/* initial heap construction */
adjust(a, i, n);
for (i = n - 1; i > 0; i--) { /* heap adjust */
SWAP(a[1], a[i+1], temp);
adjust(a, 1, i);
}
Complexity of heap sort
for the first for loop : O(n)
Let the height of the tree be k
2
k-1<= n < 2
k
for the second for loop : O(n·log
2n)
Worst and average time complexity:
O(n·log
2n)
1 1 1 1 1 1 1 12
(
)
2
2
)
(
2
k j j k j j k k i ik
i
j
n
j
n
O
n
Example of Heap sorting process
- input list
(26,5,77,1,61,11,59,15,48,19)
array interpreted as a binary tree
48 1 5 61 11 26 59 77 15 19 [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] 26 5 77 1 61 11 59 15 48 19 [1] [2] [3] [4] [5] [6] [7] [8] [9] [10]