rb_tree_ut.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. #include "rb_tree.h"
  2. #include <library/cpp/testing/unittest/registar.h>
  3. #include <util/random/fast.h>
  4. #include <util/random/easy.h>
  5. #include <util/random/shuffle.h>
  6. class TRedBlackTreeTest: public TTestBase {
  7. struct TCmp {
  8. template <class T>
  9. static inline bool Compare(const T& l, const T& r) {
  10. return l.N < r.N;
  11. }
  12. template <class T>
  13. static inline bool Compare(const T& l, int r) {
  14. return l.N < r;
  15. }
  16. template <class T>
  17. static inline bool Compare(int l, const T& r) {
  18. return l < r.N;
  19. }
  20. };
  21. class TNode: public TRbTreeItem<TNode, TCmp> {
  22. public:
  23. inline TNode(int n) noexcept
  24. : N(n)
  25. {
  26. }
  27. int N;
  28. };
  29. using TTree = TRbTree<TNode, TCmp>;
  30. UNIT_TEST_SUITE(TRedBlackTreeTest);
  31. UNIT_TEST(TestEmpty)
  32. UNIT_TEST(TestInsert)
  33. UNIT_TEST(TestErase)
  34. UNIT_TEST(TestFind)
  35. UNIT_TEST(TestStress)
  36. UNIT_TEST(TestGettingIndexWithDifferentValues)
  37. UNIT_TEST(TestCheckChildrenAfterErase)
  38. UNIT_TEST(TestGettingIndexWithDifferentValuesAfterErase)
  39. UNIT_TEST(TestGettingIndexWithEqualValues)
  40. UNIT_TEST(TestLessCountOnEmptyTree)
  41. UNIT_TEST_SUITE_END();
  42. private:
  43. inline void TestStress() {
  44. TVector<TSimpleSharedPtr<TNode>> nodes;
  45. for (int i = 0; i < 1000; ++i) {
  46. nodes.push_back(new TNode(i));
  47. }
  48. TTree tree;
  49. TReallyFastRng32 rnd(Random());
  50. for (size_t i = 0; i < 1000000; ++i) {
  51. tree.Insert(nodes[rnd.Uniform(nodes.size())].Get());
  52. }
  53. for (TTree::TConstIterator it = tree.Begin(); it != tree.End();) {
  54. const int v1 = it->N;
  55. if (++it == tree.End()) {
  56. break;
  57. }
  58. const int v2 = it->N;
  59. UNIT_ASSERT(v1 < v2);
  60. }
  61. }
  62. inline void TestGettingIndexWithDifferentValues() {
  63. TVector<TSimpleSharedPtr<TNode>> nodes;
  64. size_t N = 1000;
  65. for (size_t i = 0; i < N; ++i) {
  66. nodes.push_back(new TNode(int(i)));
  67. }
  68. TTree tree;
  69. Shuffle(nodes.begin(), nodes.end());
  70. for (size_t i = 0; i < N; ++i) {
  71. tree.Insert(nodes[i].Get());
  72. }
  73. for (size_t i = 0; i < N; ++i) {
  74. UNIT_ASSERT_EQUAL(tree.LessCount(i), i);
  75. UNIT_ASSERT_EQUAL(tree.NotGreaterCount(i), i + 1);
  76. UNIT_ASSERT_EQUAL(tree.GreaterCount(i), N - i - 1);
  77. UNIT_ASSERT_EQUAL(tree.NotLessCount(i), N - i);
  78. auto nodePtr = tree.Find(i);
  79. UNIT_ASSERT_EQUAL(tree.GetIndex(nodePtr), i);
  80. UNIT_ASSERT_EQUAL(tree.GetIndex(nodes[i].Get()), static_cast<size_t>(nodes[i]->N));
  81. }
  82. }
  83. inline void TestCheckChildrenAfterErase() {
  84. TVector<TSimpleSharedPtr<TNode>> nodes;
  85. size_t N = 1000;
  86. for (size_t i = 0; i < N; ++i) {
  87. nodes.push_back(new TNode(int(i)));
  88. }
  89. TTree tree;
  90. Shuffle(nodes.begin(), nodes.end());
  91. for (size_t i = 0; i < N; ++i) {
  92. tree.Insert(nodes[i].Get());
  93. }
  94. auto checker = [](const TTree& tree) {
  95. for (auto node = tree.Begin(); node != tree.End(); ++node) {
  96. size_t childrens = 1;
  97. if (node->Left_) {
  98. childrens += node->Left_->Children_;
  99. }
  100. if (node->Right_) {
  101. childrens += node->Right_->Children_;
  102. }
  103. UNIT_ASSERT_VALUES_EQUAL(childrens, node->Children_);
  104. }
  105. };
  106. for (auto node : nodes) {
  107. tree.Erase(node.Get());
  108. checker(tree);
  109. }
  110. }
  111. inline void TestGettingIndexWithDifferentValuesAfterErase() {
  112. TVector<TSimpleSharedPtr<TNode>> nodes;
  113. size_t N = 1000;
  114. for (size_t i = 0; i < N; ++i) {
  115. nodes.push_back(new TNode(int(i)));
  116. }
  117. TTree tree;
  118. Shuffle(nodes.begin(), nodes.end());
  119. for (size_t i = 0; i < N; ++i) {
  120. tree.Insert(nodes[i].Get());
  121. }
  122. {
  123. size_t index = 0;
  124. for (auto node = tree.Begin(); node != tree.End(); ++node, ++index) {
  125. UNIT_ASSERT_VALUES_EQUAL(tree.GetIndex(&*node), index);
  126. UNIT_ASSERT_VALUES_EQUAL(tree.ByIndex(index)->N, node->N);
  127. UNIT_ASSERT_VALUES_EQUAL(node->N, index);
  128. }
  129. }
  130. for (size_t i = 1; i < N; i += 2) {
  131. auto* node = tree.Find(i);
  132. UNIT_ASSERT_VALUES_EQUAL(node->N, i);
  133. tree.Erase(node);
  134. }
  135. {
  136. size_t index = 0;
  137. for (auto node = tree.Begin(); node != tree.End(); ++node, ++index) {
  138. UNIT_ASSERT_VALUES_EQUAL(tree.GetIndex(&*node), index);
  139. UNIT_ASSERT_VALUES_EQUAL(tree.ByIndex(index)->N, node->N);
  140. UNIT_ASSERT_VALUES_EQUAL(node->N, 2 * index);
  141. }
  142. }
  143. }
  144. inline void TestGettingIndexWithEqualValues() {
  145. TVector<TSimpleSharedPtr<TNode>> nodes;
  146. size_t N = 1000;
  147. for (size_t i = 0; i < N; ++i) {
  148. nodes.push_back(new TNode(0));
  149. }
  150. TTree tree;
  151. for (size_t i = 0; i < N; ++i) {
  152. tree.Insert(nodes[i].Get());
  153. }
  154. for (size_t i = 0; i < N; ++i) {
  155. UNIT_ASSERT_EQUAL(tree.LessCount(nodes[i]->N), 0);
  156. UNIT_ASSERT_EQUAL(tree.NotGreaterCount(nodes[i]->N), N);
  157. UNIT_ASSERT_EQUAL(tree.GreaterCount(nodes[i]->N), 0);
  158. UNIT_ASSERT_EQUAL(tree.NotLessCount(nodes[i]->N), N);
  159. UNIT_ASSERT_EQUAL(tree.LessCount(*nodes[i].Get()), 0);
  160. UNIT_ASSERT_EQUAL(tree.NotGreaterCount(*nodes[i].Get()), N);
  161. UNIT_ASSERT_EQUAL(tree.GreaterCount(*nodes[i].Get()), 0);
  162. UNIT_ASSERT_EQUAL(tree.NotLessCount(*nodes[i].Get()), N);
  163. }
  164. }
  165. inline void TestFind() {
  166. TTree tree;
  167. {
  168. TNode n1(1);
  169. TNode n2(2);
  170. TNode n3(3);
  171. tree.Insert(n1);
  172. tree.Insert(n2);
  173. tree.Insert(n3);
  174. UNIT_ASSERT_EQUAL(tree.Find(1)->N, 1);
  175. UNIT_ASSERT_EQUAL(tree.Find(2)->N, 2);
  176. UNIT_ASSERT_EQUAL(tree.Find(3)->N, 3);
  177. UNIT_ASSERT(!tree.Find(0));
  178. UNIT_ASSERT(!tree.Find(4));
  179. UNIT_ASSERT(!tree.Find(1234567));
  180. }
  181. UNIT_ASSERT(tree.Empty());
  182. }
  183. inline void TestEmpty() {
  184. TTree tree;
  185. UNIT_ASSERT(tree.Empty());
  186. UNIT_ASSERT_EQUAL(tree.Begin(), tree.End());
  187. }
  188. inline void TestInsert() {
  189. TTree tree;
  190. {
  191. TNode n1(1);
  192. TNode n2(2);
  193. TNode n3(3);
  194. tree.Insert(n1);
  195. tree.Insert(n2);
  196. tree.Insert(n3);
  197. TTree::TConstIterator it = tree.Begin();
  198. UNIT_ASSERT_EQUAL((it++)->N, 1);
  199. UNIT_ASSERT_EQUAL((it++)->N, 2);
  200. UNIT_ASSERT_EQUAL((it++)->N, 3);
  201. UNIT_ASSERT_EQUAL(it, tree.End());
  202. }
  203. UNIT_ASSERT(tree.Empty());
  204. }
  205. inline void TestErase() {
  206. TTree tree;
  207. {
  208. TNode n1(1);
  209. TNode n2(2);
  210. TNode n3(3);
  211. tree.Insert(n1);
  212. tree.Insert(n2);
  213. tree.Insert(n3);
  214. TTree::TIterator it = tree.Begin();
  215. tree.Erase(it++);
  216. UNIT_ASSERT_EQUAL(it, tree.Begin());
  217. UNIT_ASSERT_EQUAL(it->N, 2);
  218. tree.Erase(it++);
  219. UNIT_ASSERT_EQUAL(it, tree.Begin());
  220. UNIT_ASSERT_EQUAL(it->N, 3);
  221. tree.Erase(it++);
  222. UNIT_ASSERT_EQUAL(it, tree.Begin());
  223. UNIT_ASSERT_EQUAL(it, tree.End());
  224. }
  225. UNIT_ASSERT(tree.Empty());
  226. }
  227. inline void TestLessCountOnEmptyTree() {
  228. TTree tree;
  229. UNIT_ASSERT_VALUES_EQUAL(0, tree.LessCount(TNode(1)));
  230. }
  231. };
  232. UNIT_TEST_SUITE_REGISTRATION(TRedBlackTreeTest);