diff --git a/cavl.h b/cavl.h index fced134..2efc3de 100644 --- a/cavl.h +++ b/cavl.h @@ -30,8 +30,7 @@ #ifdef __cplusplus // This is, strictly speaking, useless because we do not define any functions with external linkage here, -// but it tells static analyzers that what follows should be interpreted as C code rather than C++, where -// identifiers starting with "_" are allowed in the global scope, C-style casts are allowed, etc. +// but it tells static analyzers that what follows should be interpreted as C code rather than C++. extern "C" { #endif @@ -48,7 +47,7 @@ struct Cavl int8_t bf; ///< Balance factor is positive when right-heavy. Allowed values are {-1, 0, +1}. }; #if defined(static_assert) || defined(__cplusplus) -static_assert(sizeof(Cavl) <= sizeof(void* [4])); +static_assert(sizeof(Cavl) <= sizeof(void* [4]), "Bad size"); #endif /// Returns POSITIVE if the search target is GREATER than the provided node, negative if smaller, zero on match (found). @@ -99,7 +98,7 @@ static inline Cavl* cavlFindExtremum(Cavl* const root, const bool maximum) // ---------------------------------------- POLICE LINE DO NOT CROSS ---------------------------------------- /// INTERNAL USE ONLY. Makes the '!r' child of node 'x' its parent; i.e., rotates 'x' toward 'r'. -static inline void _cavlRotate(Cavl* const x, const bool r) +static inline void cavlPrivateRotate(Cavl* const x, const bool r) { assert((x != NULL) && (x->lr[!r] != NULL) && ((x->bf >= -1) && (x->bf <= +1))); Cavl* const z = x->lr[!r]; @@ -120,7 +119,7 @@ static inline void _cavlRotate(Cavl* const x, const bool r) /// INTERNAL USE ONLY. /// Accepts a node and how its balance factor needs to be changed -- either +1 or -1. /// Returns the new node to replace the old one if tree rotation took place, same node otherwise. -static inline Cavl* _cavlAdjustBalance(Cavl* const x, const bool increment) +static inline Cavl* cavlPrivateAdjustBalance(Cavl* const x, const bool increment) { assert((x != NULL) && ((x->bf >= -1) && (x->bf <= +1))); Cavl* out = x; @@ -134,7 +133,7 @@ static inline Cavl* _cavlAdjustBalance(Cavl* const x, const bool increment) if ((z->bf * sign) <= 0) // Parent and child are heavy on the same side or the child is balanced. { out = z; - _cavlRotate(x, r); + cavlPrivateRotate(x, r); if (z->bf == 0) { x->bf = (int8_t) (-sign); @@ -151,8 +150,8 @@ static inline Cavl* _cavlAdjustBalance(Cavl* const x, const bool increment) Cavl* const y = z->lr[r]; assert(y != NULL); // Heavy side cannot be empty. out = y; - _cavlRotate(z, !r); - _cavlRotate(x, r); + cavlPrivateRotate(z, !r); + cavlPrivateRotate(x, r); if ((y->bf * sign) < 0) { x->bf = (int8_t) (+sign); @@ -182,7 +181,7 @@ static inline Cavl* _cavlAdjustBalance(Cavl* const x, const bool increment) /// INTERNAL USE ONLY. /// Takes the culprit node (the one that is added); returns NULL or the root of the tree (possibly new one). /// When adding a new node, set its balance factor to zero and call this function to propagate the changes upward. -static inline Cavl* _cavlRetraceOnGrowth(Cavl* const added) +static inline Cavl* cavlPrivateRetraceOnGrowth(Cavl* const added) { assert((added != NULL) && (added->bf == 0)); Cavl* c = added; // Child @@ -191,7 +190,7 @@ static inline Cavl* _cavlRetraceOnGrowth(Cavl* const added) { const bool r = p->lr[1] == c; // c is the right child of parent assert(p->lr[r] == c); - c = _cavlAdjustBalance(p, r); + c = cavlPrivateAdjustBalance(p, r); p = c->up; if (c->bf == 0) { // The height change of the subtree made this parent perfectly balanced (as all things should be), @@ -234,7 +233,7 @@ static inline Cavl* cavlSearch(Cavl** const root, out->lr[1] = NULL; out->up = up; out->bf = 0; - Cavl* const rt = _cavlRetraceOnGrowth(out); + Cavl* const rt = cavlPrivateRetraceOnGrowth(out); if (rt != NULL) { *root = rt; @@ -321,7 +320,7 @@ static inline void cavlRemove(Cavl** const root, const Cavl* const node) Cavl* c = NULL; for (;;) { - c = _cavlAdjustBalance(p, !r); + c = cavlPrivateAdjustBalance(p, !r); p = c->up; if ((c->bf != 0) || (p == NULL)) // Reached the root or the height difference is absorbed by c. { diff --git a/test.cpp b/test.cpp index 2c5c29a..fad3764 100644 --- a/test.cpp +++ b/test.cpp @@ -160,15 +160,11 @@ void printGraphviz(const Node* const nd) traverse(nd, [](const Node* const x) { if (x->lr[0] != nullptr) { - std::printf("%u:sw->%u:n;", - unsigned(x->value), - unsigned(reinterpret_cast*>(x->lr[0])->value)); + std::printf("%u:sw->%u:n;", unsigned(x->value), unsigned(reinterpret_cast*>(x->lr[0])->value)); } if (x->lr[1] != nullptr) { - std::printf("%u:se->%u:n;", - unsigned(x->value), - unsigned(reinterpret_cast*>(x->lr[1])->value)); + std::printf("%u:se->%u:n;", unsigned(x->value), unsigned(reinterpret_cast*>(x->lr[1])->value)); } }); std::puts("\n}"); @@ -286,7 +282,7 @@ void testRotation() print(&x); std::printf("After left rotation:\n"); - _cavlRotate(&x, false); // z is now the root + cavlPrivateRotate(&x, false); // z is now the root TEST_ASSERT_NULL(findBrokenAncestry(&z)); print(&z); TEST_ASSERT_EQUAL(&a, x.lr[0]); @@ -295,7 +291,7 @@ void testRotation() TEST_ASSERT_EQUAL(&c, z.lr[1]); std::printf("After right rotation, back into the original configuration:\n"); - _cavlRotate(&z, true); // x is now the root + cavlPrivateRotate(&z, true); // x is now the root TEST_ASSERT_NULL(findBrokenAncestry(&x)); print(&x); TEST_ASSERT_EQUAL(&a, x.lr[0]); @@ -330,11 +326,11 @@ void testBalancingA() y.lr[1] = &g; print(&x); TEST_ASSERT_NULL(findBrokenAncestry(&x)); - TEST_ASSERT_EQUAL(&x, _cavlAdjustBalance(&x, false)); // bf = -1, same topology + TEST_ASSERT_EQUAL(&x, cavlPrivateAdjustBalance(&x, false)); // bf = -1, same topology TEST_ASSERT_EQUAL(-1, x.bf); - TEST_ASSERT_EQUAL(&z, _cavlAdjustBalance(&z, true)); // bf = +1, same topology + TEST_ASSERT_EQUAL(&z, cavlPrivateAdjustBalance(&z, true)); // bf = +1, same topology TEST_ASSERT_EQUAL(+1, z.bf); - TEST_ASSERT_EQUAL(&y, _cavlAdjustBalance(&x, false)); // bf = -2, rotation needed + TEST_ASSERT_EQUAL(&y, cavlPrivateAdjustBalance(&x, false)); // bf = -2, rotation needed print(&y); TEST_ASSERT_NULL(findBrokenBalanceFactor(&y)); // Should be balanced now. TEST_ASSERT_NULL(findBrokenAncestry(&y)); @@ -379,13 +375,13 @@ void testBalancingB() g = {{&y, {Zz, Zz}, 0}, 7}; print(&x); TEST_ASSERT_NULL(findBrokenAncestry(&x)); - TEST_ASSERT_EQUAL(&x, _cavlAdjustBalance(&x, false)); // bf = -1, same topology + TEST_ASSERT_EQUAL(&x, cavlPrivateAdjustBalance(&x, false)); // bf = -1, same topology TEST_ASSERT_EQUAL(-1, x.bf); - TEST_ASSERT_EQUAL(&z, _cavlAdjustBalance(&z, true)); // bf = +1, same topology + TEST_ASSERT_EQUAL(&z, cavlPrivateAdjustBalance(&z, true)); // bf = +1, same topology TEST_ASSERT_EQUAL(+1, z.bf); - TEST_ASSERT_EQUAL(&y, _cavlAdjustBalance(&y, true)); // bf = +1, same topology + TEST_ASSERT_EQUAL(&y, cavlPrivateAdjustBalance(&y, true)); // bf = +1, same topology TEST_ASSERT_EQUAL(+1, y.bf); - TEST_ASSERT_EQUAL(&y, _cavlAdjustBalance(&x, false)); // bf = -2, rotation needed + TEST_ASSERT_EQUAL(&y, cavlPrivateAdjustBalance(&x, false)); // bf = -2, rotation needed print(&y); TEST_ASSERT_NULL(findBrokenBalanceFactor(&y)); // Should be balanced now. TEST_ASSERT_NULL(findBrokenAncestry(&y)); @@ -430,11 +426,11 @@ void testBalancingC() g = {{&d, {Zz, Zz}, 0}, 7}; print(&x); TEST_ASSERT_NULL(findBrokenAncestry(&x)); - TEST_ASSERT_EQUAL(&x, _cavlAdjustBalance(&x, false)); // bf = -1, same topology + TEST_ASSERT_EQUAL(&x, cavlPrivateAdjustBalance(&x, false)); // bf = -1, same topology TEST_ASSERT_EQUAL(-1, x.bf); - TEST_ASSERT_EQUAL(&z, _cavlAdjustBalance(&z, false)); // bf = -1, same topology + TEST_ASSERT_EQUAL(&z, cavlPrivateAdjustBalance(&z, false)); // bf = -1, same topology TEST_ASSERT_EQUAL(-1, z.bf); - TEST_ASSERT_EQUAL(&z, _cavlAdjustBalance(&x, false)); + TEST_ASSERT_EQUAL(&z, cavlPrivateAdjustBalance(&x, false)); print(&z); TEST_ASSERT_NULL(findBrokenBalanceFactor(&z)); TEST_ASSERT_NULL(findBrokenAncestry(&z)); @@ -478,7 +474,7 @@ void testRetracingOnGrowth() print(&t[50]); // The tree is imbalanced because we just added 1 and are about to retrace it. TEST_ASSERT_NULL(findBrokenAncestry(&t[50])); TEST_ASSERT_EQUAL(6, checkAscension(&t[50])); - TEST_ASSERT_EQUAL(&t[30], _cavlRetraceOnGrowth(&t[10])); + TEST_ASSERT_EQUAL(&t[30], cavlPrivateRetraceOnGrowth(&t[10])); std::puts("ADD 10:"); print(&t[30]); // This is the new root. TEST_ASSERT_EQUAL(&t[20], t[30].lr[0]); @@ -508,7 +504,7 @@ void testRetracingOnGrowth() TEST_ASSERT_NULL(findBrokenBalanceFactor(&t[30])); t[21] = {&t[20], {Zzzzzz, Zzzzzz}, 0}; t[20].lr[1] = &t[21]; - TEST_ASSERT_NULL(_cavlRetraceOnGrowth(&t[21])); // Root not reached, NULL returned. + TEST_ASSERT_NULL(cavlPrivateRetraceOnGrowth(&t[21])); // Root not reached, NULL returned. std::puts("ADD 21:"); print(&t[30]); TEST_ASSERT_EQUAL(0, t[20].bf); @@ -575,7 +571,7 @@ void testRetracingOnGrowth() TEST_ASSERT_EQUAL(7, checkAscension(&t[30])); t[15] = {&t[10], {Zzzzzz, Zzzzzz}, 0}; t[10].lr[1] = &t[15]; - TEST_ASSERT_EQUAL(&t[30], _cavlRetraceOnGrowth(&t[15])); // Same root, its balance becomes -1. + TEST_ASSERT_EQUAL(&t[30], cavlPrivateRetraceOnGrowth(&t[15])); // Same root, its balance becomes -1. print(&t[30]); TEST_ASSERT_EQUAL(+1, t[10].bf); TEST_ASSERT_EQUAL(-1, t[20].bf); @@ -587,7 +583,7 @@ void testRetracingOnGrowth() std::puts("ADD 17:"); t[17] = {&t[15], {Zzzzzz, Zzzzzz}, 0}; t[15].lr[1] = &t[17]; - TEST_ASSERT_EQUAL(nullptr, _cavlRetraceOnGrowth(&t[17])); // Same root, same balance, 10 rotated left. + TEST_ASSERT_EQUAL(nullptr, cavlPrivateRetraceOnGrowth(&t[17])); // Same root, same balance, 10 rotated left. print(&t[30]); // Check 10 TEST_ASSERT_EQUAL(&t[15], t[10].up); @@ -622,7 +618,7 @@ void testRetracingOnGrowth() std::puts("ADD 18:"); t[18] = {&t[17], {Zzzzzz, Zzzzzz}, 0}; t[17].lr[1] = &t[18]; - TEST_ASSERT_EQUAL(nullptr, _cavlRetraceOnGrowth(&t[18])); // Same root, 15 went left, 20 went right. + TEST_ASSERT_EQUAL(nullptr, cavlPrivateRetraceOnGrowth(&t[18])); // Same root, 15 went left, 20 went right. print(&t[30]); // Check 17 TEST_ASSERT_EQUAL(&t[30], t[17].up);