CSCE 221 Chapter 10
« previous | Tuesday, March 8, 2011 | next »
Divide and Conquer (D&C)
(See wikipedia:Master Theorem→)
Recurrence Relation
- represents the time to solve a problem of size
- can be separated into several subproblems if divided unequally (e.g. )
- represents the number of subproblems that we'll have to recurse over
- represents the size of subproblems we'll recurse over
- represents the time to partition into subproblems
- represents the time to combine subproblem solutions to get a total solution
(not in chapter)
Example
Multiply two -bit integers:
- Divide: split I and J into high- and low- order bits
- Multiply parts and adding:
- Recurrence Relation:
Merge Sort D&C
- Divide: divide into and
- Recurse: divide and recursively until base case is of size 0 or 1
- Conquer: combine solutions of and
Algorithm mergeSort(Sequence S,Comparator c) {
if (S.size() > 1) {
(S_1, S_2) = partition(S, n/2);
mergeSort(S_1);
mergeSort(S_2);
S := merge(S_1,S_2);
}
}
Algorithm merge(Sequence A, Sequence B) {
S = Sequence();
while (!A.isEmpty() && !B.isEmpty()) {
if (A.first().element() < B.first().element()) {
S.insertLast(A.remove(A.first()));
} else {
S.insertLast(B.remove(B.first()));
}
}
while (!A.isEmpty()) {
S.insertLast(A.remove(A.first()));
}
while (!B.isEmpty()) {
S.insertLast(B.remove(B.first()));
}
return S;
}
Analysis
Depth | # Sequences | Size of each Sequence |
---|---|---|
0 | 1 | |
1 | 2 | |
2 | 4 | |
… | … | … |
The merge() algorithm takes time, where is the size of and .
Time function recurrence relation:
- forms a binary tree of height , where an function is called at each level. Therefore .
Brute force analysis:
Therefore, merge sort is
Parallel Algorithm
D&C is very useful for parallel processing:
Quick Sort
Thursday, March 10, 2011
- Divide: Pick a random element called a pivot and partition into elements less than , elements equal to , and elements greater than .
- Recur: Sort and
- Conquer: Combine/join , , and .
Algorithm partition(Sequence S, Position p) {
Sequence L, E, G;
x = S.remove(p);
while (!S.isEmpty()) {
y = S.remove(S.first());
if (y < x) L.insertLast(y);
else if (y == x) E.insertLast(y);
else G.insertLast(y);
}
// sort L, E, and G
return merge(L, E, G);
}
Analysis
Best Case (we pick the middle element every time; ):
Worst Case (we pick smallest or largest element every time):
Summary of Comparison-based Algorithms
Algorithm | Time | Notes |
---|---|---|
selection-sort | in-place, slow (good for small inputs) | |
insertion sort | in-place, slow (good for small inputs) | |
quick-sort | in-place, randomized, fastest (good for large inputs) | |
heap-sort | in-place, fast (good for large inputs) | |
merge-sort | sequential data access, fast (good for large inputs) |
Bucket-Sort
Not comparison-based and uns in linear time.
Input: A sequence of key/value paired items with key range 0-9 (inclusive).
Lexicographic sort (sort by key, then by item)
- Create a bucket array of size 10 (chained array like what was used for dictionaries)
- Stick items in their buckets depending on key element
- pull items out of bucket (don't worry about arranging by value element)
In General:
- Keys range from [0, N−1]
- Create a bucket array of size
- Phase 1: Empty the sequence by moving each item into its bucket
- Phase 2: For i=0..N-1, move the items to the end of the sequence
def bucketSort s, n
b = Array.new(n)
while !s.isEmpty do
f = s.first
(k,o) = s.remove f
B[k].insertLast (k,o)
end
for 0.upto(N-1) do |i|
while !B[i].isEmpty do
f = B[i].first
(k,o) = B[i].remove f
s.insertLast (k,o)
end
end
end
In order to sort lexicographically, we bucket-sort based on the last element in the tuple, then bucket sort in reverse up to the 1st tuple element. The reason this works is because bucket-sort is stable
Example
Sort (3,3) (1,5) (2,5) (1,2) (2,3) (1,7) (3,2) (2,2):
- bucket-sort by 2nd: (1,2) (3,2) (2,2) (3,3) (2,3) (1,5) (2,5) (1,7)
- bucket-sort by 1st: (1,2) (1,5) (1,7) (2,2) (2,3) (2,5) (3,2) (3,3)
Radix Sort
- Break an integer into digit tuples:
- e.g. 746 → (7,4,6); 10 → (0,1,0)
- Perform bucket-sort on the ones place, tens place, hundreds place, etc.
- et voila!
def radixSort s, n
# s is a sequence of d-tuples such that each place in the tuple is between 0 and n-1
for d.downto(1) do |i|
# set key k of each item of s to i-th dimension x_i
bucketSort(s,n)
end
end
Runs in time, where is the number of "digits" (thus number of iterations), is the number of items to sort, and is the number of buckets.
Example
In computers, we use binary numbers:
- Bits can be 0 or 1
- We can look at many bits. We'll call this number (i.e. : 00, 01, 10, 11)
- , where is the number of bits in an integer.
Now the running time is . The best value to choose for would be one that balances and somehow.
Thursday, March 24, 2011
Balance and for -bit binary integers:
Selection
Tuesday, March 29, 2011
Choose the smallest element from an array (also called order statistics):
- Minimum: — 1st order statistic
- Maximum: — nth order statistic
- Median:
Naïve solution: sort and select th item.
Linear Looking
Algorithm minimum(A) { m = A[1]; for i in 2..n { M = min(m, A[i]); } return m; }
Runs in time. (no better)
If we want to find the th smallest element, we have to perform k scans, so
Quick-select
Randomized selection algorithm based on "prune-and-search" paradigm (similar to D&Q)
Prune: pick a pivot element x and partition S into subsets less, equal, and greater.
Search: Depending on , answer must be in only one of those subsets. Recurse on that half only
def partition S, p
# input: Sequence (S) position (p) of pivot
# output: three subsequences based on pivot value: L (less than), E (equal to), and G (greater than)
l = e = g = Sequence.new
x = s.remove(p)
while !s.isEmpty? do
y = s.remove(s.first)
if y < x do
l.insertLast(y)
else if y == x do
e.insertLast(y)
else do
g.insertLast(y)
end
end
return l,e,g
end
Runs in Best and Average; Worst case.
Deterministic Selection
(See wikipedia:Selection algorithm#Linear general selection algorithm - Median of Medians algorithm→)
Solves in worst-case
Idea: recursively use the selection algorithm itself to find a good pivot for quick-select:
- Divide into sets of 5 each
- Find a median in each set.
- Create a sequence of all the medians of the chunks-of-five
- Recursively call this algorithm on the sequence of medians.
Analysis
columns, bigger/smaller than Median of Medians (MoM)
elements bigger/smaller than MoM.