Advertisement
zozohoang

CoutingSort-RadixSort-BucketSort

Mar 26th, 2025
357
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.66 KB | Source Code | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <cmath>
  4. #include <algorithm>
  5.  
  6. /*
  7. Để cài đặt heap sort chúng ta cần xây dựng Maxheap or MinHeap trước
  8. Nút lá là nút không có nút con
  9. Nta quy ước:
  10. - Nút trái có dạng 2i+1
  11. - Nút phải có dạng 2i+2
  12. - Nút cha (nút root) (i - 1)/2
  13. - Nút lá sẽ có chỉ số từ (n/2 đến n - 1)
  14. - Như vậy nút có nút con sé có chỉ số từ 0-> n/2 - 1
  15. - Với n là kích thước của mảng
  16.  
  17. ** Chứng minh nút lá có chỉ số từ n/2 đến n-1 như sau:
  18. Nút lá là nút nút không có nút con nào suy ra nút đó sẽ không có nút trái và nút phải
  19. nghĩa là:
  20. 2i + 1 >= n and 2i + 2 >= n
  21. tương đương
  22. i >= (n - 1)/2 and i >= (n - 2)/2
  23. rõ ràng nếu i >= (n-1)/2 sẽ thoả mãn đc (n - 2)/2 nên ta xét:
  24. i >= (n-1)/2 làm tròn số nguyên xuống nên lấy n/2 là thoả mãn nút lá sẽ bắt đầu từ đây
  25.  
  26. Độ phức tạp thuật toán O(NlogN)
  27. Space complexity: O(1)
  28.  
  29.  
  30. Heapify hàm này có tác dụng xây dựng lại cây MaxHeap or MinHeap
  31.  
  32. Maxheap:
  33. */
  34.  
  35. void PrintArr(const std::vector<int>& arr, bool isBreakLine = true)
  36. {
  37.     for (const auto& i : arr)
  38.     {
  39.         std::cout << i << " ";
  40.     }
  41.    
  42.     if (isBreakLine)
  43.         std::cout << "\n";
  44. }
  45.  
  46. void Swap(int* num1, int* num2)
  47. {
  48.     int tmp = *num1;
  49.     *num1 = *num2;
  50.     *num2 = tmp;
  51. }
  52.  
  53. void Heapify(std::vector<int>& arr, int arrSize, int idxParentNode)
  54. {
  55.     int left = 2 * idxParentNode + 1;
  56.     int right = 2 * idxParentNode + 2;
  57.     int len = arrSize;
  58.    
  59.     int newIdxParentNode = idxParentNode;
  60.    
  61.     if (left < len && arr[idxParentNode] < arr[left])
  62.     {
  63.         newIdxParentNode = left;
  64.     }
  65.    
  66.     if (right < len && arr[newIdxParentNode] < arr[right])
  67.     {
  68.         newIdxParentNode = right;
  69.     }
  70.    
  71.     if (newIdxParentNode != idxParentNode)
  72.     {
  73.         Swap(&arr[idxParentNode], &arr[newIdxParentNode]);
  74.         Heapify(arr, len, newIdxParentNode);
  75.     }
  76. }
  77.  
  78. void BuildMaxHeap(std::vector<int>& arr)
  79. {
  80.     int len = arr.size();
  81.     int lastNodeHasChildNode = (int) len/2 - 1;
  82.    
  83.     for (int i = lastNodeHasChildNode; i >= 0; i--)
  84.     {
  85.         Heapify(arr, arr.size(), i);
  86.     }
  87. }
  88.  
  89. void HeapSort(std::vector<int>& unsorted_arr)
  90. {
  91.     BuildMaxHeap(unsorted_arr);
  92.    
  93.     for (int i = unsorted_arr.size() - 1; i >= 0; i--)
  94.     {
  95.         Swap(&unsorted_arr[i], &unsorted_arr[0]);
  96.         Heapify(unsorted_arr, i, 0);
  97.     }
  98. }
  99.  
  100.  
  101. /*
  102. Counting Sort được sử dụng khi kích thước các phần từ
  103. nằm từ min max của mảng đó coi như tính tổng các số
  104. hạng trong mảng đầu vào với
  105. số các số hạng = ((số lớn nhất trong dãy - số nhỏ nhất trong dãy) / khoảng cách) + 1
  106. với khoảng cách coi là 1 đơn vị nên số các số hạng trong dãy là n = (max - min) + 1
  107.  
  108. 1) Tính n là số các số hạng trong mảng để tạo mảng count tần suất xuất hiện
  109. các phần tử trong mảng
  110.  
  111. 2) Tiếp theo tạo 1 mảng count số lượng xuất hiện của các phần tử trong
  112. mảng đầu vào
  113. 3) Cộng dồn mảng count thì giá trị của phần tử mảng cộng dồn thể hiện
  114. có bao nhiêu phần tử <= phần tử đang xét
  115.  
  116. Time Complexity: O(n + k)
  117. Space Complexity: O(n + k)
  118. */
  119.  
  120. std::vector<int> CountingSort(const std::vector<int>& unsorted_arr)
  121. {
  122.     int max = unsorted_arr[0], min = unsorted_arr[0];
  123.     for (int i = 1; i < unsorted_arr.size(); i++)
  124.     {
  125.         if (unsorted_arr[i] > max)
  126.             max = unsorted_arr[i];
  127.        
  128.         if (unsorted_arr[i] < min)
  129.             min = unsorted_arr[i];
  130.        
  131.     }
  132.    
  133.     int n = max - min + 1;
  134.     std::vector<int> counts(n + 1, 0);
  135.    
  136.     for (const auto& e : unsorted_arr)
  137.     {
  138.         counts[e]++;
  139.     }
  140.    
  141.     for (int j = 1; j <= n; j++)
  142.     {
  143.         counts[j] = counts[j] + counts[j - 1];
  144.     }
  145.    
  146.     std::vector<int> ret(unsorted_arr.size());
  147.    
  148.     for (const auto& e : unsorted_arr)
  149.     {
  150.         int numLessOrEqualThanE = counts[e];
  151.         if (numLessOrEqualThanE > 0)
  152.         {
  153.             ret[numLessOrEqualThanE - 1] = e;
  154.             counts[e]--;
  155.         }
  156.     }
  157.    
  158.     return ret;
  159. }
  160.  
  161. /*
  162. RadixSort:
  163. Ý tưởng: Tìm số lớn nhất để xem độ dài số là bao nhiêu
  164. để sắp xếp theo các hàng của các số trong mảng
  165. */
  166.  
  167. std::vector<int> RadixSort(const std::vector<int>& unsorted_arr)
  168. {
  169.     int max = unsorted_arr[0];
  170.     int len = unsorted_arr.size();
  171.    
  172.     for (int i = 1; i < unsorted_arr.size(); i++)
  173.     {
  174.         if (max < unsorted_arr[i])
  175.             max = unsorted_arr[i];
  176.     }
  177.    
  178.     int countUnit = 0;
  179.     while (true)
  180.     {
  181.         int digit = max / (int) pow(10, countUnit);
  182.         if (digit > 0)
  183.         {
  184.             countUnit++;
  185.         }
  186.         else
  187.         {
  188.             break;
  189.         }
  190.     }
  191.    
  192.     std::vector<std::vector<int>> buckets(10);
  193.     std::vector<int> sortedArr(unsorted_arr.cbegin(), unsorted_arr.cend());
  194.    
  195.     for (int i = 0; i < countUnit; i++)
  196.     {
  197.         for (int j = 0; j < len; j++)
  198.         {
  199.             int idxBucket = (sortedArr[j] / (int) pow(10, i)) % 10;
  200.            
  201.             buckets[idxBucket].emplace_back(sortedArr[j]);
  202.         }
  203.        
  204.         sortedArr.clear();
  205.        
  206.         for (int k = 0; k < 10; k++)
  207.         {
  208.             if (buckets[k].size() == 0)
  209.                 continue;
  210.            
  211.             for (const auto& e : buckets[k])
  212.             {
  213.                 sortedArr.emplace_back(e);
  214.             }
  215.         }
  216.        
  217.         buckets.clear();
  218.         buckets.resize(10);
  219.     }
  220.    
  221.     return sortedArr;
  222. }
  223.  
  224. void CountingSortSub(std::vector<int>& unsorted_arr, int exp)
  225. {
  226.     std::vector<int> counts(10, 0);
  227.     std::vector<int> output(unsorted_arr.size());
  228.    
  229.     std::cout << "Before and exp: " << exp << std::endl;
  230.     PrintArr(unsorted_arr);
  231.    
  232.     for (const auto& e : unsorted_arr)
  233.     {
  234.         int digit = (e / exp) % 10;
  235.         std::cout << "e: " << e << " digit: " << digit << std::endl;
  236.         counts[digit]++;
  237.     }
  238.    
  239.     for (int i = 1; i < 10; i++)
  240.     {
  241.         counts[i] = counts[i] + counts[i - 1];
  242.     }
  243.    
  244.     for (int j = unsorted_arr.size() - 1; j >= 0; j--)
  245.     {
  246.         int digit = (unsorted_arr[j] / exp) % 10;
  247.         output[counts[digit] - 1] = unsorted_arr[j];
  248.         counts[digit]--;
  249.     }
  250.    
  251.     for(int k = 0; k < output.size(); k++)
  252.     {
  253.         unsorted_arr[k] = output[k];
  254.     }
  255.    
  256.     std::cout << "[CountingSortSub]\n";
  257.     PrintArr(unsorted_arr);
  258. }
  259.  
  260. void RadixSort2(std::vector<int>& unsorted_arr)
  261. {
  262.     int max = unsorted_arr[0];
  263.     int len = unsorted_arr.size();
  264.    
  265.     for (int i = 1; i < len; i++)
  266.     {
  267.         if (max < unsorted_arr[i])
  268.             max = unsorted_arr[i];
  269.     }
  270.    
  271.     for (int exp = 1; (max/exp) > 0; exp = 10 * exp)
  272.     {
  273.         CountingSortSub(unsorted_arr, exp);
  274.     }
  275. }
  276.  
  277. /*
  278. Bucketsort: dùng trong trường hợp dãy là phân phối đều trên 1 khoảng
  279. Ý tưởng:
  280. Chia dãy vào các bucket khác nhau và sắp xếp trên từng bucket
  281. sau đó gộp chúng vào thành mảng kết quả
  282. */
  283.  
  284. std::vector<int> BucketSort(const std::vector<int>& unsorted_arr)
  285. {
  286.     int len = unsorted_arr.size();
  287.     int max = unsorted_arr[0];
  288.    
  289.     for (const auto& e : unsorted_arr)
  290.     {
  291.         if (max < e)
  292.             max = e;
  293.     }
  294.    
  295.     max = ceil(max / 10.0) * 10;
  296.     int bucketSize = max / 10;
  297.     std::vector<std::vector<int>> buckets(bucketSize);
  298.    
  299.     for (int i = 0; i < len; i++)
  300.     {
  301.         int idxBucket = (unsorted_arr[i] * bucketSize) / max;
  302.         buckets[idxBucket].emplace_back(unsorted_arr[i]);
  303.     }
  304.    
  305.     for (int i = 0; i < bucketSize; i++)
  306.     {
  307.         std::sort(buckets[i].begin(), buckets[i].end());
  308.     }
  309.    
  310.     std::vector<int> ret;
  311.    
  312.     for (int i = 0; i < bucketSize; i++)
  313.     {
  314.         for (const auto& e : buckets[i])
  315.         {
  316.             ret.emplace_back(e);
  317.         }
  318.     }
  319.    
  320.     return ret;
  321. }
  322.  
  323.  
  324. int main()
  325. {
  326.     std::vector<int> arr = {4, 10, 3, 5, 1};
  327.     // BuildMaxHeap(arr);
  328.     HeapSort(arr);
  329.     PrintArr(arr);
  330.    
  331.     // std::vector<int> unsorted_arr_ctSort = {4, 2, 2, 8, 3, 3, 1};
  332.     // auto sorted_arr = CountingSort(unsorted_arr_ctSort);
  333.     // PrintArr(sorted_arr);
  334.    
  335.    
  336.     std::vector<int> unsorted_arr_radixsort = {170, 45, 75, 90, 802, 24, 2, 66};
  337.     // RadixSort2(unsorted_arr_radixsort);
  338.     // PrintArr(unsorted_arr_radixsort);
  339.    
  340.     auto ret = BucketSort(unsorted_arr_radixsort);
  341.     PrintArr(ret);
  342.    
  343.     return 0;
  344. }
Tags: dsa
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement