Guest User

Untitled

a guest
Dec 3rd, 2025
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.32 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. #include <random>
  5. #include <chrono>
  6.  
  7. // Modified Quicksort with three element rule
  8. // Contact Email [email protected]
  9. // Created by I.A
  10.  
  11. // Configuration Constants
  12. const int NUM_ELEMENTS = 1000000; // 1 million elements
  13. const int NUM_TRIALS = 100; // 1000 trials
  14.  
  15. /**
  16. * Applies the specific rule requested for subarrays of size 3.
  17. *
  18. * There are 6 possible orderings:
  19. * 1 2 3 -> 2 1 3
  20. * 1 3 2 -> 3 1 2
  21. * 2 1 3 -> 1 2 3
  22. * 2 3 1 -> 1 2 3
  23. * 3 1 2 -> 2 3 1
  24. * 3 2 1 -> 1 3 2
  25. *
  26. * In two cases, this will produce the correct order. In one case, it will disorder the correct order.
  27. * In the remaining three cases, it changes the order, but whether that is beneficial or not is not clear.
  28. */
  29. template <class T>
  30. void apply_three_element_rule(std::vector<T>& arr, int low, int high) {
  31. // Corrected condition: size 3 implies high - low == 2 (e.g., indices 0, 1, 2)
  32. if (high - low == 2) {
  33. // a (pivot) b c
  34. T const& pivot = arr[low]; // First number as pivot
  35. T const& third_num = arr[high]; // Third number to compare
  36.  
  37. // if c < a
  38. if (third_num <= pivot) {
  39. // Swap all 3 to make pivot middle, third_num first
  40. T temp_mid = arr[low + 1];
  41. // c a b
  42. arr[high] = temp_mid;
  43. arr[low + 1] = pivot;
  44. arr[low] = third_num;
  45. }
  46. else {
  47. // Swap first two
  48. T temp_mid = arr[low + 1];
  49.  
  50. // b a c
  51. arr[low] = temp_mid;
  52. arr[low + 1] = pivot;
  53. }
  54. }
  55. }
  56.  
  57. // Standard Hoare partition scheme
  58. template <class T>
  59. int partition(std::vector<T>& arr, int low, int high) {
  60. T pivot = arr[low];
  61. int i = low - 1;
  62. int j = high + 1;
  63.  
  64. while (true) {
  65. do {
  66. i++;
  67. } while (arr[i] < pivot);
  68.  
  69. do {
  70. j--;
  71. } while (arr[j] > pivot);
  72.  
  73. if (i >= j)
  74. return j;
  75.  
  76. std::swap(arr[i], arr[j]);
  77. }
  78. }
  79.  
  80. /**
  81. * Quicksort implementation.
  82. * Integrates the apply_three_element_rule when the subarray size is 3.
  83. */
  84. static const bool MONTY_SORT = true;
  85. template <class T, bool MS>
  86. void quickSort(std::vector<T>& arr, int low, int high) {
  87. if (low < high) {
  88. // Check for specific 3-element case
  89. if (MONTY_SORT && high - low == 2) {
  90. apply_three_element_rule(arr, low, high);
  91. }
  92.  
  93. // Partition the array
  94. int p = partition(arr, low, high);
  95.  
  96. // Recursively sort elements before and after partition
  97. quickSort<T, MS>(arr, low, p);
  98. quickSort<T, MS>(arr, p + 1, high);
  99. }
  100. }
  101.  
  102. /**
  103. * Quicksort implementation.
  104. * Integrates the apply_three_element_rule when the subarray size is 3.
  105. */
  106. bool const OPTIMIZE_2 = true;
  107. bool const OPTIMIZE_3 = true;
  108. template <class T>
  109. void quickSort2(std::vector<T>& arr, int low, int high) {
  110. int size = high - low;
  111. if (size <= 0) return;
  112. if (OPTIMIZE_2 && size == 1) {
  113. if (arr[high] < arr[low]) std::swap(arr[low], arr[high]);
  114. return;
  115. }
  116. if (OPTIMIZE_3 && size == 2) {
  117. T const& a = arr[low];
  118. T const& b = arr[low + 1];
  119. T const& c = arr[low + 2];
  120. if (b < a) { // b < a
  121. if (c < b) { // a b c -> c b a
  122. std::swap(arr[low], arr[high]);
  123. }
  124. else if (c < a) { // a b c -> b c a
  125. T a = arr[low];
  126. arr[low] = arr[low + 1];
  127. arr[low + 1] = arr[high];
  128. arr[high] = a;
  129. }
  130. else { // a b c -> b a c
  131. std::swap(arr[low], arr[low + 1]);
  132. }
  133. }
  134. else { // a is <= b
  135. if (c < a) { // a b c -> c a b
  136. T c = arr[high];
  137. arr[high] = arr[low + 1];
  138. arr[low + 1] = a;
  139. arr[low] = c;
  140. }
  141. else if (c < b) { // a b c -> a c b
  142. std::swap(arr[low + 1], arr[high]);
  143. }
  144. }
  145. return;
  146. }
  147.  
  148. // Partition the array
  149. int p = partition(arr, low, high);
  150.  
  151. // Recursively sort elements before and after partition
  152. quickSort2(arr, low, p);
  153. quickSort2(arr, p + 1, high);
  154. }
  155.  
  156. std::string generate_string() {
  157. static constexpr auto CHARS =
  158. "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  159. "abcdefghijklmnopqrstuvwxyz";
  160. thread_local std::random_device rd;
  161. thread_local std::mt19937 gen(rd());
  162. thread_local std::uniform_int_distribution<> dist(0u, std::strlen(CHARS) - 1u);
  163.  
  164. std::string::size_type length = dist(gen);
  165. std::string result(length, '\0');
  166. std::generate_n(result.begin(), length, [&]() { return CHARS[dist(gen)]; });
  167. return result;
  168. }
  169.  
  170. int main() {
  171. std::cout << "Starting Benchmark..." << std::endl;
  172. std::cout << "Elements per array: " << NUM_ELEMENTS << std::endl;
  173. std::cout << "Total Trials: " << NUM_TRIALS << std::endl;
  174.  
  175. // Setup random number generation
  176. std::random_device rd;
  177. std::mt19937 gen(rd());
  178. std::uniform_int_distribution<> distrib(1, 10000000);
  179.  
  180. // Pre-allocate vector
  181. std::vector<std::string> unsorted(NUM_ELEMENTS);
  182.  
  183. // Variable to hold ONLY the time spent sorting
  184. std::chrono::duration<double> quicksort_time(0);
  185. std::chrono::duration<double> montysort_time(0);
  186. std::chrono::duration<double> stdsort_time(0);
  187.  
  188. for (int t = 1; t <= NUM_TRIALS; ++t) {
  189. // std::generate(data.begin(), data.end(), [&distrib, &gen]() { return distrib(gen); });
  190. std::generate(unsorted.begin(), unsorted.end(), generate_string);
  191.  
  192. auto data = unsorted;
  193. auto start = std::chrono::high_resolution_clock::now();
  194. quickSort<std::string, false>(data, 0, NUM_ELEMENTS - 1);
  195. auto end = std::chrono::high_resolution_clock::now();
  196. quicksort_time += (end - start);
  197.  
  198. data = unsorted;
  199. start = std::chrono::high_resolution_clock::now();
  200. quickSort<std::string, true>(data, 0, NUM_ELEMENTS - 1);
  201. end = std::chrono::high_resolution_clock::now();
  202. montysort_time += (end - start);
  203.  
  204. data = unsorted;
  205. start = std::chrono::high_resolution_clock::now();
  206. std::sort(data.begin(), data.end());
  207. end = std::chrono::high_resolution_clock::now();
  208. stdsort_time += (end - start);
  209.  
  210. // Optional: Simple check to ensure sorted (checks only first trial)
  211. if (t == 1) {
  212. if (!std::is_sorted(data.begin(), data.end())) {
  213. std::cerr << "Error: Array not sorted on trial 1!" << std::endl;
  214. return 1;
  215. }
  216. }
  217.  
  218. // Progress logging
  219. if (t % 1 == 0 || t == NUM_TRIALS) {
  220. std::cout << "Completed Trial " << t << "/" << NUM_TRIALS << "\r" << std::flush;
  221. }
  222. }
  223.  
  224. std::cout << "\n\nBenchmark Complete." << std::endl;
  225.  
  226. // Output stats based on the accumulated sort duration
  227. std::cout << "Quicksort Time: " << quicksort_time.count() << " seconds" << std::endl;
  228. std::cout << "MontySort Time: " << montysort_time.count() << " seconds" << std::endl;
  229. std::cout << "std::sort Time: " << stdsort_time.count() << " seconds" << std::endl;
  230.  
  231. return 0;
  232. }
  233.  
Advertisement
Add Comment
Please, Sign In to add comment