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

Lecture10 Sorting

The document outlines various sorting algorithms, focusing primarily on Merge Sort, which utilizes a divide-and-conquer approach to sort data efficiently with a time complexity of O(n log n). It explains the process of merging sorted sequences and provides an execution example illustrating the recursive calls and merging steps. Additionally, it includes a comparison of sorting algorithms and a nonrecursive implementation of Merge Sort.

Uploaded by

Đức An Phạm
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views

Lecture10 Sorting

The document outlines various sorting algorithms, focusing primarily on Merge Sort, which utilizes a divide-and-conquer approach to sort data efficiently with a time complexity of O(n log n). It explains the process of merging sorted sequences and provides an execution example illustrating the recursive calls and merging steps. Additionally, it includes a comparison of sorting algorithms and a nonrecursive implementation of Merge Sort.

Uploaded by

Đức An Phạm
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 53

Data Structures and

Algorithms
"
Sorting!
Outline"
• Merge Sort!
• Quick Sort!
• Sorting Lower Bound!
• Bucket-Sort!
• Radix Sort!

Phạm Bảo Sơn DSA 2


Merge Sort"

7 2 ⏐ 9 4 → 2 4 7 9

7 ⏐ 2 → 2 7 9 ⏐ 4 → 4 9

7→7 2→2 9→9 4→4


Divide-and-Conquer"
• Divide-and conquer is a • Merge-sort is a sorting
general algorithm design algorithm based on the
paradigm:! divide-and-conquer
– Divide: divide the input data paradigm !
S in two disjoint subsets S1 • Like heap-sort!
and S2! – It uses a comparator!
– Recur: solve the – It has O(n log n) running
subproblems associated time!
with S1 and S2!
– Conquer: combine the • Unlike heap-sort!
solutions for S1 and S2 into a – It does not use an auxiliary
solution for S priority queue!
• The base case for the – It accesses data in a
recursion are subproblems sequential manner
(suitable to sort data on a
of size 0 or 1!
disk)!
Phạm Bảo Sơn DSA 4
Merge-Sort"
• Merge-sort on an input Algorithm mergeSort(S, C)
sequence S with n Input sequence S with n
elements consists of elements,
comparator C
three steps:!
Output sequence S sorted
– Divide: partition S into
according to C
two sequences S1 and S2
of about n/2 elements if S.size() > 1
each! (S1, S2) ← partition(S, n/2)
– Recur: recursively sort S1 mergeSort(S1, C)
and S2 mergeSort(S2, C)
– Conquer: merge S1 and S ← merge(S1, S2)
S2 into a unique sorted
sequence!

Phạm Bảo Sơn DSA 5


Merging Two Sorted
Sequences"
• The conquer step of Algorithm merge(A, B)
merge-sort consists Input sequences A and B with
of merging two n/2 elements each
sorted sequences A Output sorted sequence of A ∪ B
and B into a sorted
sequence S S ← empty sequence
containing the union while ¬A.isEmpty() ∧ ¬B.isEmpty()
of the elements of A if A.first().element() < B.first().element()
and B! S.insertLast(A.remove(A.first()))
• Merging two sorted else
sequences, each S.insertLast(B.remove(B.first()))
with n/2 elements while ¬A.isEmpty()
and implemented by S.insertLast(A.remove(A.first()))
means of a doubly while ¬B.isEmpty()
linked list, takes O(n) S.insertLast(B.remove(B.first()))
time! return S
Phạm Bảo Sơn DSA 6
Merge-Sort Tree"
• An execution of merge-sort is depicted by a binary tree!
– each node represents a recursive call of merge-sort and stores!
• unsorted sequence before the execution and its partition!
• sorted sequence at the end of the execution!
– the root is the initial call !
– the leaves are calls on subsequences of size 0 or 1!

7 2 ⏐ 9 4 → 2 4 7 9

7 ⏐ 2 → 2 7 9 ⏐ 4 → 4 9

7→7 2→2 9→9 4→4


Phạm Bảo Sơn DSA 7
Execution Example"
• Partition!
7 2 9 4 ⏐ 3 8 6 1 → 1 2 3 4 6 7 8 9

7 2 9 4 → 2 4 7 9 3 8 6 1 → 1 3 8 6

7 2 → 2 7 9 4 → 4 9 3 8 → 3 8 6 1 → 1 6

7→7 2→2 9→9 4→4 3→3 8→8 6→6 1→1


Phạm Bảo Sơn DSA 8
Execution Example (cont.)"
• Recursive call, partition!
7 2 9 4 ⏐ 3 8 6 1 → 1 2 3 4 6 7 8 9

7 2 ⏐ 9 4 → 2 4 7 9 3 8 6 1 → 1 3 8 6

7 2 → 2 7 9 4 → 4 9 3 8 → 3 8 6 1 → 1 6

7→7 2→2 9→9 4→4 3→3 8→8 6→6 1→1


Phạm Bảo Sơn DSA 9
Execution Example (cont.)"
• Recursive call, partition!
7 2 9 4 ⏐ 3 8 6 1 → 1 2 3 4 6 7 8 9

7 2 ⏐ 9 4 → 2 4 7 9 3 8 6 1 → 1 3 8 6

7 ⏐ 2 → 2 7 9 4 → 4 9 3 8 → 3 8 6 1 → 1 6

7→7 2→2 9→9 4→4 3→3 8→8 6→6 1→1


Phạm Bảo Sơn DSA 10
Execution Example (cont.)"
• Recursive call, base case!
7 2 9 4 ⏐ 3 8 6 1 → 1 2 3 4 6 7 8 9

7 2 ⏐ 9 4 → 2 4 7 9 3 8 6 1 → 1 3 8 6

7 ⏐ 2 → 2 7 9 4 → 4 9 3 8 → 3 8 6 1 → 1 6

7→7 2→2 9→9 4→4 3→3 8→8 6→6 1→1


Phạm Bảo Sơn DSA 11
Execution Example (cont.)"
• Recursive call, base case!
7 2 9 4 ⏐ 3 8 6 1 → 1 2 3 4 6 7 8 9

7 2 ⏐ 9 4 → 2 4 7 9 3 8 6 1 → 1 3 8 6

7 ⏐ 2 → 2 7 9 4 → 4 9 3 8 → 3 8 6 1 → 1 6

7→7 2→2 9→9 4→4 3→3 8→8 6→6 1→1


Phạm Bảo Sơn DSA 12
Execution Example (cont.)"
• Merge!
7 2 9 4 ⏐ 3 8 6 1 → 1 2 3 4 6 7 8 9

7 2 ⏐ 9 4 → 2 4 7 9 3 8 6 1 → 1 3 8 6

7 ⏐ 2 → 2 7 9 4 → 4 9 3 8 → 3 8 6 1 → 1 6

7→7 2→2 9→9 4→4 3→3 8→8 6→6 1→1


Phạm Bảo Sơn DSA 13
Execution Example (cont.)"
• Recursive call, …, base case, merge!
7 2 9 4 ⏐ 3 8 6 1 → 1 2 3 4 6 7 8 9

7 2 ⏐ 9 4 → 2 4 7 9 3 8 6 1 → 1 3 8 6

7 ⏐ 2 → 2 7 9 4 → 4 9 3 8 → 3 8 6 1 → 1 6

7→7 2→2 9→9 4→4 3→3 8→8 6→6 1→1


Phạm Bảo Sơn DSA 14
Execution Example (cont.)"
• Merge!
7 2 9 4 ⏐ 3 8 6 1 → 1 2 3 4 6 7 8 9

7 2 ⏐ 9 4 → 2 4 7 9 3 8 6 1 → 1 3 8 6

7 ⏐ 2 → 2 7 9 4 → 4 9 3 8 → 3 8 6 1 → 1 6

7→7 2→2 9→9 4→4 3→3 8→8 6→6 1→1


Phạm Bảo Sơn DSA 15
Execution Example (cont.)"
• Recursive call, …, merge, merge!
7 2 9 4 ⏐ 3 8 6 1 → 1 2 3 4 6 7 8 9

7 2 ⏐ 9 4 → 2 4 7 9 3 8 6 1 → 1 3 6 8

7 ⏐ 2 → 2 7 9 4 → 4 9 3 8 → 3 8 6 1 → 1 6

7→7 2→2 9→9 4→4 3→3 8→8 6→6 1→1


Phạm Bảo Sơn DSA 16
Execution Example (cont.)"
• Merge!
7 2 9 4 ⏐ 3 8 6 1 → 1 2 3 4 6 7 8 9

7 2 ⏐ 9 4 → 2 4 7 9 3 8 6 1 → 1 3 6 8

7 ⏐ 2 → 2 7 9 4 → 4 9 3 8 → 3 8 6 1 → 1 6

7→7 2→2 9→9 4→4 3→3 8→8 6→6 1→1


Phạm Bảo Sơn DSA 17
Analysis of Merge-Sort"
• The height h of the merge-sort tree is O(log n) !
– at each recursive call we divide in half the sequence,
• The overall amount or work done at the nodes of depth i is O(n) !
– we partition and merge 2i sequences of size n/2i !
– we make 2i+1 recursive calls!
• Thus, the total running time of merge-sort is O(n log n)

depth #seqs size


0 1 n

1 2 n/2

i 2i n/2i

… … …
Phạm Bảo Sơn DSA 18
Summary of Sorting Algorithms"
Algorithm Time Notes
! slow
selection-sort O(n2) ! in-place
! for small data sets (< 1K)
! slow
insertion-sort O(n2) ! in-place
! for small data sets (< 1K)
! fast
heap-sort O(n log n) ! in-place
! for large data sets (1K — 1M)
! fast
merge-sort O(n log n) ! sequential data access
! for huge data sets (> 1M)
Phạm Bảo Sơn DSA 19
Nonrecursive Merge-Sort"
public static void mergeSort(Object[] orig, Comparator c) { //
nonrecursive!
Object[] in = new Object[orig.length]; // make a new temporary array!
System.arraycopy(orig,0,in,0,in.length); // copy the input!
Object[] out = new Object[in.length]; // output array!
Object[] temp; // temp array reference used for swapping!
int n = in.length;!
for (int i=1; i < n; i*=2) { // each iteration sorts all length-2*i runs !
for (int j=0; j < n; j+=2*i) // each iteration merges two length-i pairs!
merge(in,out,c,j,i); // merge from in to out two length-i runs at j!
temp = in; in = out; out = temp; // swap arrays for next iteration!
}!
// the "in" array contains the sorted array, so re-copy it!
System.arraycopy(in,0,orig,0,in.length);!
}!
!

Phạm Bảo Sơn DSA 20


Nonrecursive Merge-Sort"
public static void mergeSort(Object[] orig, Comparator c) { // nonrecursive!
Object[] in = new Object[orig.length]; // make a new temporary array!
System.arraycopy(orig,0,in,0,in.length); // copy the input!
Object[] out = new Object[in.length]; // output array!
Object[] temp; // temp array reference used for swapping!
int n = in.length;!
merge runs of for (int i=1; i < n; i*=2) { // each iteration sorts all length-2*i runs !
for (int j=0; j < n; j+=2*i) // each iteration merges two length-i pairs!
length 2, then merge(in,out,c,j,i); // merge from in to out two length-i runs at j!
temp = in; in = out; out = temp; // swap arrays for next iteration!
4, then 8, and }!
// the "in" array contains the sorted array, so re-copy it!
so on System.arraycopy(in,0,orig,0,in.length);!
}!
protected static void merge(Object[] in, Object[] out, Comparator c, int start, !
int inc) { // merge in[start..start+inc-1] and in[start+inc..start+2*inc-1]!
int x = start; // index into run #1!
int end1 = Math.min(start+inc, in.length); // boundary for run #1!
int end2 = Math.min(start+2*inc, in.length); // boundary for run #2!
int y = start+inc; // index into run #2 (could be beyond array boundary)!
merge two runs int z = start; // index into the out array!
while ((x < end1) && (y < end2)) !
in the in array if (c.compare(in[x],in[y]) <= 0) out[z++] = in[x++];!
else out[z++] = in[y++];!
to the out array if (x < end1) // first run didn't finish!
System.arraycopy(in, x, out, z, end1 - x);!
else if (y < end2) // second run didn't finish!
System.arraycopy(in, y, out, z, end2 - y);!
Phạm Bảo Sơn DSA 21
}!
Quick-Sort"

7 4 9 6 2 → 2 4 6 7 9

4 2 → 2 4 7 9 → 7 9

2→2 9→9
Quick-Sort"
• Quick-sort is a
randomized sorting x
algorithm based on the
divide-and-conquer
paradigm:!
– Divide: pick a random x
element x (called pivot) and
partition S into !
• L elements less than x
L E G
• E elements equal x!
• G elements greater than x!
– Recur: sort L and G! x
– Conquer: join L, E and G
Phạm Bảo Sơn DSA 23
Partition"
• We partition an input Algorithm partition(S, p)
sequence as follows:! Input sequence S, position p of pivot
– We remove, in turn, each Output subsequences L, E, G of the
element y from S and ! elements of S less than, equal to,
or greater than the pivot, resp.
– We insert y into L, E or G, L, E, G ← empty sequences
depending on the result of
x ← S.remove(p)
the comparison with the
pivot x while ¬S.isEmpty()
y ← S.remove(S.first())
• Each insertion and removal if y < x
is at the beginning or at the L.insertLast(y)
end of a sequence, and else if y = x
hence takes O(1) time! E.insertLast(y)
• Thus, the partition step of else { y > x }
quick-sort takes O(n) time! G.insertLast(y)
return L, E, G
Phạm Bảo Sơn DSA 24
Quick-Sort Tree"
• An execution of quick-sort is depicted by a binary tree!
– Each node represents a recursive call of quick-sort and stores!
• Unsorted sequence before the execution and its pivot!
• Sorted sequence at the end of the execution!
– The root is the initial call !
– The leaves are calls on subsequences of size 0 or 1!

7 4 9 6 2 → 2 4 6 7 9

4 2 → 2 4 7 9 → 7 9

2→2 9→9
Phạm Bảo Sơn DSA 25
Execution Example"
• Pivot selection!
7 2 9 43 7 6 1 → 1 2 3 4 6 7 8 9

7 2 9 4 → 2 4 7 9 3 8 6 1 → 1 3 8 6

2→2 9 4 → 4 9 3→3 8→8

9→9 4→4
Phạm Bảo Sơn DSA 26
Execution Example (cont.)"
• Partition, recursive call, pivot selection!
7 2 9 4 3 7 6 1→ 1 2 3 4 6 7 8 9

2 4 3 1→ 2 4 7 9 3 8 6 1 → 1 3 8 6

2→2 9 4 → 4 9 3→3 8→8

9→9 4→4
Phạm Bảo Sơn DSA 27
Execution Example (cont.)"
• Partition, recursive call, base case!
7 2 9 43 7 6 1→→ 1 2 3 4 6 7 8 9

2 4 3 1 →→ 2 4 7 3 8 6 1 → 1 3 8 6

1→1 9 4 → 4 9 3→3 8→8

9→9 4→4
Phạm Bảo Sơn DSA 28
Execution Example (cont.)"
• Recursive call, …, base case, join!
7 2 9 43 7 6 1→ 1 2 3 4 6 7 8 9

2 4 3 1 → 1 2 3 4 3 8 6 1 → 1 3 8 6

1→1 4 3 → 3 4 3→3 8→8

9→9 4→4
Phạm Bảo Sơn DSA 29
Execution Example (cont.)"
• Recursive call, pivot selection!
7 2 9 43 7 6 1→ 1 2 3 4 6 7 8 9

2 4 3 1 → 1 2 3 4 7 9 7 1 → 1 3 8 6

1→1 4 3 → 3 4 8→8 9→9

9→9 4→4
Phạm Bảo Sơn DSA 30
Execution Example (cont.)"
• Partition, …, recursive call, base case!
7 2 9 43 7 6 1→ 1 2 3 4 6 7 8 9

2 4 3 1 → 1 2 3 4 7 9 7 1 → 1 3 8 6

1→1 4 3 → 3 4 8→8 9→9

9→9 4→4
Phạm Bảo Sơn DSA 31
Execution Example (cont.)"
• Join, join!
7 2 9 4 3 7 6 1 →1 2 3 4 6 7 7 9

2 4 3 1 → 1 2 3 4 7 9 7 → 17 7 9

1→1 4 3 → 3 4 8→8 9→9

9→9 4→4
Phạm Bảo Sơn DSA 32
Worst-case Running Time"
• The worst case for quick-sort occurs when the pivot is the unique
minimum or maximum element!
• One of L and G has size n - 1 and the other has size 0
• The running time is proportional to the sum!
n + (n - 1) + … + 2 + 1!
• Thus, the worst-case running time of quick-sort is O(n2)
depth time
0 n

1 n-1

… …

n-1 1
Phạm Bảo Sơn DSA 33
Expected Running Time"
• Consider a recursive call of quick-sort on a sequence of size s
– Good call: the sizes of L and G are each less than 3s/4
– Bad call: one of L and G has size greater than 3s/4
7 2 9 43 7 6 19 7 2 9 43 7 6 1

2 4 3 1 7 9 7 1 → 1 1 7294376

Good call Bad call

• A call is good with probability 1/2


– 1/2 of the possible pivots cause good calls:!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

Bad pivots Good pivots Bad pivots

Phạm Bảo Sơn DSA 34


Expected Running Time, Part 2"
• Probabilistic Fact: The expected number of coin tosses required in
order to get k heads is 2k
• For a node of with input size s, the input sizes of its children are
each at most s3/4 or s/(4/3).

! Therefore, we have expected height time per level


s(r) O(n)
n For a node of depth 2log4/3n, the
expected input size is one
n The expected height of the s(a) s(b) O(n)
quick-sort tree is O(log n)
O(log n)
! The amount or work done at the s(c) s(d) s(e) s(f) O(n)
nodes of the same depth is O(n)
! Thus, the expected running time
of quick-sort is O(n log n)
total expected time: O(n log n)
Phạm Bảo Sơn DSA 35
In-Place Quick-Sort"
• Quick-sort can be implemented
to run in-place!
• In the partition step, we use Algorithm inPlaceQuickSort(S, l, r)
replace operations to rearrange Input sequence S, ranks l and r
the elements of the input Output sequence S with the
sequence such that! elements of rank between l and r
rearranged in increasing order
– the elements less than the
pivot have rank less than h if l ≥ r
– the elements equal to the pivot return
have rank between h and k! i ← a random integer between l and r
– the elements greater than the x ← S.elemAtRank(i)
pivot have rank greater than k! (h, k) ← inPlacePartition(x)
• The recursive calls consider! inPlaceQuickSort(S, l, h - 1)
– elements with rank less than h inPlaceQuickSort(S, k + 1, r)
– elements with rank greater
than k
Phạm Bảo Sơn DSA 36
In-Place Partitioning"
• Perform the partition using two indices to split S into L and
E U G (a similar method can split E U G into E and G).!
j k
3 2 5 1 0 7 3 5 9 2 7 9 8 9 7 6 9 (pivot = 6)

• Repeat until j and k cross:!


– Scan j to the right until finding an element > x.!
– Scan k to the left until finding an element < x.!
– Swap elements at indices j and k!
j k
3 2 5 1 0 7 3 5 9 2 7 9 8 9 7 6 9

Phạm Bảo Sơn DSA 37


Summary of Sorting
Algorithms"
Algorithm Time Notes
! in-place
selection-sort O(n2) ! slow (good for small inputs)
! in-place
insertion-sort O(n2) ! slow (good for small inputs)

O(n log n) ! in-place, randomized


quick-sort ! fastest (good for large inputs)
expected
! in-place
heap-sort O(n log n) ! fast (good for large inputs)
! sequential data access
merge-sort O(n log n) ! fast (good for huge inputs)
Phạm Bảo Sơn DSA 38
Java Implementation"
public static void quickSort (Object[] S, Comparator c) {!
if (S.length < 2) return; // the array is already sorted in this case!
quickSortStep(S, c, 0, S.length-1); // recursive sort method!
}!
private static void quickSortStep (Object[] S, Comparator c,!
int leftBound, int rightBound ) {!
if (leftBound >= rightBound) return; // the indices have crossed!
Object temp; // temp object used for swapping!
Object pivot = S[rightBound];!
int leftIndex = leftBound; // will scan rightward!
int rightIndex = rightBound-1; // will scan leftward!
while (leftIndex <= rightIndex) { // scan right until larger than the pivot!
only works while ( (leftIndex <= rightIndex) && (c.compare(S[leftIndex], pivot)<=0) )!
leftIndex++; !
for distinct // scan leftward to find an element smaller than the pivot!
while ( (rightIndex >= leftIndex) && (c.compare(S[rightIndex], pivot)>=0))!
elements rightIndex--;!
if (leftIndex < rightIndex) { // both elements were found!
temp = S[rightIndex]; !
!S[rightIndex] = S[leftIndex]; // swap these elements!
!S[leftIndex] = temp;!
}!
} // the loop continues until the indices cross!
temp = S[rightBound]; // swap pivot with the element at leftIndex!
S[rightBound] = S[leftIndex]; !
S[leftIndex] = temp; // the pivot is now at leftIndex, so recurse!
quickSortStep(S, c, leftBound, leftIndex-1);!
quickSortStep(S, c, leftIndex+1, rightBound);!
Phạm Bảo Sơn DSA}! 39
Sorting Lower Bound"
Comparison-Based
Sorting"
• Many sorting algorithms are comparison based.!
– They sort by making comparisons between pairs of objects!
– Examples: bubble-sort, selection-sort, insertion-sort, heap-sort,
merge-sort, quick-sort, ...!
• Let us therefore derive a lower bound on the running
time of any algorithm that uses comparisons to sort n
elements, x1, x2, …, xn.!

no
Is xi < xj?

yes
Phạm Bảo Sơn DSA 41
Counting Comparisons"
• Let us just count comparisons then.!
• Each possible run of the algorithm
corresponds to a root-to-leaf path in a
decision tree! xi < xj ?

xa < xb ? xc < xd ?

xe < xf ? xk < xl ? x m < xo ? xp < xq ?

Phạm Bảo Sơn DSA 42


Decision Tree Height"
• The height of this decision tree is a lower bound on the running time!
• Every possible input permutation must lead to a separate leaf output. !
– If not, some input …4…5… would have same output ordering as …
5…4…, which would be wrong.!
• Since there are n!=1*2*…*n leaves, the height is at least log (n!)!
minimum height (time)
xi < x j ?

xa < xb ? xc < xd ?

log (n!)
xe < xf ? xk < xl ? xm < xo ? xp < xq ?

Phạm Bảo Sơn DSA n! 43


The Lower Bound"
• Any comparison-based sorting algorithms takes at
least log (n!) time!
• Therefore, any such algorithm takes time at least!
n
⎛ n ⎞
2
log (n!) ≥ log ⎜ ⎟ = (n / 2) log (n / 2).
⎝ 2 ⎠

• That is, any comparison-based sorting algorithm must


run in Ω(n log n) time.!

Phạm Bảo Sơn DSA 44


Bucket-Sort and Radix-Sort"

1, c 3, a 3, b 7, d 7, g 7, e

B ∅ ∅ ∅ ∅ ∅ ∅ ∅
0 1 2 3 4 5 6 7 8 9
Bucket-Sort"
• Let be S be a sequence of n Algorithm bucketSort(S, N)
(key, element) entries with keys Input sequence S of (key, element)
in the range [0, N - 1] items with keys in the range
• Bucket-sort uses the keys as [0, N - 1]
indices into an auxiliary array B Output sequence S sorted by
of sequences (buckets)! increasing keys
Phase 1: Empty sequence S by B ← array of N empty sequences
moving each entry (k, o) into its while ¬S.isEmpty()
bucket B[k] f ← S.first()
Phase 2: For i = 0, …, N - 1, move (k, o) ← S.remove(f)
the entries of bucket B[i] to the B[k].insertLast((k, o))
end of sequence S!
for i ← 0 to N - 1
• Analysis:! while ¬B[i].isEmpty()
– Phase 1 takes O(n) time! f ← B[i].first()
– Phase 2 takes O(n + N) time! (k, o) ← B[i].remove(f)
!Bucket-sort takes O(n + N) time! S.insertLast((k, o))
Phạm Bảo Sơn DSA 46
Example"
• Key range [0, 9]

7, d 1, c 3, a 7, g 3, b 7, e
Phase 1

1, c 3, a 3, b 7, d 7, g 7, e

B ∅ ∅ ∅ ∅ ∅ ∅ ∅
0 1 2 3 4 5 6 7 8 9
Phase 2

1, c 3, a 3, b 7, d 7, g 7, e
Phạm Bảo Sơn DSA 47
Properties and Extensions"
• Key-type Property! Extensions!
– The keys are used as – Integer keys in the range [a, b]!
indices into an array • Put entry (k, o) into bucket
and cannot be arbitrary B[k - a] !
objects! – String keys from a set D of
possible strings, where D has
– No external comparator! constant size (e.g., names of
• Stable Sort Property! the 50 U.S. states)!
• Sort D and compute the rank
– The relative order of r(k) of each string k of D in the
any two items with the sorted sequence !
same key is preserved • Put entry (k, o) into bucket
after the execution of B[r(k)]!
the algorithm!

Phạm Bảo Sơn DSA 48


Lexicographic Order"
• A d-tuple is a sequence of d keys (k1, k2, …, kd), where
key ki is said to be the i-th dimension of the tuple
• Example:!
– The Cartesian coordinates of a point in space are a 3-tuple!
• The lexicographic order of two d-tuples is recursively
defined as follows!
(x1, x2, …, xd) < (y1, y2, …, yd)

x1 < y1
∨ x1 = y1 ∧ (x2, …, xd) < (y2, …, yd)
I.e., the tuples are compared by the first dimension,
then by the second dimension, etc.!
Phạm Bảo Sơn DSA 49
Lexicographic-Sort"
• Let Ci be the comparator Algorithm lexicographicSort(S)
that compares two tuples by Input sequence S of d-tuples
their i-th dimension! Output sequence S sorted in
• Let stableSort(S, C) be a lexicographic order
stable sorting algorithm that
uses comparator C! for i ← d downto 1
• Lexicographic-sort sorts a stableSort(S, Ci)
sequence of d-tuples in
lexicographic order by
executing d times algorithm Example:
stableSort, one per (7,4,6) (5,1,5) (2,4,6) (2, 1, 4) (3, 2, 4)
dimension!
• Lexicographic-sort runs in (2, 1, 4) (3, 2, 4) (5,1,5) (7,4,6) (2,4,6)
O(dT(n)) time, where T(n) is
(2, 1, 4) (5,1,5) (3, 2, 4) (7,4,6) (2,4,6)
the running time of
stableSort (2, 1, 4) (2,4,6) (3, 2, 4) (5,1,5) (7,4,6)
Phạm Bảo Sơn DSA 50
Radix-Sort"
• Radix-sort is a
specialization of
lexicographic-sort that
uses bucket-sort as the
stable sorting algorithm
in each dimension! Algorithm radixSort(S, N)
• Radix-sort is applicable Input sequence S of d-tuples such
to tuples where the keys that (0, …, 0) ≤ (x1, …, xd) and
in each dimension i are (x1, …, xd) ≤ (N - 1, …, N - 1)
integers in the range [0, for each tuple (x1, …, xd) in S
N - 1] Output sequence S sorted in
lexicographic order
• Radix-sort runs in time for i ← d downto 1
O(d( n + N))
bucketSort(S, N)

Phạm Bảo Sơn DSA 51


Radix-Sort for
Binary Numbers"
• Consider a sequence of n
b-bit integers
!x = xb - 1 … x1x0!
• We represent each element Algorithm binaryRadixSort(S)
as a b-tuple of integers in Input sequence S of b-bit
integers
the range [0, 1] and apply Output sequence S sorted
radix-sort with N = 2 replace each element x
• This application of the of S with the item (0, x)
radix-sort algorithm runs in for i ← 0 to b - 1
O(bn) time ! replace the key k of
• For example, we can sort a each item (k, x) of S
with bit xi of x
sequence of 32-bit integers
bucketSort(S, 2)
in linear time!
Phạm Bảo Sơn DSA 52
Example"
• Sorting a sequence of 4-bit integers!

1001 0010 1001 1001 0001

0010 1110 1101 0001 0010

1101 1001 0001 0010 1001

0001 1101 0010 1101 1101

1110 0001 1110 1110 1110

Phạm Bảo Sơn DSA 53

You might also like