Algorithms and Data Structures
Algorithms and Data Structures
Algorithms and Data Structures
Create successful ePaper yourself
Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.
N.Wirth. <strong>Algorithms</strong> <strong>and</strong> <strong>Data</strong> <strong>Structures</strong>. Oberon version 64<br />
Analysis of Heapsort. At first sight it is not evident that this method of sorting provides good results.<br />
After all, the large items are first sifted to the left before finally being deposited at the far right. Indeed, the<br />
procedure is not recommended for small numbers of items, such as shown in the example. However, for<br />
large n, Heapsort is very efficient, <strong>and</strong> the larger n is, the better it becomes — even compared to Shellsort.<br />
In the worst case, there are n/2 sift steps necessary, sifting items through log(n/2), log(n/2+1), ... ,<br />
log(n-1) positions, where the logarithm (to the base 2) is truncated to the next lower integer.<br />
Subsequently, the sorting phase takes n-1 sifts, with at most log(n-1), log(n-2), ..., 1 moves. In<br />
addition, there are n-1 moves for stashing the item from the top away at the right. This argument shows<br />
that Heapsort takes of the order of n × log(n) moves even in the worst possible case. This excellent<br />
worst-case performance is one of the strongest qualities of Heapsort.<br />
It is not at all clear in which case the worst (or the best) performance can be expected. But generally<br />
Heapsort seems to like initial sequences in which the items are more or less sorted in the inverse order, <strong>and</strong><br />
therefore it displays an unnatural behavior. The heap creation phase requires zero moves if the inverse<br />
order is present. The average number of moves is approximately n/2 × log(n), <strong>and</strong> the deviations from this<br />
value are relatively small.<br />
2.3.3 Partition Sort<br />
After having discussed two advanced sorting methods based on the principles of insertion <strong>and</strong> selection,<br />
we introduce a third improved method based on the principle of exchange. In view of the fact that<br />
Bubblesort was on the average the least effective of the three straight sorting algorithms, a relatively<br />
significant improvement factor should be expected. Still, it comes as a surprise that the improvement based<br />
on exchanges to be discussed subsequently yields the best sorting method on arrays known so far. Its<br />
performance is so spectacular that its inventor, C.A.R. Hoare, called it Quicksort [2.5 <strong>and</strong> 2.6].<br />
Quicksort is based on the recognition that exchanges should preferably be performed over large<br />
distances in order to be most effective. Assume that n items are given in reverse order of their keys. It is<br />
possible to sort them by performing only n/2 exchanges, first taking the leftmost <strong>and</strong> the rightmost <strong>and</strong><br />
gradually progressing inward from both sides. Naturally, this is possible only if we know that their order is<br />
exactly inverse. But something might still be learned from this example.<br />
Let us try the following algorithm: Pick any item at r<strong>and</strong>om (<strong>and</strong> call it x); scan the array from the left<br />
until an item a i > x is found <strong>and</strong> then scan from the right until an item a j < x is found. Now exchange the<br />
two items <strong>and</strong> continue this scan <strong>and</strong> swap process until the two scans meet somewhere in the middle of<br />
the array. The result is that the array is now partitioned into a left part with keys less than (or equal to) x,<br />
<strong>and</strong> a right part with keys greater than (or equal to) x. This partitioning process is now formulated in the<br />
form of a procedure. Note that the relations > <strong>and</strong> < have been replaced by ≥ <strong>and</strong> ≤, whose negations in<br />
the while clause are < <strong>and</strong> >. With this change x acts as a sentinel for both scans.<br />
PROCEDURE partition;<br />
VAR i, j: INTEGER; w, x: Item;<br />
BEGIN<br />
i := 0; j := n-1;<br />
select an item x at r<strong>and</strong>om;<br />
REPEAT<br />
WHILE a[i] < x DO i := i+1 END;<br />
WHILE x < a[j] DO j := j-1 END;<br />
IF i j<br />
END partition