Advertisement
Derga

Untitled

Feb 23rd, 2023
681
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.60 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3.  
  4. //тут мы будем сортировать массив строк по цифре, которая стоит на месте digit_pos
  5. void count_sort(std::vector<std::string>& arr, int digit_pos) {
  6.   //число различиных цифр == 10 {0, 1, 2, ..., 9}
  7.   const int DIFFERENT_DIGITS_COUNT = 10;
  8.  
  9.   //Создаем вектор для сортировки подсчетом. Размер - 10, изначально в каждой ячейке - 0
  10.   std::vector<int> counting(DIFFERENT_DIGITS_COUNT, 0);
  11.  
  12.   //создали лямбду, которая будет выдергивать цифру из позиции digit_pos. Ее спокойно можно заменить функцией!
  13.   auto get_digit = [digit_pos] (const std::string& number) {
  14.     return number[digit_pos] - '0';
  15.   };
  16.  
  17.   //прохожусь по всем числам массива и из каждого выдергиваю цифру из digit_pos
  18.   for (const std::string& number : arr) {
  19.     int digit = get_digit(number);
  20.     counting[digit]++;
  21.   }
  22.  
  23.   /*
  24.   переделываю вектор в котором хранится сколько каких у меня цифр в массив префиксных сумм
  25.   что это дает? это хитрое место.
  26.  
  27.   например у нас был такой вектор после подсчета
  28.    0  1  2  3  4  5  6  7  8  9
  29.   {0, 1, 0, 1, 0, 0, 0, 2, 0, 0}
  30.   т.е. мы насчитали одну цифру "1", еще одну "3" и две "7"
  31.  
  32.   после того, как переделали вектор с подсчетом числа цифр в вектор префиксных сумм - получили
  33.   {0, 1, 1, 2, 2, 2, 2, 4, 4, 4};
  34.  
  35.   тут я долго осознавал, что нам это дает!
  36.  
  37.   Дальше я беру из вектора arr число, смотрю на его цифру из разряда с которым работаем.
  38.   Пусть там цифра 7. Дальше я захожу в 7ую ячейку вектора префиксных сумм, вижу число 4 и - магия!
  39.   Кладу число из arr в 4ую(если нумерация от 1) ячейку вектора tmp. 4 - это тот индекс в массиве tmp, куда я должен положить число из arr.
  40.   После этого уменьшаю число из вектора с префиксными суммами на 1.
  41.  
  42.   {0, 1, 1, 2, 2, 2, 2, 3, 4, 4};
  43.   Там теперь будет лежать число 3. Это значит, что когда я достану из вектора arr числоу которого в разряде с которым я работаю
  44.   будет снова 7 - я ее положу в 3ью ячейку вектора tmp. итд
  45.   */
  46.   for (int i = 1; i < counting.size(); ++i) {
  47.     counting[i] += counting[i - 1];
  48.   }
  49.  
  50.   //Создаем временный вектор в котором будем хранить результат сортировки
  51.   std::vector<std::string> tmp(arr.size());
  52.  
  53.   //в цикле иду по нему и расставляю элементы на места
  54.   //причем иду с конца arr, потому что в конце у меня (по смыслу сортировки) лежат большие числа, если рассматривать их предыдущие разряды.
  55.   //Они лежат в определенном порядке, отсортированные по цифре из предыдущего разряда.
  56.   for (int i = arr.size() - 1; i >= 0; --i) {
  57.     int digit = get_digit(arr[i]);
  58.     tmp[counting[digit] - 1] = arr[i];
  59.     counting[digit]--;
  60.   }
  61.  
  62.   //сохраняю в arr отсортированный вектор tmp
  63.   arr = tmp;
  64. }
  65.  
  66. /*
  67. Идея сортировки в том, что мы можем сортировать числа - "по цифрам".
  68.  
  69. Например есть два числа 132 и 123
  70.  
  71. Сначала мы рассмотрим последние цифры - 2 и 3.
  72. Отсортируем по этоим цифрам, получится - 132, потом 123
  73.  
  74. Дальше рассмотрим вторую цифру числа, там 3 и 2.
  75. Отсортируем по этоим цифрам, получится 123, 132
  76.  
  77. Дальше рассмотрим первую цифру - они одинаковые, поэтому не меняем прошлый порядок(!иначе все испортим), оставляем 123, 132
  78. */
  79. void radix_sort(std::vector<std::string>& arr) {
  80.   if (arr.empty()) {
  81.     return;
  82.   }
  83.  
  84.   //цикл идет по числу цифр в числе, начиная с последней (отвечающей за единицы) цифры.
  85.   const int digits_count = arr.front().size();
  86.   for (int digit_pos = digits_count - 1; digit_pos >= 0; --digit_pos) {
  87.     //тут мы с помощью сортировки подсчетом будем сортировать числа по каждой цифре начиная с последней (отвечающей за единицы)
  88.     count_sort(arr, digit_pos);
  89.   }
  90. }
  91.  
  92. int main() {
  93.   std::ios_base::sync_with_stdio(false);
  94.   std::cin.tie(nullptr);
  95.  
  96.   size_t n;
  97.   std::cin >> n;
  98.  
  99.   std::vector<std::string> lines(n);
  100.   for (auto& line : lines) {
  101.     std::cin >> line;
  102.   }
  103.   std::cout << std::endl;
  104.  
  105.   radix_sort(lines);
  106.  
  107.   for (const auto& line : lines) {
  108.     std::cout << line << "\n";
  109.   }
  110.  
  111.   return 0;
  112. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement