| [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 | } | 
|---|