summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-12-18 13:22:11 -0800
committerKaz Kylheku <kaz@kylheku.com>2021-12-18 13:22:11 -0800
commit095232d6c245d2669eacb7056a8d94293ba8a501 (patch)
tree811a88bc0646c39aad677ba2b045acfdd396e058
parent517c875d3288be0b31f59faafdd84bb181dfc22c (diff)
downloadtxr-095232d6c245d2669eacb7056a8d94293ba8a501.tar.gz
txr-095232d6c245d2669eacb7056a8d94293ba8a501.tar.bz2
txr-095232d6c245d2669eacb7056a8d94293ba8a501.zip
tree: bugfix wrong tree-count.
When duplicate keys are inserted in the default way with replacement, the tree size must not be incremented. * tree.c (tr_insert): Increment the tr->size and maintain tr->max_size here. In the case of replacing an existing node, do not touch the count. * tests/010/tree.tl: Add test cases covering duplicate insertion and tree-count. (tree_insert_node): Remove unconditional size increment.
-rw-r--r--tests/010/tree.tl10
-rw-r--r--tree.c6
2 files changed, 14 insertions, 2 deletions
diff --git a/tests/010/tree.tl b/tests/010/tree.tl
index 898fd91d..79bab793 100644
--- a/tests/010/tree.tl
+++ b/tests/010/tree.tl
@@ -216,3 +216,13 @@
(let* ((items (make-items))
(tr (tree items : : : t)))
(vtest (vec-list [mapcar .label tr]) [mapcar .label items]))
+
+(let ((tr (tree)))
+ (mtest
+ (tree-insert tr 1) #N(1 nil nil)
+ (tree-insert tr 1) #N(1 nil nil)
+ (tree-insert tr 1) #N(1 nil nil))
+ (tree-insert tr 2)
+ (test (tree-count tr) 2)
+ (tree-insert tr 1 t)
+ (test (tree-count tr) 3))
diff --git a/tree.c b/tree.c
index c3ddd756..8af798ad 100644
--- a/tree.c
+++ b/tree.c
@@ -379,6 +379,8 @@ static void tr_insert(val tree, struct tree *tr, struct tree_iter *ti,
} else {
int dep = ti->depth + 1;
set(mkloc(subtree->tn.left, subtree), node);
+ if (++tr->size > tr->max_size)
+ tr->max_size = tr->size;
if (subtree->tn.right == nil && (((ucnum) 1) << dep) > tr->size) {
set(mkloc(ti->path[ti->depth++], ti->self), subtree);
tr_find_rebuild_scapegoat(tree, tr, ti, node, 1);
@@ -408,6 +410,8 @@ static void tr_insert(val tree, struct tree *tr, struct tree_iter *ti,
} else {
int dep = ti->depth + 1;
set(mkloc(subtree->tn.right, subtree), node);
+ if (++tr->size > tr->max_size)
+ tr->max_size = tr->size;
if (subtree->tn.left == nil && (((ucnum) 1) << dep) > tr->size) {
set(mkloc(ti->path[ti->depth++], ti->self), subtree);
tr_find_rebuild_scapegoat(tree, tr, ti, node, 1);
@@ -608,8 +612,6 @@ val tree_insert_node(val tree, val node, val dup_in)
set(mkloc(tr->root, tree), node);
} else {
struct tree_iter ti = tree_iter_init(0);
- if (++tr->size > tr->max_size)
- tr->max_size = tr->size;
tr_insert(tree, tr, &ti, tr->root, node, dup);
}