Advertisement
nlw

Quicksort and variations

nlw
Sep 30th, 2012
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.99 KB | None | 0 0
  1. // Demosntration of a few sorting algorithms
  2. // by Nicolau Werneck<nwerneck@gmail.com>, Sept. 2012
  3.  
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <math.h>
  7. #include <sys/times.h>
  8.  
  9. void print_array(unsigned int* arr, unsigned int size) {
  10.   unsigned int k;
  11.   for (k=0; k<size; k++) {
  12.     printf("%05u %16u\n", k, arr[k]);
  13.   }
  14. }
  15.  
  16. void fill_array(unsigned int* arr, unsigned int size, unsigned int bits) {
  17.   unsigned int k;
  18.   for(k = 0; k < size; k++)
  19.     arr[k] = rand() % (1<<(bits)) ;
  20. }
  21.  
  22. unsigned int* insertion_sort(unsigned int* arr, unsigned int size) {
  23.   if (size <= 1)
  24.     return;
  25.  
  26.   unsigned int p, q;
  27.   unsigned int tmp;
  28.  
  29.   for(p=1; p<size; p++) {
  30.     if (arr[p-1] <= arr[p])
  31.       continue;
  32.     for(q=p; (q > 0) && !(arr[q-1] <= arr[q]); q--) {
  33.       tmp = arr[q];
  34.       arr[q] = arr[q-1];
  35.       arr[q-1] = tmp;
  36.     }
  37.   }
  38. }
  39.  
  40. unsigned int* mixsort(unsigned int* arr, unsigned int size, unsigned int pivot) {
  41.  
  42.   // If the list size is small, just run insertion sort and get done with it.
  43.   if (size <= 8){
  44.     return insertion_sort(arr, size);
  45.   }
  46.  
  47.   // Just for safety really.
  48.   if (pivot == 0){
  49.     return;
  50.   }
  51.  
  52.   unsigned int k; // Loop variable
  53.   unsigned int tmp; // Temp variable to switch values
  54.  
  55.   // This variable points to the first item that is larger or equal
  56.   // than the pivot.
  57.   unsigned int sep;
  58.  
  59.   // Look for the first item that is larger or equal than the pivot.
  60.   for (k = 0; k < size && !(arr[k] & pivot); k++);
  61.   sep = k;
  62.  
  63.   // Now iterate through the remaining list items, and move the
  64.   // smaller ones to the first half of the list.
  65.   for (; k < size; k++) {
  66.     // If the current item is smaller than the pivot,
  67.     if (!(arr[k] & pivot)) {
  68.       // switch the current small value with head of second half
  69.       tmp = arr[sep];
  70.       arr[sep] = arr[k];
  71.       arr[k] = tmp;
  72.       // and increment head of the second half.
  73.       sep++;
  74.     }
  75.   }
  76.  
  77.   // Make the recursive calls for the two sublists, and the next less
  78.   // significant bit.
  79.   mixsort(arr, sep, pivot >> 1);
  80.   mixsort(arr+sep, size-sep, pivot >> 1);
  81. }
  82.  
  83. unsigned int* mixquicksort(unsigned int* arr, unsigned int size) {
  84.  
  85.   // If the list size is small, just run insertion sort and get done with it.
  86.   if (size <= 8){
  87.     return insertion_sort(arr, size);
  88.   }
  89.  
  90.   unsigned int k; // Loop variable
  91.   unsigned int tmp; // Temp variable to switch values
  92.  
  93.   // Select item to be the pivot using the median from 3 values.
  94.   unsigned int piv = 0;
  95.  
  96.   if (arr[0] < arr[size/2] && arr[size/2] < arr[size-1] || \
  97.       arr[size-1] < arr[size/2] && arr[size/2] < arr[0]) {
  98.   }
  99.   else if (arr[size/2] < arr[size-1] && arr[size-1] < arr[0] || \
  100.        arr[0] < arr[size-1] && arr[size-1] < arr[size/2]) {
  101.   }
  102.   else {
  103.     piv = 0;
  104.   }
  105.   unsigned int pivot = arr[piv];
  106.  
  107.   // This variable points to the first item that is larger or equal
  108.   // than the pivot.
  109.   unsigned int sep;
  110.  
  111.   // Switch pivot with last list item.
  112.   tmp = arr[size-1];
  113.   arr[size-1] = arr[piv];
  114.   arr[piv] = tmp;
  115.  
  116.   // Look for the first item that is larger or equal than the pivot.
  117.   for (k = 0; (k < size) && (arr[k] < pivot); k++);
  118.   sep = k;
  119.  
  120.   // Now iterate through the remaining list items, and move the
  121.   // smaller ones to the first half of the list.
  122.   for (; k < size; k++) {
  123.     // If the current item is smaller than the pivot,
  124.     if (arr[k] < pivot) {
  125.       // switch the current small value with head of second half
  126.       tmp = arr[sep];
  127.       arr[sep] = arr[k];
  128.       arr[k] = tmp;
  129.       // and increment head of the second half.
  130.       sep++;
  131.     }
  132.   }
  133.  
  134.   // Switch last item (pivot) with first.
  135.   tmp = arr[size-1];
  136.   arr[size-1] = arr[sep];
  137.   arr[sep] = tmp;
  138.  
  139.   // Make the recursive calls for the two sublists, and the next less
  140.   // significant bit.
  141.   mixquicksort(arr, sep);
  142.   mixquicksort(arr+sep+1, size-sep-1);
  143. }
  144.  
  145.  
  146.  
  147. unsigned int* radixsort(unsigned int* arr, unsigned int size, unsigned int pivot) {
  148.  
  149.   // Return if there are no more bits to test or if the list is empty.
  150.   if (pivot == 0 || size <= 1){
  151.     return;
  152.   }
  153.  
  154.   unsigned int k; // Loop variable
  155.   unsigned int tmp; // Temp variable to switch values
  156.  
  157.   // This variable points to the first item that is larger or equal
  158.   // than the pivot.
  159.   unsigned int sep;
  160.  
  161.   // Look for the first item that is larger or equal than the pivot.
  162.   for (k = 0; k < size && !(arr[k] & pivot); k++);
  163.   sep = k;
  164.  
  165.   // Now iterate through the remaining list items, and move the
  166.   // smaller ones to the first half of the list.
  167.   for (; k < size; k++) {
  168.     // If the current item is smaller than the pivot,
  169.     if (!(arr[k] & pivot)) {
  170.       // switch the current small value with head of second half
  171.       tmp = arr[sep];
  172.       arr[sep] = arr[k];
  173.       arr[k] = tmp;
  174.       // and increment head of the second half.
  175.       sep++;
  176.     }
  177.   }
  178.  
  179.   // Make the recursive calls for the two sublists, and the next less
  180.   // significant bit.
  181.   radixsort(arr, sep, pivot >> 1);
  182.   radixsort(arr+sep, size-sep, pivot >> 1);
  183. }
  184.  
  185. unsigned int* quicksort(unsigned int* arr, unsigned int size) {
  186.  
  187.   // Return if there are no more bits to test or if the list is empty.
  188.   if (size <= 1){
  189.     return;
  190.   }
  191.  
  192.   unsigned int k; // Loop variable
  193.   unsigned int tmp; // Temp variable to switch values
  194.  
  195.   // Select item to be the pivot using the median from 3 values.
  196.   unsigned int piv = 0;
  197.  
  198.   if (arr[0] < arr[size/2] && arr[size/2] < arr[size-1] || \
  199.       arr[size-1] < arr[size/2] && arr[size/2] < arr[0]) {
  200.   }
  201.   else if (arr[size/2] < arr[size-1] && arr[size-1] < arr[0] || \
  202.        arr[0] < arr[size-1] && arr[size-1] < arr[size/2]) {
  203.   }
  204.   else {
  205.     piv = 0;
  206.   }
  207.   unsigned int pivot = arr[piv];
  208.  
  209.   // This variable points to the first item that is larger or equal
  210.   // than the pivot.
  211.   unsigned int sep;
  212.  
  213.   // Switch pivot with last list item.
  214.   tmp = arr[size-1];
  215.   arr[size-1] = arr[piv];
  216.   arr[piv] = tmp;
  217.  
  218.   // Look for the first item that is larger or equal than the pivot.
  219.   for (k = 0; (k < size) && (arr[k] < pivot); k++);
  220.   sep = k;
  221.  
  222.   // Now iterate through the remaining list items, and move the
  223.   // smaller ones to the first half of the list.
  224.   for (; k < size; k++) {
  225.     // If the current item is smaller than the pivot,
  226.     if (arr[k] < pivot) {
  227.       // switch the current small value with head of second half
  228.       tmp = arr[sep];
  229.       arr[sep] = arr[k];
  230.       arr[k] = tmp;
  231.       // and increment head of the second half.
  232.       sep++;
  233.     }
  234.   }
  235.  
  236.   // Switch last item (pivot) with first.
  237.   tmp = arr[size-1];
  238.   arr[size-1] = arr[sep];
  239.   arr[sep] = tmp;
  240.  
  241.   // Make the recursive calls for the two sublists, and the next less
  242.   // significant bit.
  243.   quicksort(arr, sep);
  244.   quicksort(arr+sep+1, size-sep-1);
  245. }
  246.  
  247. int main(int argc, char* argv[]) {
  248.  
  249.   // Return if there is no argument.
  250.   if (argc < 5) {
  251.     return 1;
  252.   }
  253.  
  254.   // Select algorithm to use.
  255.   char func = argv[1][0];
  256.  
  257.   // Read word size from input argument.
  258.   int bits = atoi(argv[2]);
  259.  
  260.   // Read array size from input argument.
  261.   int size = atoi(argv[3]);
  262.  
  263.   // Read number of iterations from input argument.
  264.   int iters = atoi(argv[4]);
  265.  
  266.   // Return if conversion of arguments was not successful.
  267.   if (size == 0 || bits == 0 || bits > 31) {
  268.     return 1;
  269.   }
  270.  
  271.   // Allocate memory for the array to be sorted
  272.   unsigned int* arr = (unsigned int*) malloc(sizeof(int)*size);
  273.  
  274.   // Initialize random generator from current time.
  275.   srand ( time(NULL) );
  276.  
  277.   //////////////////////////////////////////////////////////////////////////
  278.   // Where the real action begins.  
  279.   //
  280.  
  281.   // Stuff to measure time.
  282.   struct tms tta;
  283.   struct tms ttb;
  284.   times(&tta);
  285.  
  286.  
  287.   // If iters = 0 just run once and print stuff.
  288.   if (iters == 0) {
  289.  
  290.     // Initialize array.
  291.     fill_array(arr, size, bits);
  292.     print_array(arr, size);
  293.        
  294.     // Make the initial call to the sort procedure.
  295.     if (func=='q') {
  296.       quicksort(arr, size);
  297.     } else if (func=='r') {
  298.       radixsort(arr, size,  1 << (bits-1));
  299.     } else if (func=='i') {
  300.       insertion_sort(arr, size);
  301.     } else if (func=='m') {
  302.       mixsort(arr, size,  1 << (bits-1));
  303.     } else if (func=='n') {
  304.       mixquicksort(arr, size);
  305.     }
  306.  
  307.     printf("\nSorting...\n\n");
  308.  
  309.     print_array(arr, size);
  310.  
  311.     return 0;
  312.   }
  313.  
  314.  
  315.   // Re-fill array and run quicksort for the specified number of iterations.
  316.   int k;
  317.   for(k=0;k<iters;k++) {
  318.     // Initialize array.
  319.     fill_array(arr, size, bits);
  320.        
  321.     // Make the initial call to the sort procedure.
  322.     if (func=='q') {
  323.       quicksort(arr, size);
  324.     } else if (func=='r') {
  325.       radixsort(arr, size,  1 << (bits-1));
  326.     } else if (func=='i') {
  327.       insertion_sort(arr, size);
  328.     } else if (func=='m') {
  329.       mixsort(arr, size,  1 << (bits-1));
  330.     } else if (func=='n') {
  331.       mixquicksort(arr, size);
  332.     } else if (func=='0') {
  333.       continue;
  334.     }
  335.   }
  336.  
  337.   times(&ttb);
  338.   printf("%d %e\n", size, \
  339.      ((double) (ttb.tms_utime - tta.tms_utime)*.01/iters ));
  340.  
  341.   return 0;
  342. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement