Advertisement
jusohatam

Untitled

Dec 13th, 2021
843
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.40 KB | None | 0 0
  1. #include <iostream>
  2. #include <fstream>
  3. #include <sstream>
  4. #include <ctime>
  5. #include <tuple>
  6.  
  7. using namespace std;
  8.  
  9. class DirectMerge {
  10. private:
  11.     // Счетчик количества сравнений
  12.     int count_compare = 0;
  13.  
  14.     // Счетчик количества перемещений
  15.     int count_move = 0;
  16.  
  17.     // Счетчики длины серии, сегментов, длины файлов a,b,c
  18.     size_t iterations, segments = 0, len_a, len_b, len_c;
  19.     string filename;
  20.  
  21. public:
  22.     DirectMerge(size_t n, string& input_filename) {
  23.         len_a = n;
  24.         iterations = 1;
  25.         filename = input_filename;
  26.     }
  27.  
  28.     void write(ofstream &file, string &val, bool &flag) {
  29.         if (!val.empty()) {
  30.             if (flag) {
  31.                 file << "\n";
  32.             }
  33.             file << val;
  34.             ++count_move;
  35.             flag = true;
  36.         }
  37.     }
  38.  
  39.     bool compare(string& x, string& y) {
  40.         // Читаем только первый элемент строки
  41.         stringstream xs(x), ys(y);
  42.         string comp_x, comp_y;
  43.         xs >> comp_x;
  44.         ys >> comp_y;
  45.         ++count_compare;
  46.         return comp_x < comp_y;
  47.     }
  48.  
  49.     void separate() {
  50.         // Открываекм файл a для чтения
  51.         ifstream file_a(filename, ios::out | ios::binary);
  52.         // Открываем файлы b, c для записи
  53.         ofstream file_b("b.bin", ios::in | ios::trunc | ios::binary),
  54.                 file_c("c.bin", ios::in | ios::trunc | ios::binary);
  55.         string x;
  56.         // Счетчики длины текущей серии и текущей строки файла
  57.         size_t tmp_count = 0, a_i = 0;
  58.         segments = 1;
  59.         len_b = 0, len_c = 0;
  60.         bool write_b = true, new_line_b = false, new_line_c = false;
  61.  
  62.         // Пока не кончился файл a
  63.         while (a_i < len_a) {
  64.             // Если достигли длины текущей серии, то переключаем запись на второй файл
  65.             if (tmp_count == iterations) {
  66.                 write_b = !write_b;
  67.                 tmp_count = 0;
  68.                 ++segments;
  69.             }
  70.             getline(file_a, x);
  71.             ++a_i;
  72.             // Запись переменной в файл b
  73.             if (write_b) {
  74.                 write(file_b, x, new_line_b);
  75.                 ++len_b;
  76.             // Запись переменной в файл c
  77.             } else {
  78.                 write(file_c, x, new_line_c);
  79.                 ++len_c;
  80.             }
  81.             ++tmp_count;
  82.         }
  83.  
  84.         // Закрываем все файлы
  85.         file_a.close();
  86.         file_b.close();
  87.         file_c.close();
  88.     }
  89.  
  90.     void merge() {
  91.         // Открываем файл a для записи
  92.         ofstream file_a(filename, ios::in | ios::trunc | ios::binary);
  93.         // Отркываем файлы b, c для чтения
  94.         ifstream file_b("b.bin", ios::out | ios::binary), file_c("c.bin", ios::out | ios::binary);
  95.         string x, y;
  96.         size_t count_b = iterations, count_c = iterations, b_i = 0, c_i = 0;
  97.         bool picked_b = false, picked_c = false, end_b = false, end_c = false, new_line_a = false;
  98.  
  99.         // Пока не достигли конца файла b или файла c
  100.         while (!end_b || !end_c) {
  101.  
  102.             // Если достигли конца серии в одном из файлов, обновляем счетчики
  103.             if (count_b == 0 && count_c == 0) {
  104.                 count_b = iterations, count_c = iterations;
  105.             }
  106.  
  107.             // Если файл b не кончился и выполнены условия, читаем очередную переменную
  108.             if (b_i < len_b) {
  109.                 if (count_b > 0 && !picked_b) {
  110.                     getline(file_b, x);
  111.                     ++b_i;
  112.                     picked_b = true;
  113.                 }
  114.             } else {
  115.                 end_b = true;
  116.             }
  117.  
  118.             // Если файл c не кончился и выполнены условия, читаем очередную переменную
  119.             if (c_i < len_c) {
  120.                 if (count_c > 0 && !picked_c) {
  121.                     getline(file_c, y);
  122.                     ++c_i;
  123.                     picked_c = true;
  124.                 }
  125.             } else {
  126.                 end_c = true;
  127.             }
  128.  
  129.             // Сливаем считанные переменные в файл a, пока не кончится одна из серий в одном из файлов
  130.             if (picked_b) {
  131.                 if (picked_c) {
  132.                     if (compare(x, y)) {
  133.                         write(file_a, x, new_line_a);
  134.                         --count_b;
  135.                         picked_b = false;
  136.                     } else {
  137.                         write(file_a, y, new_line_a);
  138.                         --count_c;
  139.                         picked_c = false;
  140.                     }
  141.                 } else {
  142.                     write(file_a, x, new_line_a);
  143.                     --count_b;
  144.                     picked_b = false;
  145.                 }
  146.             } else if (picked_c) {
  147.                 write(file_a, y, new_line_a);
  148.                 --count_c;
  149.                 picked_c = false;
  150.             }
  151.         }
  152.         // Увеличиваем длину серии вдвое для следующей фазы разделения
  153.         iterations *= 2;
  154.  
  155.         // Закрываем файлы
  156.         file_a.close();
  157.         file_b.close();
  158.         file_c.close();
  159.     }
  160.  
  161.     tuple<int, int, double> sort() {
  162.         // Время начала работы алгоритма
  163.         time_t time_begin = clock();
  164.  
  165.         // Функция сортировки
  166.         while (true) {
  167.             separate();
  168.             if (segments == 1) {
  169.                 break;
  170.             }
  171.             merge();
  172.         }
  173.  
  174.         // Время окончания работы алгоритма
  175.         time_t time_end = clock();
  176.  
  177.         // Итоговое время работы алгоритма
  178.         double time_spent = (double)(time_end - time_begin) / (double)CLOCKS_PER_SEC;
  179.  
  180.         return {count_compare, count_move, time_spent};
  181.     }
  182.  
  183. };
  184.  
  185. void run_tests(size_t& n, string& filename) {
  186.     DirectMerge dm(n, filename);
  187.     // Запуск функции сортировки
  188.     tuple<int, int, double> res = dm.sort();
  189.  
  190.     // Вывод полученных результатов прогона
  191.     cout << "N = " << n << "\n";
  192.     cout << "----------\n";
  193.     cout << "Count of compares: " << get<0>(res);
  194.     cout << "\nCount of moves: " << get<1>(res);
  195.     cout << "\nTime spent in sc: " << get<2>(res) << "\n\n";
  196. }
  197.  
  198. int main() {
  199.     size_t n1 = 100, n2 = 1000, n3 = 10000, n4 = 100000, n5 = 1000000;
  200.     string f1 = "a_n1.bin", f2 = "a_n2.bin", f3 = "a_n3.bin", f4 = "a_n4.bin", f5 = "a_n5.bin";
  201.  
  202.     run_tests(n1, f1);
  203.     run_tests(n2, f2);
  204.     run_tests(n3, f3);
  205.     run_tests(n4, f4);
  206.     run_tests(n5, f5);
  207. }
  208.  
  209. //N = 100
  210. //----------
  211. //Count of compares: 573
  212. //Count of moves: 1500
  213. //Time spent in sc: 0.039
  214. //
  215. //N = 1000
  216. //----------
  217. //Count of compares: 8723
  218. //Count of moves: 21000
  219. //Time spent in sc: 0.061
  220. //
  221. //N = 10000
  222. //----------
  223. //Count of compares: 123525
  224. //Count of moves: 290000
  225. //Time spent in sc: 0.609
  226. //
  227. //N = 100000
  228. //----------
  229. //Count of compares: 1564043
  230. //Count of moves: 3500000
  231. //Time spent in sc: 5.989
  232. //
  233. //N = 1000000
  234. //----------
  235. //Count of compares: 18681881
  236. //Count of moves: 41000000
  237. //Time spent in sc: 76.396
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement