fork download
  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. #include <numeric>
  5. #include <random>
  6. #include <chrono>
  7. using namespace std;
  8.  
  9. auto vandenman(const vector<int>& x, const int k) {
  10. auto y = x;
  11. std::nth_element(y.begin(), y.begin() + k, y.end());
  12. const auto kthValue = y[k];
  13. auto idxK = std::find(x.begin(), x.end(), kthValue);
  14. return idxK;
  15. }
  16.  
  17. template<typename It>
  18. auto miscco(It first, It last, const int k) {
  19. auto cmp_it_values = [](It lt, It rt){ return *lt < *rt;};
  20. vector<It> y;
  21. y.reserve(std::distance(first, last));
  22. for(auto it = first; it != last; ++it){
  23. y.emplace_back(it);
  24. }
  25. std::nth_element(y.begin(), y.begin() + k, y.end(), cmp_it_values);
  26. return y[k];
  27. }
  28.  
  29. template<typename It>
  30. It min_k(It first, It last, int k){
  31. auto cmp_it_values = [](It lt, It rt){ return *lt < *rt;};
  32. auto max_copy = std::min<long>(k, std::distance(first, last));
  33. auto start_it = first;
  34. std::advance(start_it, max_copy);
  35.  
  36. k++; // k == 0 has to return smallest one element.
  37. std::vector<It> k_smallest;
  38. k_smallest.reserve(k+1);
  39. for(auto it = first; it != start_it; ++it){
  40. k_smallest.push_back(it);
  41. }
  42. std::sort(k_smallest.begin(), k_smallest.end(), cmp_it_values);
  43.  
  44. for(auto it = start_it; it != last; ++it){
  45. if(k_smallest.empty() || *it < *k_smallest.back()){
  46. auto insertion_point = std::lower_bound(k_smallest.begin(), k_smallest.end(),
  47. it, cmp_it_values);
  48. k_smallest.insert(insertion_point, it);
  49. if(k_smallest.size() > k){
  50. k_smallest.pop_back(); // Remove the largest value
  51. }
  52. }
  53. }
  54. return k_smallest.back(); // The iterator to the min(k, n) smallest value
  55. }
  56.  
  57.  
  58. template<typename It>
  59. It min_k_heap(It first, It last, int k){
  60. k++; // k == 0 has to return smallest one element.
  61. auto cmp_it_values = [](It lt, It rt){ return *lt < *rt;};
  62. auto max_copy = std::min<long>(k, std::distance(first, last));
  63. auto start_it = first;
  64. std::advance(start_it, max_copy);
  65.  
  66. std::vector<It> k_smallest;
  67. k_smallest.reserve(k+1);
  68. for(auto it = first; it != start_it; ++it){
  69. k_smallest.push_back(it);
  70. }
  71. std::make_heap(k_smallest.begin(), k_smallest.end(), cmp_it_values);
  72.  
  73. for(auto it = start_it; it != last; ++it){
  74. if(*it < *k_smallest.front()){
  75. k_smallest.push_back(it);
  76. push_heap(k_smallest.begin(), k_smallest.end(), cmp_it_values);
  77. pop_heap(k_smallest.begin(), k_smallest.end(), cmp_it_values);
  78. k_smallest.pop_back();
  79. }
  80. }
  81. return k_smallest.front(); // The iterator to the min(k, n) smallest value
  82. }
  83.  
  84. int main() {
  85. std::vector<int> v(10000);
  86. std::vector<std::vector<int>::iterator> vPtr;
  87. vPtr.reserve(v.size());
  88. for (auto it = v.begin(); it != v.end(); ++it) {
  89. vPtr.push_back(it);
  90. }
  91. std::iota (std::begin(v), std::end(v), 0);
  92. std::mt19937 g(3);
  93. std::shuffle(v.begin(), v.end(), g);
  94.  
  95. {
  96. auto start = chrono::steady_clock::now();
  97. auto ans1 = *vandenman(v, 50);
  98. auto time1 = chrono::steady_clock::now() - start;
  99. cout << "Orig " << ans1<< " time: ";
  100. cout << chrono::duration <double, nano> (time1).count() << " ns" << endl;
  101. }
  102. {
  103. auto start = chrono::steady_clock::now();
  104. auto ans1 = *miscco(v.begin(), v.end(), 50);
  105. auto time1 = chrono::steady_clock::now() - start;
  106. cout << "Miscco " << ans1<< " time: ";
  107. cout << chrono::duration <double, nano> (time1).count() << " ns" << endl;
  108. }
  109. {
  110. auto start = chrono::steady_clock::now();
  111. std::nth_element(vPtr.begin(), std::next(vPtr.begin(), 50), vPtr.end(), [](auto lt, auto rt) { return (*lt) < (*rt); });
  112. auto ans1 = **std::next(vPtr.begin(), 50);
  113. auto time1 = chrono::steady_clock::now() - start;
  114. cout << "Miscco orig " << ans1 << " time: ";
  115. cout << chrono::duration <double, nano>(time1).count() << " ns" << endl;
  116. }
  117. {
  118. auto start = chrono::steady_clock::now();
  119. auto ans1 = *min_k(v.begin(), v.end(), 50);
  120. auto time1 = chrono::steady_clock::now() - start;
  121. cout << "Emily Binary insertion " << ans1<< " time: ";
  122. cout << chrono::duration <double, nano> (time1).count() << " ns" << endl;
  123. }
  124. {
  125. auto start = chrono::steady_clock::now();
  126. auto ans1 = *min_k_heap(v.begin(), v.end(), 50);
  127. auto time1 = chrono::steady_clock::now() - start;
  128. cout << "Emily Heap " << ans1<< " time: ";
  129. cout << chrono::duration <double, nano> (time1).count() << " ns" << endl;
  130. }
  131. return 0;
  132. }
Success #stdin #stdout 0s 16072KB
stdin
Standard input is empty
stdout
Orig 50 time: 152499 ns
Miscco 50 time: 173800 ns
Miscco orig 50 time: 115246 ns
Emily Binary insertion 50 time: 72504 ns
Emily Heap 50 time: 65070 ns