Advertisement
zhukov000

sorting array

Feb 23rd, 2020
233
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.59 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <time.h>
  3. #include <stdlib.h>
  4. #include <assert.h>
  5.  
  6. #define MIN_LEN 100
  7. #define MAX_LEN 100000
  8.  
  9. // обмен значений
  10. void swap(int* a, int* b)
  11. {
  12.   int t = *a;
  13.   *a = *b;
  14.   *b = t;
  15. }
  16.  
  17. // получить случайное число из диапазона
  18. int get_random(int left, int right)
  19. {
  20.   int len = right - left + 1;
  21.   assert(len > 0); // длинна интервала должна быть больше нуля
  22.   int x = ((rand() << 15) + rand()) % len + left;
  23.   assert(left <= x && x <= right); // проверка, что число сгенерировано в заданном интервале
  24.   return x;
  25. }
  26.  
  27. // генерация случайного массива размера size
  28. int * get_random_array(int size)
  29. {
  30.   int * arr = calloc(size, sizeof(int));
  31.   for(int i=0; i<size; ++i)
  32.     arr[i] = get_random(-10000, 10000);
  33.   return arr;
  34. }
  35.  
  36. // сортировка выбором
  37. void selection_sort(int * a, int size)
  38. {
  39.   for (int i=0; i < size-1; ++i)
  40.   {
  41.     // выбор минимального
  42.     int mn = i;
  43.     for(int j=i+1; j<size; ++j)
  44.       if (a[j] < a[mn])
  45.         mn = j;
  46.     swap(&a[i], &a[mn]); // обмен значений
  47.   }
  48. }
  49.  
  50. // поиск индекса для деления массива - индекса стержневого элемента:
  51. // слева от этого индекса будут элементы меньше его, справа - больше
  52. int partition (int *a, int left, int right)
  53. {
  54.     int pivot = a[right - 1]; // стержневой элемент
  55.     int i = left; // индекс минимального элемента
  56.     for (int j = left; j < right - 1; j++)
  57.     {
  58.       if (a[j] < pivot)
  59.       {
  60.         swap(&a[i], &a[j]);
  61.         i++;
  62.       }
  63.     }
  64.     swap(&a[i], &a[right - 1]);   // ставим стержневой элемент на верное место
  65.     return i;                     // возвращаем индекс стержневого элемента
  66. }
  67.  
  68. // сортировка массива a на отрезке [left, right)
  69. void quick_sort(int * a, int left, int right)
  70. {
  71.     if (left + 1 < right)
  72.     {
  73.       // находим индекс разделения - элемент a[pi] стоит на своем месте
  74.       int pi = partition(a, left, right);
  75.       // сортируем по частям
  76.       quick_sort(a, left, pi);
  77.       quick_sort(a, pi + 1, right);
  78.     }
  79. }
  80.  
  81. void merge(int *a, int left, int mid, int right)
  82. {
  83.   // создаем массивы для слияния
  84.   int * left_arr = (int *) malloc(sizeof(int) * (mid - left));
  85.   int * right_arr = (int *) malloc(sizeof(int) * (right - mid));
  86.   // копируем элементы во временные массивы
  87.   memcpy(left_arr, &a[left], sizeof(int) * (mid - left));
  88.   memcpy(right_arr, &a[mid], sizeof(int) * (right - mid));
  89.   // слияние
  90.   int i = 0, j = 0, k = left;
  91.   while (i < mid - left && j < right - mid)
  92.   {
  93.     if (left_arr[i] <= right_arr[j])
  94.     {
  95.       a[k] = left_arr[i];
  96.       i++;
  97.     }
  98.     else
  99.     {
  100.       a[k] = right_arr[j];
  101.       j++;
  102.     }
  103.     ++k;
  104.   }
  105.   // сливаем остатки из левого массива
  106.   while (i < mid - left)
  107.   {
  108.     a[k] = left_arr[i];
  109.     ++i;
  110.     ++k;
  111.   }
  112.   // сливаем остатки из правого массива
  113.   while (j < right - mid)
  114.   {
  115.     a[k] = right_arr[j];
  116.     ++j;
  117.     ++k;
  118.   }
  119. }
  120.  
  121. // сортировка массива a на отрезке [left, right)
  122. void merge_sort(int * a, int left, int right)
  123. {
  124.   if (left + 1 < right) // в массиве больше одного элемента
  125.   {
  126.     int mid = (left + right) / 2; // середина масива
  127.     merge_sort(a, left, mid); // сортировка первой половины
  128.     merge_sort(a, mid, right); // сортировка второй половины
  129.     merge(a, left, mid, right); // слияние половин
  130.   }
  131. }
  132.  
  133. // проверка упорядоченности массива
  134. int check_ordering(int * a, int size)
  135. {
  136.   int is_ordering = 1;
  137.   for(int i=1; i<size; ++i)
  138.     if (a[i] < a[i-1])
  139.       is_ordering = 0; // если не упорядочен
  140.   return is_ordering;
  141. }
  142.  
  143. int main()
  144. {
  145.   srand(time(0)); // инициализация генератора случайных чисел -> rand()
  146.   printf("##| array size | select |  quick |  merge \n");
  147.   for(int test = 0; test < 10; ++test) // число тестов = 10
  148.   {
  149.     // для замеров времени выполнения
  150.     clock_t start, end;
  151.     double cpu_time_used[3];
  152.  
  153.     int size = get_random(MIN_LEN, MAX_LEN);      // размер массива случайный в заданном диапазоне
  154.     int * src = get_random_array(size);           // генерация массива
  155.     int * copy_src = malloc(size * sizeof(int)); // копия массива
  156.  
  157.     // 1. Сортировка выбором
  158.     memcpy(copy_src, src, size * sizeof(int)); // копируем исходный массив
  159.     start = clock();  // стартуем
  160.     selection_sort(copy_src, size); // сортируем
  161.     end = clock();  // заканчиваем
  162.     cpu_time_used[0] = ((double) (end - start)) / CLOCKS_PER_SEC; // подсчитываем время
  163.     assert(check_ordering(copy_src, size)); // проверка упорядоченности
  164.  
  165.     // 2. Быстрая сортировка
  166.     memcpy(copy_src, src, size * sizeof(int)); // копируем исходный массив
  167.     start = clock();  // стартуем
  168.     quick_sort(copy_src, 0, size); // сортируем
  169.     end = clock();  // заканчиваем
  170.     cpu_time_used[1] = ((double) (end - start)) / CLOCKS_PER_SEC; // подсчитываем время
  171.     assert(check_ordering(copy_src, size)); // проверка упорядоченности
  172.  
  173.     // 3. Сортировка слиянием
  174.     memcpy(copy_src, src, size * sizeof(int)); // копируем исходный массив
  175.     start = clock();  // стартуем
  176.     merge_sort(copy_src, 0, size); // сортируем
  177.     end = clock();  // заканчиваем
  178.     cpu_time_used[2] = ((double) (end - start)) / CLOCKS_PER_SEC; // подсчитываем время
  179.     assert(check_ordering(copy_src, size)); // проверка упорядоченности
  180.  
  181.     // вывод строки результатов
  182.     printf("%2d|%11d ", test+1, size);
  183.     for(int i=0; i<3; ++i) printf("|%7.3f ", cpu_time_used[i]);
  184.     printf("\n");
  185.   }
  186.   return 0;
  187. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement