[GRASS-SVN] r71465 - grass/trunk/lib/btree2
svn_grass at osgeo.org
svn_grass at osgeo.org
Mon Sep 4 13:25:47 PDT 2017
Author: mmetz
Date: 2017-09-04 13:25:47 -0700 (Mon, 04 Sep 2017)
New Revision: 71465
Modified:
grass/trunk/lib/btree2/kdtree.c
Log:
btree2lib: improve kdtree balancing
Modified: grass/trunk/lib/btree2/kdtree.c
===================================================================
--- grass/trunk/lib/btree2/kdtree.c 2017-09-04 18:15:15 UTC (rev 71464)
+++ grass/trunk/lib/btree2/kdtree.c 2017-09-04 20:25:47 UTC (rev 71465)
@@ -100,7 +100,6 @@
if (t->btol < 2)
t->btol = 2;
}
- t->btol = 7;
t->nextdim = G_malloc(ndims * sizeof(char));
for (i = 0; i < ndims - 1; i++)
@@ -254,10 +253,10 @@
ld = (!n->child[0] ? -1 : n->child[0]->depth);
rd = (!n->child[1] ? -1 : n->child[1]->depth);
n->depth = MAX(ld, rd) + 1;
+
+ while (kdtree_balance(t, n, 0));
}
- while (kdtree_balance(t, t->root, 0));
-
return 1;
}
@@ -290,7 +289,25 @@
while (s[top].n) {
n = s[top].n;
+ ld = (!n->child[0] ? -1 : n->child[0]->depth);
+ rd = (!n->child[1] ? -1 : n->child[1]->depth);
+
+ dir = (rd > ld);
+
+ top++;
+ s[top].n = n->child[dir];
+ }
+
+ while (top) {
+ top--;
+ n = s[top].n;
+
/* balance node */
+ while (kdtree_balance(t, n->child[0], level));
+ while (kdtree_balance(t, n->child[1], level));
+ ld = (!n->child[0] ? -1 : n->child[0]->depth);
+ rd = (!n->child[1] ? -1 : n->child[1]->depth);
+ n->depth = MAX(ld, rd) + 1;
while (kdtree_balance(t, n, level)) {
while (kdtree_balance(t, n->child[0], level));
while (kdtree_balance(t, n->child[1], level));
@@ -300,10 +317,30 @@
n->depth = MAX(ld, rd) + 1;
nbal++;
}
+ }
+ while (s[top].n) {
+ n = s[top].n;
+
+ /* balance node */
+ while (kdtree_balance(t, n->child[0], level));
+ while (kdtree_balance(t, n->child[1], level));
ld = (!n->child[0] ? -1 : n->child[0]->depth);
rd = (!n->child[1] ? -1 : n->child[1]->depth);
+ n->depth = MAX(ld, rd) + 1;
+ while (kdtree_balance(t, n, level)) {
+ while (kdtree_balance(t, n->child[0], level));
+ while (kdtree_balance(t, n->child[1], level));
+ ld = (!n->child[0] ? -1 : n->child[0]->depth);
+ rd = (!n->child[1] ? -1 : n->child[1]->depth);
+ n->depth = MAX(ld, rd) + 1;
+ nbal++;
+ }
+
+ ld = (!n->child[0] ? -1 : n->child[0]->depth);
+ rd = (!n->child[1] ? -1 : n->child[1]->depth);
+
dir = (rd > ld);
top++;
@@ -327,6 +364,12 @@
n = s[top].n;
/* balance node */
+ while (kdtree_balance(t, n->child[0], level));
+ while (kdtree_balance(t, n->child[1], level));
+
+ ld = (!n->child[0] ? -1 : n->child[0]->depth);
+ rd = (!n->child[1] ? -1 : n->child[1]->depth);
+ n->depth = MAX(ld, rd) + 1;
while (kdtree_balance(t, n, level)) {
while (kdtree_balance(t, n->child[0], level));
while (kdtree_balance(t, n->child[1], level));
@@ -976,8 +1019,11 @@
rd = (!n->child[1] ? -1 : n->child[1]->depth);
n->depth = MAX(ld, rd) + 1;
+#if 0
+ /* this can cause stack overflow because of too high levels of recursion */
if (bmode > 1)
while (kdtree_balance(t, n, bmode));
+#endif
if (n->depth == old_depth)
top = 0;
@@ -1089,7 +1135,7 @@
struct kdnode *nnew,
int balance, int dc)
{
- struct kdnode *n, *n2;
+ struct kdnode *n;
struct kdstack {
struct kdnode *n;
int dir;
@@ -1113,66 +1159,17 @@
if (rcallsmax < rcalls)
rcallsmax = rcalls;
- /* most optimal tree: bmode = 2, only bottom-up balancing
- * fastest tree building: bmode = 0 with a priori, top-down and
- * bottom-up balancing */
- bmode = 0;
+ /* balancing modes
+ * bmode = 0: a posteriori, top-down and bottom-up balancing, no recursion
+ * slow, high tree depth (sub-optimal tree)
+ * bmode = 1: top-down and bottom-up balancing, recursion
+ * faster, lower tree depth (more optimal tree)
+ * bmode = 2: bottom-up balancing
+ * fastest, tree depth similar to bmode = 1
+ * most optimal, but slowest: recursion, bottom-up, a posteriori
+ * */
+ bmode = 2;
- if (balance && bmode == 0) {
- int diffl, diffr;
-
- top = 0;
- s[top].n = r;
- while (s[top].n) {
- n = s[top].n;
-
- /* balance node */
- while (kdtree_balance(t, n, bmode)) {
- while (kdtree_balance(t, n->child[0], bmode));
- while (kdtree_balance(t, n->child[1], bmode));
-
- ld = (!n->child[0] ? -1 : n->child[0]->depth);
- rd = (!n->child[1] ? -1 : n->child[1]->depth);
- n->depth = MAX(ld, rd) + 1;
- }
-
- diffl = diffr = -1;
- if (n->child[0]) {
- n2 = n->child[0];
- ld = (!n2->child[0] ? -1 : n2->child[0]->depth);
- rd = (!n2->child[1] ? -1 : n2->child[1]->depth);
-
- diffl = ld - rd;
- if (diffl < 0)
- diffl = -diffl;
- }
- if (n->child[1]) {
- n2 = n->child[1];
- ld = (!n2->child[0] ? -1 : n2->child[0]->depth);
- rd = (!n2->child[1] ? -1 : n2->child[1]->depth);
-
- diffr = ld - rd;
- if (diffr < 0)
- diffr = -diffr;
- }
-
- dir = (diffr > diffl);
-
- top++;
- s[top].n = n->child[dir];
- }
-
- while (top) {
- top--;
- n = s[top].n;
-
- /* update node depth */
- ld = (!n->child[0] ? -1 : n->child[0]->depth);
- rd = (!n->child[1] ? -1 : n->child[1]->depth);
- n->depth = MAX(ld, rd) + 1;
- }
- }
-
/* find node with free child */
top = 0;
go_back = 0;
@@ -1182,9 +1179,15 @@
n = s[top].n;
if (balance && bmode < 2) {
+ /* balance node */
old_depth = n->depth;
- /* balance node */
+ while (kdtree_balance(t, n->child[0], bmode));
+ while (kdtree_balance(t, n->child[1], bmode));
+
+ ld = (!n->child[0] ? -1 : n->child[0]->depth);
+ rd = (!n->child[1] ? -1 : n->child[1]->depth);
+ n->depth = MAX(ld, rd) + 1;
while (kdtree_balance(t, n, bmode)) {
while (kdtree_balance(t, n->child[0], bmode));
while (kdtree_balance(t, n->child[1], bmode));
@@ -1193,7 +1196,6 @@
rd = (!n->child[1] ? -1 : n->child[1]->depth);
n->depth = MAX(ld, rd) + 1;
}
-
if (old_depth != n->depth)
go_back = top;
}
@@ -1234,6 +1236,12 @@
if (balance) {
/* balance parent */
+ while (kdtree_balance(t, n->child[0], bmode));
+ while (kdtree_balance(t, n->child[1], bmode));
+
+ ld = (!n->child[0] ? -1 : n->child[0]->depth);
+ rd = (!n->child[1] ? -1 : n->child[1]->depth);
+ n->depth = MAX(ld, rd) + 1;
while (kdtree_balance(t, n, bmode)) {
while (kdtree_balance(t, n->child[0], bmode));
while (kdtree_balance(t, n->child[1], bmode));
@@ -1249,11 +1257,6 @@
}
/* go back up */
-#ifdef KD_DEBUG
- go_back = top;
-#endif
- top = go_back;
-
while (top) {
top--;
n = s[top].n;
@@ -1265,6 +1268,15 @@
if (balance) {
/* balance node */
+ /* slightly reduced tree depth, a bit slower: */
+ /*
+ while (kdtree_balance(t, n->child[0], bmode));
+ while (kdtree_balance(t, n->child[1], bmode));
+ */
+
+ ld = (!n->child[0] ? -1 : n->child[0]->depth);
+ rd = (!n->child[1] ? -1 : n->child[1]->depth);
+ n->depth = MAX(ld, rd) + 1;
while (kdtree_balance(t, n, bmode)) {
while (kdtree_balance(t, n->child[0], bmode));
while (kdtree_balance(t, n->child[1], bmode));
@@ -1288,6 +1300,55 @@
#endif
}
+ if (balance && bmode == 0) {
+ top = 0;
+ go_back = 0;
+ s[top].n = r;
+ while (s[top].n) {
+ n = s[top].n;
+ old_depth = n->depth;
+
+ /* balance node */
+ while (kdtree_balance(t, n->child[0], bmode));
+ while (kdtree_balance(t, n->child[1], bmode));
+
+ ld = (!n->child[0] ? -1 : n->child[0]->depth);
+ rd = (!n->child[1] ? -1 : n->child[1]->depth);
+ n->depth = MAX(ld, rd) + 1;
+ while (kdtree_balance(t, n, bmode)) {
+ /*
+ while (kdtree_balance(t, n->child[0], bmode));
+ while (kdtree_balance(t, n->child[1], bmode));
+ */
+
+ ld = (!n->child[0] ? -1 : n->child[0]->depth);
+ rd = (!n->child[1] ? -1 : n->child[1]->depth);
+ n->depth = MAX(ld, rd) + 1;
+ }
+ if (old_depth != n->depth)
+ go_back = top;
+
+ ld = (!n->child[0] ? -1 : n->child[0]->depth);
+ rd = (!n->child[1] ? -1 : n->child[1]->depth);
+
+ dir = (ld < rd);
+
+ top++;
+ s[top].n = n->child[dir];
+ }
+
+ top = go_back;
+ while (top) {
+ top--;
+ n = s[top].n;
+
+ /* update node depth */
+ ld = (!n->child[0] ? -1 : n->child[0]->depth);
+ rd = (!n->child[1] ? -1 : n->child[1]->depth);
+ n->depth = MAX(ld, rd) + 1;
+ }
+ }
+
rcalls--;
return r;
More information about the grass-commit
mailing list