home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 2 / ctrom_ii_b.zip / ctrom_ii_b / C!T / C!T05_93 / CLAPET / CLAPET.C
C/C++ Source or Header  |  1993-01-12  |  10KB  |  362 lines

  1. // Demonstratieprogramma: Clapet-sort versus Quick-sort
  2. // Auteur: Koos Eenink te Apeldoorn
  3. // Januari 1993
  4.  
  5. // de sorteermethode: Clapet-sort, verwijder het comment voor
  6. // #define Q voor Quick-sorting
  7. //#define Q
  8.  
  9. // Instelbare parameters: ****************************************************
  10. //  de record-lengte,
  11. #define Key_Lengte   25
  12.  
  13. // optional print (naar scherm), verwijder comment voor scherm-print
  14. //#define PR
  15. // en formaat scherm-print
  16. #define Print_Formaat   "%-16s"
  17.  
  18. // Afgeleide instellingen: ***************************************************
  19. // als niet Quicksort, dan Clapetsort
  20. #ifndef Q
  21.     #define C
  22. #endif
  23.  
  24. // Record-lengte gekozen: 1 + key-lengte, record wordt zodoende automatisch
  25. // ASCIIZ formaat
  26. #define Record_Lengte      (Key_Lengte + 1)
  27.  
  28. // de lengte tabel met integers (indexen in buffer) en daarom ook het aantal
  29. // records, is gelimiteerd (64kBytes -> 32k records): afgerond op 1000-tal
  30.     #define MAX_AANTAL_RECORDS   32000
  31.  
  32. // eind ketting indicator:
  33.     #define LEEG    0xffff
  34.  
  35. // div. standaard-includes ***************************************************
  36. #include <stdio.h>
  37. #include <stdlib.h>
  38. #include <malloc.h>
  39. #include <string.h>
  40. #include <conio.h>
  41. #include <time.h>
  42. #include <dos.h>
  43.  
  44. unsigned char
  45.         *recbuf,                    // begin record-buffer
  46.         *record,                    // ptr naar actuele record
  47.         *rnd = (char *)0xf0000000;  // ptr naar ROM-programma voor 'randomizing'
  48.  
  49. // integers over pointers voor adres-calculatie, zie: zet_record_ptr()
  50. //
  51. //   <     pointer     >
  52. //   <integer> <integer>
  53. //  | offset  | segment |
  54. //
  55. unsigned int
  56.     *bufseg = (int *)(((char *) &recbuf) + 2),
  57.     *recseg = (int *)(((char *) &record) + 2),
  58.     *recofs = (int *)(((char *) &record));
  59. //
  60.  
  61. unsigned int
  62.         aantal_records = MAX_AANTAL_RECORDS,
  63.         *ketting;
  64. #define verwijzing  ketting
  65. // voor Clapetsort: volgnr volgende in ketting
  66. // voor Qsort: volgnr in buffer, zelfde array wordt gebruikt
  67.  
  68. unsigned long
  69.         tim,            // elapsed time
  70.         sizalloc;       // aantal bytes in buffer (probeer_start-waarde)
  71.  
  72. #ifdef C
  73. // de ankers:
  74. unsigned int
  75.         *anker_in,      // array: (256) ankers input sorteergang
  76.         *anker_uit,     // idem output sorteergang
  77.         anker1[256],    // 256 aflegvakken, afwisselend gebruikt voor in-
  78.         anker2[256];    //     en output (anker_in resp. anker_uit)
  79. #endif
  80.  
  81. // Prototypes
  82. void Quick_sort ( int left, int right);
  83. void Clapet_sort();
  84. long prtim(char * txt);
  85. void * zet_record_ptr(int x);
  86.  
  87. // ************************ Het hoofd-programma ******************************
  88. void main(int argc,char **argv)
  89. {
  90. unsigned int
  91.         u1,     // div. tellers
  92.         u2,
  93.         u3,
  94.         next;   // index in ketting
  95.  
  96. long    hulp_long_var;
  97.  
  98. unsigned char
  99.         hulp_char;
  100.  
  101. // met runtime parameter kan aantal_records (default 32000) overschreven
  102. // worden
  103.     if (argc == 2)
  104.         sscanf(argv[1],"%d",&aantal_records);
  105.  
  106. // geheugen-allocaties
  107.     ketting = (unsigned int *) halloc(aantal_records,sizeof (int));
  108.  
  109.     sizalloc=630000; // 1e probeer-waarde
  110.     while ((recbuf = (char *)halloc(sizalloc,1)) == NULL)
  111.         sizalloc -= 1000;
  112.     if ((sizalloc / Record_Lengte) <= aantal_records)
  113.         aantal_records = sizalloc / Record_Lengte;
  114.  
  115. // naar beneden afronden op duizendtal t.b.v. tijdregistratie:
  116.     if ((aantal_records = 1000 * (aantal_records / 1000)) == 0)
  117.         return;
  118.  
  119.     printf(
  120.             "\nlengte buffer in bytes :%ld"
  121.             "\naantal bytes gebruikt  :%ld"
  122.             "\naantal records         :%u"
  123.             "\nRecord_Lengte          :%d"
  124.             "\nKey_Lengte             :%d",
  125.         sizalloc,
  126.         ((long)aantal_records) * Record_Lengte,
  127.         aantal_records,
  128.         Record_Lengte,
  129.         Key_Lengte);
  130.  
  131. #ifdef Q
  132.     printf("\nsorteermethode         :Quick-sort");
  133. #else
  134.     printf("\nsorteermethode         :Clapet-sort");
  135. #endif
  136.  
  137. // initiele verwijzing (Qsort)
  138. #ifdef Q
  139. // n-de entry wijst naar n-de record
  140.     for (u1 = 0; u1 < aantal_records ; ++u1)
  141.         verwijzing[u1] = u1;
  142. #else
  143. // initiele ketting (Csort)
  144. // n-de entry wijst naar (n+1)-de record
  145.     for (u1 = 0; u1 < aantal_records - 1; ++u1)
  146.         ketting[u1] = u1 + 1;
  147. // laatste entry wijst naar niets
  148.     ketting[u1] = LEEG;
  149. #endif
  150.  
  151.     // vul records met "random" waarde
  152.     hulp_long_var = prtim("bezig met vullen van random-records");
  153.     for (u1=0; u1 < aantal_records; ++u1)
  154.     {
  155.         zet_record_ptr(u1);
  156.         for (u2 = 0; u2 < Key_Lengte; ++u2)
  157.         {
  158.             do
  159.                 hulp_long_var = 41 * hulp_long_var + 41 + rnd[u3++];
  160.             while ((hulp_char = (hulp_long_var >> 6) & 127) < 32);
  161.             record[u2] = hulp_char;
  162.         }
  163.     }
  164.     tim = prtim("start sorting");
  165.  
  166. #ifdef  Q
  167. // Quick sort + optionele print
  168.     Quick_sort(0,aantal_records - 1);
  169.     tim = prtim("end   sorting") - tim;
  170.     printf("    %3.2lf\n",tim/100.);
  171.  
  172. // het "ophalen" van de gesorteerde informatie voor verdere bewerking:
  173.   #ifdef PR
  174.     printf("    druk een toets\n");
  175.     getch();    // pauze om resultaten te bekijiken
  176.   #endif
  177.     for (u1 = 0;u1 < aantal_records; ++u1)
  178.     {
  179.         zet_record_ptr(verwijzing[u1]);
  180.  
  181.     // doe hier wat gedaan moet worden met de gesorteerde informatie
  182.     #ifdef PR
  183.         printf(Print_Formaat,record);
  184.     #endif
  185.  
  186.     }
  187.  
  188. #else
  189.  
  190. // Clapet sort + optionele print
  191.     Clapet_sort();
  192.     tim = prtim("end   sorting") - tim;
  193.     printf("    %3.2f\n",tim/100.);
  194.  
  195. // het "ophalen" van de gesorteerde informatie voor verdere bewerking:
  196.   #ifdef PR
  197.     printf("    druk een toets\n");
  198.     getch();    // pauze om resultaten te bekijiken
  199.   #endif
  200.     for (u1 = 0; u1 < 256; ++u1)
  201.     {
  202.         next = anker_uit[u1];
  203.         while (next != LEEG)
  204.         {
  205.             zet_record_ptr(next);
  206.  
  207.     // doe hier wat gedaan moet worden met de gesorteerde informatie
  208.     #ifdef PR
  209.             printf(Print_Formaat,record);
  210.     #endif
  211.  
  212.             next = ketting[next];
  213.         }
  214.     }
  215.  
  216. #endif
  217. }
  218.  
  219. #ifdef Q
  220. // swapping
  221. unsigned int
  222.     swap_help;
  223.  
  224. __inline void swap(unsigned int x,unsigned int y)
  225. {
  226. // swappen gebeurt eenvoudig door de inhoud van x-de en y-de entry in
  227. // de array: ketting (verwijzing) te verwisselen
  228. swap_help=verwijzing[x];
  229. verwijzing[x]=verwijzing[y];
  230. verwijzing[y]=swap_help;
  231. }
  232.  
  233. unsigned char
  234.         * auxrec;
  235.  
  236. void Quick_sort ( int left, int right)
  237. {
  238. int     i,
  239.         last;
  240.  
  241.     if (left >= right)
  242.         return;
  243.     i = (left + right) / 2;
  244.     swap(left,i);
  245.     last = left;
  246.     for(i = left + 1;i <= right; ++i)
  247.     {
  248.         auxrec = zet_record_ptr(verwijzing[i]);
  249.         zet_record_ptr(verwijzing[left]);
  250.         if (strncmp(auxrec,record,Key_Lengte) < 0)
  251.             swap(++last,i);
  252.     }
  253.     swap(left,last);
  254.     Quick_sort(left,last-1);
  255.     Quick_sort(last+1,right);
  256. }
  257.  
  258. #else   // Clapet
  259.  
  260. void Clapet_sort()
  261. {
  262. static  int anker_eind_ketting[256],
  263.                         // administratie laatste in aflegvakvak
  264.             *anker_swap_hulp,
  265.                         // voor swappen in- en output vakken
  266.             kolom,      // kolom in key
  267.             next,       // index volgende key
  268.             act_rec,    // actuele record, save-veld volgende key
  269.             i;          // teller
  270. static  unsigned char
  271.             ch;         // karakter uit key
  272.  
  273. // initial
  274.     // alloceer anker_in en anker_uit
  275.     anker_in = anker1;
  276.     anker_uit = anker2;
  277.  
  278.     // hang alles aan anker_uit[0],
  279.     // en anker_uit[1]..anker_uit[n] 'leegmaken'
  280.     anker_uit[0] = 0;
  281.     i = 1;
  282.     while( i < 256)
  283.         anker_uit[i++] = LEEG;
  284.  
  285.     kolom = Key_Lengte;
  286.  
  287.     // begin by laatste kolom (Key_lengte - 1 !) t/m kolom: 0 (eerste kolom)
  288.     while (kolom--)
  289.     {
  290.     // verwissel aflegvakken: gevulde vakken vorige slag worden nu input
  291.         anker_swap_hulp = anker_uit;
  292.         anker_uit = anker_in;
  293.         anker_in = anker_swap_hulp;
  294.  
  295.     // maak te vullen vakken leeg
  296.         for (i = 0; i < 256; ++i)
  297.             anker_uit[i] = LEEG;
  298.  
  299.     // ga door alle in vorige ronde gevulde vakken
  300.         for (i = 0; i < 256; ++i)
  301.         {
  302.             next = anker_in[i];     // start van de ketting
  303.             while (next != LEEG)    // doorloop ketting door char: i
  304.             {
  305.                 zet_record_ptr(next);
  306.                 if (anker_uit[ch = record[kolom]] == LEEG)
  307.                 // zet ketting start
  308.                     anker_uit[ch] = next;
  309.                 else
  310.                 // zet verwijzing in laatste record in ketting
  311.                 // NB. aflegvakken volgens FIFO-principe
  312.                     ketting[anker_eind_ketting[ch]] = next;
  313.  
  314.             // administreer positie laatste in ketting
  315.                 anker_eind_ketting[ch] = next;
  316.  
  317.             //  maak ketting in actuele record: LEEG
  318.                 act_rec = next;          // save verwijzing
  319.                 next = ketting[act_rec]; // haal volgende in ketting
  320.                 ketting[act_rec] = LEEG; // actuele record: laatste in ketting
  321.             }
  322.         }
  323.     }
  324. } // Clapet_sort-end
  325. #endif
  326.  
  327. // Print tijd en tekst en geef tijd in eenheden van 1/100 sec na middernacht
  328. long prtim(char * tekst)
  329. {
  330. unsigned char
  331.     hour,
  332.     min,
  333.     sec,
  334.     hndrd;
  335.  
  336. // haal tijd op via DOS-call
  337. _asm
  338.     {
  339.     mov ah,0x2c;
  340.     int 0x21;
  341.     mov hour,ch;
  342.     mov min,cl;
  343.     mov sec,dh;
  344.     mov hndrd,dl;
  345.     }
  346.  
  347. printf("\n %02d:%02d:%02d.%02d : %s",hour,min,sec,hndrd,tekst);
  348. return 360000 * hour + 6000L * min + 100*sec+hndrd;
  349. } // eind prtim()
  350.  
  351. unsigned long    zrp1;  // hulp-veld procedure: zet_record_ptr
  352. // transformeer volgnummer in buffer, in een adres: segment + offset
  353. // NB. bufferadres staat op paragraafadres: offset:0
  354. __inline void * zet_record_ptr(int n)
  355. {
  356.     zrp1 = (long) n * Record_Lengte;
  357.     *recofs = (unsigned int)(zrp1 & 0x00000fff);
  358.     *recseg = (unsigned int)(*bufseg + (unsigned int) ((zrp1 & 0xfffff000) >> 4));
  359.     return record;
  360. }
  361.  
  362.