Fix bugs of rb-tree. The bug is about searching element with key no-less-than
or no-greater-than given key.master
parent
e912288905
commit
3e34a802c7
115
rb_test.cxx
115
rb_test.cxx
|
@ -8,6 +8,8 @@ using namespace std;
|
||||||
#define RN(v) {v + KEY_VAL_DELTA, v, RB_RED}
|
#define RN(v) {v + KEY_VAL_DELTA, v, RB_RED}
|
||||||
#define BN(v) {v + KEY_VAL_DELTA, v, RB_BLACK}
|
#define BN(v) {v + KEY_VAL_DELTA, v, RB_BLACK}
|
||||||
|
|
||||||
|
#define ARRAY_SIZE(o) (sizeof((o))/sizeof((o)[0]))
|
||||||
|
|
||||||
class RB_UNIT_TEST {
|
class RB_UNIT_TEST {
|
||||||
public:
|
public:
|
||||||
// If come across a bug, turn on "dump_tree" to instruct the unit-tester
|
// If come across a bug, turn on "dump_tree" to instruct the unit-tester
|
||||||
|
@ -23,6 +25,13 @@ public:
|
||||||
_save_fail_cnt = _fail_cnt;
|
_save_fail_cnt = _fail_cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RB_UNIT_TEST(int test_id, bool dump_tree = false):
|
||||||
|
_test_id(test_id), _dump_tree(dump_tree) {
|
||||||
|
fprintf(stdout, "Testing unit test %d ...", test_id);
|
||||||
|
_rbt = rbt_create();
|
||||||
|
_save_fail_cnt = _fail_cnt;
|
||||||
|
}
|
||||||
|
|
||||||
~RB_UNIT_TEST() {
|
~RB_UNIT_TEST() {
|
||||||
if (_rbt)
|
if (_rbt)
|
||||||
rbt_destroy(_rbt);
|
rbt_destroy(_rbt);
|
||||||
|
@ -46,13 +55,39 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Search(int key, intptr_t val, bool expect_ret_val = 1) {
|
bool BulkInsert(int* val_vect, int vect_len) {
|
||||||
|
for (int i = 0; i < vect_len; i++) {
|
||||||
|
if (!InsertHelper(val_vect[i], 1)) {
|
||||||
|
_fail_cnt ++;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Search(int key, intptr_t val, RBS_RESULT expect_ret_val = RBS_EXACT) {
|
||||||
if (SearchHelper(key, val, expect_ret_val))
|
if (SearchHelper(key, val, expect_ret_val))
|
||||||
return true;
|
return true;
|
||||||
_fail_cnt ++;
|
_fail_cnt ++;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SearchLessEqu(int key, int le_key, RBS_RESULT expect_ret_val) {
|
||||||
|
if (SearchVariantHelper(key, le_key, true /*LE*/, expect_ret_val)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
_fail_cnt ++;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SearchGreaterEqu(int key, int ge_key, RBS_RESULT expect_ret_val) {
|
||||||
|
if (SearchVariantHelper(key, ge_key, false /*GE*/, expect_ret_val)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
_fail_cnt ++;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool DeleteHelper(int val, int expect_ret_val) {
|
bool DeleteHelper(int val, int expect_ret_val) {
|
||||||
if (!_rbt)
|
if (!_rbt)
|
||||||
|
@ -72,7 +107,7 @@ private:
|
||||||
if (ret == expect_ret_val && rbt_verify(_rbt) && VerifyKeyVal())
|
if (ret == expect_ret_val && rbt_verify(_rbt) && VerifyKeyVal())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
fprintf(stdout, " fail to delete %d", val);
|
fprintf(stdout, " fail to delete %d;", val);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,11 +129,11 @@ private:
|
||||||
if (ret == expect_ret_val && rbt_verify(_rbt) && VerifyKeyVal())
|
if (ret == expect_ret_val && rbt_verify(_rbt) && VerifyKeyVal())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
fprintf(stdout, " fail to insert %d", key);
|
fprintf(stdout, " fail to insert %d;", key);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SearchHelper(int key, intptr_t val, bool expect_ret_val) {
|
bool SearchHelper(int key, intptr_t val, RBS_RESULT expect_ret_val) {
|
||||||
if (!_rbt)
|
if (!_rbt)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -114,11 +149,44 @@ private:
|
||||||
if (_dump_tree)
|
if (_dump_tree)
|
||||||
Dump_Tree("after_search");
|
Dump_Tree("after_search");
|
||||||
|
|
||||||
if (ret == expect_ret_val && val == tmpval && rbt_verify(_rbt))
|
bool succ = (ret == expect_ret_val && val == tmpval);
|
||||||
|
succ = succ || expect_ret_val == RBS_FAIL;
|
||||||
|
succ = succ && rbt_verify(_rbt);
|
||||||
|
|
||||||
|
if (succ)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
fprintf(stdout, " fail to search %d", key);
|
fprintf(stdout, " fail to search %d;", key);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SearchVariantHelper(int key, int res_key,
|
||||||
|
bool le_variant, RBS_RESULT expect_ret_val) {
|
||||||
|
if (!_rbt)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (_dump_tree)
|
||||||
|
Dump_Tree("before_search");
|
||||||
|
|
||||||
|
if (!rbt_verify(_rbt))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
intptr_t res_val;
|
||||||
|
int res_key2;
|
||||||
|
RBS_RESULT ret = rbt_search_variant(_rbt, key, &res_key2, &res_val,
|
||||||
|
le_variant ? 1 : 0);
|
||||||
|
|
||||||
|
if (_dump_tree)
|
||||||
|
Dump_Tree("after_search");
|
||||||
|
|
||||||
|
bool succ = (ret == expect_ret_val) &&
|
||||||
|
(res_key2 == res_key) && (res_val == (KEY_VAL_DELTA + res_key));
|
||||||
|
succ = succ || (expect_ret_val == RBS_FAIL);
|
||||||
|
succ = succ && rbt_verify(_rbt);
|
||||||
|
if (succ)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
fprintf(stdout, " fail to search %d;", key);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,7 +238,7 @@ unit_test() {
|
||||||
// test 8.
|
// test 8.
|
||||||
{
|
{
|
||||||
rb_valcolor_t nodes[] = { BN(1), RN(2) };
|
rb_valcolor_t nodes[] = { BN(1), RN(2) };
|
||||||
RB_UNIT_TEST ut(8, nodes, 2);
|
RB_UNIT_TEST ut(8, nodes, ARRAY_SIZE(nodes));
|
||||||
ut.Delete(1);
|
ut.Delete(1);
|
||||||
ut.Delete(2);
|
ut.Delete(2);
|
||||||
}
|
}
|
||||||
|
@ -190,7 +258,7 @@ unit_test() {
|
||||||
{
|
{
|
||||||
rb_valcolor_t nodes[] = { BN(11), RN(2), BN(14), BN(1), BN(7),
|
rb_valcolor_t nodes[] = { BN(11), RN(2), BN(14), BN(1), BN(7),
|
||||||
RN(15), RN(5), RN(8) };
|
RN(15), RN(5), RN(8) };
|
||||||
RB_UNIT_TEST ut(1, nodes, sizeof(nodes)/sizeof(nodes[0]));
|
RB_UNIT_TEST ut(1, nodes, ARRAY_SIZE(nodes));
|
||||||
ut.Insert(4);
|
ut.Insert(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +267,7 @@ unit_test() {
|
||||||
{
|
{
|
||||||
rb_valcolor_t nodes[] = { BN(4), BN(2), RN(10), RN(1), BN(7),
|
rb_valcolor_t nodes[] = { BN(4), BN(2), RN(10), RN(1), BN(7),
|
||||||
BN(11), RN(6), RN(9) };
|
BN(11), RN(6), RN(9) };
|
||||||
RB_UNIT_TEST ut(2, nodes, sizeof(nodes)/sizeof(nodes[0]));
|
RB_UNIT_TEST ut(2, nodes, ARRAY_SIZE(nodes));
|
||||||
ut.Insert(8);
|
ut.Insert(8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,7 +281,7 @@ unit_test() {
|
||||||
// test 1
|
// test 1
|
||||||
{
|
{
|
||||||
rb_valcolor_t nodes[] = { BN(40), BN(20), BN(60), RN(10), RN(50), RN(70) };
|
rb_valcolor_t nodes[] = { BN(40), BN(20), BN(60), RN(10), RN(50), RN(70) };
|
||||||
RB_UNIT_TEST ut(1, nodes, sizeof(nodes)/sizeof(nodes[0]));
|
RB_UNIT_TEST ut(1, nodes, ARRAY_SIZE(nodes));
|
||||||
ut.Delete(20);
|
ut.Delete(20);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,7 +289,7 @@ unit_test() {
|
||||||
{
|
{
|
||||||
rb_valcolor_t nodes[] = { BN(40), BN(20), BN(60), RN(10), RN(30),
|
rb_valcolor_t nodes[] = { BN(40), BN(20), BN(60), RN(10), RN(30),
|
||||||
RN(50), RN(70) };
|
RN(50), RN(70) };
|
||||||
RB_UNIT_TEST ut(2, nodes, sizeof(nodes)/sizeof(nodes[0]));
|
RB_UNIT_TEST ut(2, nodes, ARRAY_SIZE(nodes));
|
||||||
ut.Delete(20);
|
ut.Delete(20);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,7 +297,7 @@ unit_test() {
|
||||||
{
|
{
|
||||||
rb_valcolor_t nodes[] = { BN(40), BN(20), BN(60), BN(10), BN(30),
|
rb_valcolor_t nodes[] = { BN(40), BN(20), BN(60), BN(10), BN(30),
|
||||||
BN(50), BN(70), RN(21) };
|
BN(50), BN(70), RN(21) };
|
||||||
RB_UNIT_TEST ut(3, nodes, sizeof(nodes)/sizeof(nodes[0]));
|
RB_UNIT_TEST ut(3, nodes, ARRAY_SIZE(nodes));
|
||||||
ut.Delete(20);
|
ut.Delete(20);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,7 +306,7 @@ unit_test() {
|
||||||
rb_valcolor_t nodes[] = { BN(8), RN(2), BN(10), BN(0), BN(4), BN(9),
|
rb_valcolor_t nodes[] = { BN(8), RN(2), BN(10), BN(0), BN(4), BN(9),
|
||||||
BN(11), BN(-1), BN(1), BN(3), RN(6),
|
BN(11), BN(-1), BN(1), BN(3), RN(6),
|
||||||
BN(5), BN(7) };
|
BN(5), BN(7) };
|
||||||
RB_UNIT_TEST ut(4, nodes, sizeof(nodes)/sizeof(nodes[0]));
|
RB_UNIT_TEST ut(4, nodes, ARRAY_SIZE(nodes));
|
||||||
ut.Delete(2);
|
ut.Delete(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,14 +319,14 @@ unit_test() {
|
||||||
BN(-11), BN(-9), BN(9), BN(11),
|
BN(-11), BN(-9), BN(9), BN(11),
|
||||||
BN(29), BN(31),
|
BN(29), BN(31),
|
||||||
BN(89), BN(91), BN(109), BN(111) };
|
BN(89), BN(91), BN(109), BN(111) };
|
||||||
RB_UNIT_TEST ut(5, nodes, sizeof(nodes)/sizeof(nodes[0]));
|
RB_UNIT_TEST ut(5, nodes, ARRAY_SIZE(nodes));
|
||||||
ut.Delete(20);
|
ut.Delete(20);
|
||||||
}
|
}
|
||||||
|
|
||||||
// test 6. For case 1' and 2'
|
// test 6. For case 1' and 2'
|
||||||
{
|
{
|
||||||
rb_valcolor_t nodes[] = { BN(4), RN(2), BN(5), BN(1), BN(3) };
|
rb_valcolor_t nodes[] = { BN(4), RN(2), BN(5), BN(1), BN(3) };
|
||||||
RB_UNIT_TEST ut(6, nodes, sizeof(nodes)/sizeof(nodes[0]));
|
RB_UNIT_TEST ut(6, nodes, ARRAY_SIZE(nodes));
|
||||||
ut.Delete(5);
|
ut.Delete(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,14 +334,14 @@ unit_test() {
|
||||||
{
|
{
|
||||||
rb_valcolor_t nodes[] = { BN(6), BN(2), BN(8), BN(1), RN(4), BN(7),
|
rb_valcolor_t nodes[] = { BN(6), BN(2), BN(8), BN(1), RN(4), BN(7),
|
||||||
BN(9), BN(3), BN(5) };
|
BN(9), BN(3), BN(5) };
|
||||||
RB_UNIT_TEST ut(7, nodes, sizeof(nodes)/sizeof(nodes[0]));
|
RB_UNIT_TEST ut(7, nodes, ARRAY_SIZE(nodes));
|
||||||
ut.Delete(8);
|
ut.Delete(8);
|
||||||
}
|
}
|
||||||
|
|
||||||
// test 8.
|
// test 8.
|
||||||
{
|
{
|
||||||
rb_valcolor_t nodes[] = { BN(1), RN(2) };
|
rb_valcolor_t nodes[] = { BN(1), RN(2) };
|
||||||
RB_UNIT_TEST ut(8, nodes, 2);
|
RB_UNIT_TEST ut(8, nodes, ARRAY_SIZE(nodes));
|
||||||
ut.Delete(1);
|
ut.Delete(1);
|
||||||
ut.Delete(2);
|
ut.Delete(2);
|
||||||
}
|
}
|
||||||
|
@ -281,7 +349,7 @@ unit_test() {
|
||||||
// test 9.
|
// test 9.
|
||||||
{
|
{
|
||||||
rb_valcolor_t nodes[] = { BN(1) };
|
rb_valcolor_t nodes[] = { BN(1) };
|
||||||
RB_UNIT_TEST ut(8, nodes, 1);
|
RB_UNIT_TEST ut(9, nodes, ARRAY_SIZE(nodes));
|
||||||
ut.Delete(1);
|
ut.Delete(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,6 +360,17 @@ unit_test() {
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// test 100
|
||||||
|
{
|
||||||
|
int val[] = { 1, 2, 3, 5, 7, 8 };
|
||||||
|
RB_UNIT_TEST ut(100);
|
||||||
|
ut.BulkInsert(val, ARRAY_SIZE(val));
|
||||||
|
ut.SearchLessEqu(4, 3, RBS_LESS);
|
||||||
|
ut.SearchLessEqu(3, 3, RBS_EXACT);
|
||||||
|
ut.SearchGreaterEqu(6, 7, RBS_GREATER);
|
||||||
|
ut.SearchGreaterEqu(7, 7, RBS_EXACT);
|
||||||
|
}
|
||||||
|
|
||||||
return RB_UNIT_TEST::Get_Fail_Cnt() == 0;
|
return RB_UNIT_TEST::Get_Fail_Cnt() == 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
2
rbtree.c
2
rbtree.c
|
@ -337,7 +337,7 @@ rbt_search_variant(rb_tree_t* rbt, int key, int* res_key, intptr_t* res_value,
|
||||||
|
|
||||||
if (res != RBS_FAIL) {
|
if (res != RBS_FAIL) {
|
||||||
if (res_key)
|
if (res_key)
|
||||||
*res_key = res_elemt - nd_vect;
|
*res_key = res_elemt->key;
|
||||||
|
|
||||||
if (res_value)
|
if (res_value)
|
||||||
*res_value = res_elemt->value;
|
*res_value = res_elemt->value;
|
||||||
|
|
Loading…
Reference in New Issue