| [a0bcf1] | 1 | /** \file mergesort2.c
 | 
|---|
 | 2 |  * MergeSort implementation.
 | 
|---|
 | 3 |  * Unbeknownst that C already chooses the best algorithim according to the
 | 
|---|
 | 4 |  * problem at hand, a mergesort algorithm was implemented by naturalmergesort(),
 | 
|---|
 | 5 |  * which does the sorting, and merge() which joins two sorted pieces in an array
 | 
|---|
 | 6 |  * together.
 | 
|---|
 | 7 |  * 
 | 
|---|
 | 8 |    Project: CP
 | 
|---|
 | 9 |  \author  Jan Hamaekers
 | 
|---|
 | 10 |  \date  2000
 | 
|---|
 | 11 |    
 | 
|---|
 | 12 |    $Id: mergesort2.c,v 1.10 2006/12/05 18:11:16 foo Exp $
 | 
|---|
 | 13 | 
 | 
|---|
 | 14 |    File: mergesort2.c 
 | 
|---|
 | 15 |    Usage:
 | 
|---|
 | 16 |    Insert in your Code
 | 
|---|
 | 17 |    \verbatim
 | 
|---|
 | 18 |    #include"mergesort2.h"
 | 
|---|
 | 19 |    double GetKey(void *Element, int i) { }
 | 
|---|
 | 20 |    void CopyElement(void *Element, int i, void *Element, int j)
 | 
|---|
 | 21 |    \endverbatim   
 | 
|---|
 | 22 |    Use:
 | 
|---|
 | 23 |     naturalmergesort(a,b,l,r,&GetKey,&CopyElement)
 | 
|---|
 | 24 |      struct Element* a, *b   b als Puffer Speicher reservieren !!!
 | 
|---|
 | 25 |      int l,r
 | 
|---|
 | 26 | 
 | 
|---|
 | 27 | */
 | 
|---|
 | 28 | 
 | 
|---|
 | 29 | #include<stdlib.h>
 | 
|---|
 | 30 | #include "mergesort2.h"
 | 
|---|
 | 31 | 
 | 
|---|
 | 32 | /** Merge two sorted sequences a[l]-a[m] and a[m+1]-a[r] -> a[l]-a[r].
 | 
|---|
 | 33 |  * Goes in both sequences through all elements, at every one step comparing the two by GetKey
 | 
|---|
 | 34 |  * and copying the lower one. Eventually, the rest of the remaining sequence is copied (into
 | 
|---|
 | 35 |  * the dummyarray). And dummyarray back to original one.
 | 
|---|
 | 36 |  * \param *a  array containging both sequences that is to be sorted
 | 
|---|
 | 37 |  * \param l start of first sequence
 | 
|---|
 | 38 |  * \param m end of first sequence, also one before start of second sequence
 | 
|---|
 | 39 |  * \param r end of second sequence
 | 
|---|
 | 40 |  * \param *b dummyarray (used for copying hither and thither, size b = r-l+1)
 | 
|---|
 | 41 |  * \param (*GetKey)(void *, int i, void *) pointer to function that decides whether a[i] is "bigger" than a[j]
 | 
|---|
 | 42 |  * \param *Args additional arguments for *GetKey function, passed to it on calling
 | 
|---|
 | 43 |  * \param (*CopyElement)(void *, int i, void *, int j)  pointer to function, copying element b[j] to a[i]
 | 
|---|
 | 44 |  */
 | 
|---|
 | 45 | static void merge(void *a, int l, int m, int r, void *b, double (*GetKey)(void *, int i, void *), void *Args, void (*CopyElement)(void *, int i, void *, int j)) {
 | 
|---|
 | 46 |   int h,i=l,j=m+1,k=l;    // i,j start at their respective sequences
 | 
|---|
 | 47 |   while (i <= m && j <= r) { // elements are copied from both parts (a[l..m] and a[m+1..r]) in order into dummyarray b[l..r]
 | 
|---|
 | 48 |     if (GetKey(a,i,Args) <= GetKey(a,j,Args)) {
 | 
|---|
 | 49 |       CopyElement(b, k, a, i);
 | 
|---|
 | 50 |       i++;
 | 
|---|
 | 51 |     } else {
 | 
|---|
 | 52 |       CopyElement(b, k, a, j);
 | 
|---|
 | 53 |       j++;
 | 
|---|
 | 54 |     }
 | 
|---|
 | 55 |     k++;
 | 
|---|
 | 56 |   }
 | 
|---|
 | 57 |   if (i > m) {  // if in one of the sequences there yet remain some elements, copy them (simple for loop)
 | 
|---|
 | 58 |     for (h=j; h <=r;h++) CopyElement(b, k+h-j, a, h);
 | 
|---|
 | 59 |   } else {
 | 
|---|
 | 60 |     for (h=i; h <=m;h++) CopyElement(b, k+h-i, a, h);
 | 
|---|
 | 61 |   } // finally copy elements back to a
 | 
|---|
 | 62 |   for (h=l; h <= r; h++) CopyElement(a, h, b, h);
 | 
|---|
 | 63 | }
 | 
|---|
 | 64 | 
 | 
|---|
 | 65 | /** Mergesort an array /a a[l,-,r].
 | 
|---|
 | 66 |  * By a divide-and-conquer strategy an array is sorted: Seek first ordered sequence, mark, seek
 | 
|---|
 | 67 |  * from thereon second order sequence, mark, merge these, until end and then begin again until
 | 
|---|
 | 68 |  * sorted. Note, that thus already present ordered partial sequences are looked for and used.
 | 
|---|
 | 69 |  * \param *a array to be sorted  
 | 
|---|
 | 70 |  * \param l start of to-be-sorted sequence in /a a
 | 
|---|
 | 71 |  * \param r end of to-be-sorted sequence in /a a
 | 
|---|
 | 72 |  * \param *b  dummyarray (size  b = r-l+1)
 | 
|---|
 | 73 |  * \param (*GetKey)(void *, int i, void *) pointer to function that decides whether a[i] is "bigger" than a[j]
 | 
|---|
 | 74 |  * \param *Args additional arguments for *GetKey function, passed to it on calling
 | 
|---|
 | 75 |  * \param (*CopyElement)(void *, int i, void *, int j)  pointer to function, copying element b[j] to a[i]
 | 
|---|
 | 76 |  * \note Should be replaced by C's own qsort-routine, that's always optimal.
 | 
|---|
 | 77 |  * \sa merge()
 | 
|---|
 | 78 |  */
 | 
|---|
 | 79 | void naturalmergesort(void *a, void *b, int l, int r, double (*GetKey)(void *, int i, void *), void *Args, void (*CopyElement)(void *, int i, void *, int j)) {
 | 
|---|
 | 80 | /* C_min = O(N)
 | 
|---|
 | 81 |    C_max = O(N)
 | 
|---|
 | 82 |   */
 | 
|---|
 | 83 |   int ll=0, mm=0, rr=0;
 | 
|---|
 | 84 |   do {
 | 
|---|
 | 85 |     rr = l-1;
 | 
|---|
 | 86 |     while (rr < r) {
 | 
|---|
 | 87 |       ll = rr+1;
 | 
|---|
 | 88 |       mm = ll;
 | 
|---|
 | 89 |       while (mm < r && GetKey(a, mm+1, Args) >= GetKey(a, mm, Args)) mm++;  // mm is increased until a lower element is found
 | 
|---|
 | 90 |       if (mm < r) { // was whole sequence in order already?
 | 
|---|
 | 91 |         rr = mm+1; // mm
 | 
|---|
 | 92 |         while (rr<r && GetKey(a, rr+1, Args) >= GetKey(a, rr, Args)) rr++;  // from mm on rr is increased until a lower element is found
 | 
|---|
 | 93 |                 merge(a,ll,mm,rr,b,GetKey,Args,CopyElement); // merge these two ordered sequences: a[ll..mm], a[mm+1..rr]
 | 
|---|
 | 94 |       } else {  // ... we are finished!
 | 
|---|
 | 95 |         rr = mm;
 | 
|---|
 | 96 |       }
 | 
|---|
 | 97 |     }
 | 
|---|
 | 98 |   } while (ll != l);
 | 
|---|
 | 99 | }
 | 
|---|