TestQuickSort.cpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. /*
  2. * Copyright (c) 2020, the SerenityOS developers.
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibTest/TestCase.h>
  7. #include <AK/Noncopyable.h>
  8. #include <AK/QuickSort.h>
  9. #include <AK/StdLibExtras.h>
  10. TEST_CASE(sorts_without_copy)
  11. {
  12. struct NoCopy {
  13. AK_MAKE_NONCOPYABLE(NoCopy);
  14. public:
  15. NoCopy() = default;
  16. NoCopy(NoCopy&&) = default;
  17. NoCopy& operator=(NoCopy&&) = default;
  18. int value { 0 };
  19. };
  20. Array<NoCopy, 64> array;
  21. // Test the dual pivot quick sort.
  22. for (size_t i = 0; i < 64; ++i)
  23. array[i].value = (64 - i) % 32 + 32;
  24. dual_pivot_quick_sort(array, 0, array.size() - 1, [](auto& a, auto& b) { return a.value < b.value; });
  25. for (size_t i = 0; i < 63; ++i)
  26. EXPECT(array[i].value <= array[i + 1].value);
  27. // Test the single pivot quick sort.
  28. for (size_t i = 0; i < 64; ++i)
  29. array[i].value = (64 - i) % 32 + 32;
  30. AK::single_pivot_quick_sort(array.begin(), array.end(), [](auto& a, auto& b) { return a.value < b.value; });
  31. for (size_t i = 0; i < 63; ++i)
  32. EXPECT(array[i].value <= array[i + 1].value);
  33. }
  34. // This test case may fail to construct a worst-case input if the pivot choice
  35. // of the underlying quick_sort no longer matches the one used here.
  36. // So it provides no strong guarantees about the properties of quick_sort.
  37. TEST_CASE(maximum_stack_depth)
  38. {
  39. const int size = 256;
  40. int* data = new int[size];
  41. for (int i = 0; i < size; i++) {
  42. data[i] = i;
  43. }
  44. // Construct the data in such a way that the assumed pivot choice
  45. // of (size / 2) causes the partitions to be of worst case size.
  46. for (int i = 0; i < size / 2; i++) {
  47. swap(data[i], data[i + (size - i) / 2]);
  48. }
  49. // Measure the depth of the call stack through the less_than argument
  50. // of quick_sort as it gets copied for each recursive call.
  51. struct DepthMeasurer {
  52. int& max_depth;
  53. int depth { 0 };
  54. DepthMeasurer(int& max_depth)
  55. : max_depth(max_depth)
  56. {
  57. }
  58. DepthMeasurer(const DepthMeasurer& obj)
  59. : max_depth(obj.max_depth)
  60. {
  61. depth = obj.depth + 1;
  62. if (depth > max_depth) {
  63. max_depth = depth;
  64. }
  65. }
  66. bool operator()(int& a, int& b)
  67. {
  68. return a < b;
  69. }
  70. };
  71. int max_depth = 0;
  72. DepthMeasurer measurer(max_depth);
  73. AK::single_pivot_quick_sort(data, data + size, measurer);
  74. EXPECT(max_depth <= 64);
  75. for (int i = 0; i < size; i++)
  76. EXPECT(data[i] == i);
  77. delete[] data;
  78. }