Divide-and-Conquer Algorithm

advertisement
Divide-and-Conquer Algorithm
Divide-and-conquer approach used divide the big problem into two smaller problems and solve
each one separately. The solution to each smaller problem is the same: You divide it into two
even smaller problems and solve them. The process continues until you get to the base case,
which can be solved easily, with no further division into halves. The divide-and-conquer
approach is commonly used with recursion.
Quicksort
Quicksort is a fast sorting algorithm, which is used not only for educational purposes, but
widely applied in practice. On the average, it has O(n log n) complexity, making quicksort
suitable for sorting big data volumes. The idea of the algorithm is quite simple and once you
realize it. The Quicksort algorithm is based on a simple but clever idea:
 Given a list of items,
 Select any item from the list. This item is called the pivot.
 Move all the items that are smaller than the pivot to the beginning of the list, and move
all the items that are larger than the pivot to the end of the list.
 Now, put the pivot between the two groups of items. This puts the pivot in the position
that it will occupy in the final, completely sorted array. It will not have to be moved again.
Quicksort was discovered by C.A.R. Hoare in 1962.
The divide-and-conquer strategy is used in quicksort. Below the recursion steps are described:
1. Choose a pivot value. We take the value of the middle element as pivot value (or the first
item in the left, the last item in the right), but it can be any value, which is in range of sorted
values, even if it doesn't present in the array.
2. Partition. Rearrange elements in such a way, that all elements which are lesser than the
pivot go to the left part of the array and all elements greater than the pivot, go to the right
part of the array. Values equal to the pivot can stay in any part of the array. Notice that array
may be divided in non-equal parts.
3. Sort both parts. Apply quicksort algorithm recursively to the left and the right parts.
Partition Algorithm In Detail
There are two indices i and j, at the very beginning of the partition algorithm i points to the first
element in the array and j points to the last one. Then algorithm moves i forward, until an
element with value greater or equal to the pivot is found. Index j is moved backward, until
an element with value lesser or equal to the pivot is found. If i ≤ j then they are swapped and
i steps to the next position (i + 1), j steps to the previous one (j - 1). Algorithm stops, when i
become greater than j.
After partition, all values before i-th element are less or equal than the pivot and all values
after j-th element are greater or equal to the pivot.
35
As you can see, there are three basic steps:
1. Partition the array or subarray into left (smaller keys) and right (larger keys) groups.
2. Call Quicksort to sort the left group.
3. Call Quicksort again to sort the right group.
Quicksort Algorithm
Given an array of n elements (e.g., integers):
• If array only contains one element, return
• Else
– Pick one element to use as pivot.
– Partition elements into two sub-arrays:
• Elements less than or equal to pivot
• Elements greater than pivot
– Quicksort two sub-arrays
– Return results
The pseudo code of the algorithm is as follows:
To sort a[left...right]:
if left < right:
Partition a[left...right] such that:
all a[left...p-1] are less than a[p], and
all a[p+1...right] are >= a[p]
Quicksort a[left...p-1]
Quicksort a[p+1...right]
Terminate
A key step in the Quicksort algorithm is partitioning the array
– We choose some (any) number p in the array to use as a pivot
– We partition the array into three parts:
–
To partition a[left...right]:
Set p = a[left], l = left + 1, r = right;
while l < r, do
while l < right && a[l] < p { l = l + 1 }
while r > left && a[r] >= p { r = r – 1}
if l < r { swap a[l] and a[r] }
a[left] = a[r]; a[r] = p;
Terminate
To see what is going on, consider the example of the following array:
35
Pick Pivot Element
There are a number of ways to pick the pivot element. In this example, we will use the first
element in the array:
Partitioning Array
Given a pivot, partition the elements of the array such that the resulting array consists of:
1. One sub-array that contains elements >= pivot
2. Another sub-array that contains elements < pivot
The sub-arrays are stored in the original data array.
Partitioning loops through, swapping elements below/above pivot.
1. While data[too_big_index] <= data[pivot]
++too_big_index
2. While data[too_small_index] > data[pivot]
--too_small_index
3. If too_big_index < too_small_index
swap data[too_big_index] and data[too_small_index]
33
4. While too_small_index > too_big_index, go to 1.
1. While data[too_big_index] <= data[pivot]
++too_big_index
2. While data[too_small_index] > data[pivot]
--too_small_index
3. If too_big_index < too_small_index
swap data[too_big_index] and data[too_small_index]
4. While too_small_index > too_big_index, go to 1.
2. While data[too_small_index] > data[pivot]
--too_small_index
3. If too_big_index < too_small_index
swap data[too_big_index] and data[too_small_index]
35
4. While too_small_index > too_big_index, go to 1.
Return to step 1
Then step 2
Step 3
Step 4
Swap data[too_small_index] and data[pivot_index]
Partition Result
The next steps Apply Quicksort algorithm recursively to the left and the right parts.
35
Example
3 7 8 5 2 1 9 5 4
3 7 8 5 2 1 9 5 4
3 1 8 5 2 7 9 5 4
3 1 2 5 8 7 9 5 4
3 1 2 5 8 7 9 5 4
3 1 2 4 8 7 9 5 5
3 1 2
4
8 7 9 5 5
3 1 2
1 3 2
1 2 3
Radix Sort
The radix sort disassembles the key into digits and arranges the data items according to the value
of the digits. Amazingly, no comparisons are necessary.
Algorithm for the Radix Sort
We’ll discuss the radix sort in terms of normal base-10 arithmetic, which is easier to visualize.
However, an efficient implementation of the radix sort would use base-2 arithmetic to take
advantage of the computer’s speed in bit manipulation. We’ll look at the radix sort rather than
the similar but somewhat more complex radix-exchange sort. The word radix means the base of
a system of numbers. Ten is the radix of the decimal system and 2 is the radix of the binary
system. The sort involves examining each digit of the key separately, starting with the 1s (least
significant) digit.
1. All the data items are divided into 10 groups, according to the value of their 1s digit.
2. These 10 groups are then reassembled: All the keys ending with 0 go first, followed by all the
keys ending in 1, and so on up to 9. We’ll call these steps a sub-sort.
3. In the second sub-sort, all data is divided into 10 groups again, but this time according to the
value of their 10s digit. This must be done without changing the order of the previous sort. That
is, within each of the 10 groups, the ordering of the items remains the same as it was after step 2;
the sub-sorts must be stable.
35
4. Again the 10 groups are recombined, those with a 10s digit of 0 first, then those with a 10s
digit of 1, and so on up to 9.
5. This process is repeated for the remaining digits. If some keys have fewer digits than others,
their higher-order digits are considered to be 0.
Here’s an example, using seven data items, each with three digits. Leading zeros are shown for
clarity.
421 240 035 532 305 430 124 // unsorted array
(240 430) (421) (532) (124) (035 305) // sorted on 1s digit
(305) (421 124) (430 532 035) (240) // sorted on 10s digit
(035) (124) (240) (305) (421 430) (532) // sorted on 100s digit
035 124 240 305 421 430 532 // sorted array
The parentheses delineate the groups. Within each group the digits in the appropriate position are
the same. To convince yourself that this approach really works, try it on a piece of paper with
some numbers you make up.
The radix-sort algorithm sorts a sequence S of entries with keys that are pairs, by applying a
stable bucket-sort on the sequence twice; first using one component of the pair as the ordering
key and then using the second component. But which order is correct?
Example: Original, unsorted list:
170, 045, 075,090, 002, 024, 802, 066
The first counting pass starts on the least significant digit of each key, producing an array of
bucket sizes:
2 (bucket size for digits of 0: 170, 090)
2 (bucket size for digits of 2: 002, 802)
1 (bucket size for digits of 4: 024)
2 (bucket size for digits of 5: 045, 075)
1 (bucket size for digits of 6: 066)
A second counting pass on the next more significant digit of each key will produce an array of
bucket sizes:
2 (bucket size for digits of 0: 002, 802)
1 (bucket size for digits of 2: 024)
1 (bucket size for digits of 4: 045)
1 (bucket size for digits of 6: 066)
2 (bucket size for digits of 7: 170, 075)
1 (bucket size for digits of 9: 090)
A third and final counting pass on the most significant digit of each key will produce an array
of bucket sizes:
6 (bucket size for digits of 0: 002, 024, 045, 066, 075, 090)
1 (bucket size for digits of 1: 170)
1 (bucket size for digits of 8: 802)
35
Download