[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