summaryrefslogtreecommitdiff
path: root/src/libdatastruct/avlnode_insertnode.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libdatastruct/avlnode_insertnode.c')
-rw-r--r--src/libdatastruct/avlnode_insertnode.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/src/libdatastruct/avlnode_insertnode.c b/src/libdatastruct/avlnode_insertnode.c
new file mode 100644
index 0000000..c69b34e
--- /dev/null
+++ b/src/libdatastruct/avlnode_insertnode.c
@@ -0,0 +1,42 @@
+/* ISC license. */
+
+#include <skalibs/functypes.h>
+#include <skalibs/avlnode.h>
+#include "avlnode-internal.h"
+
+unsigned int avlnode_insertnode (avlnode_ref s, unsigned int max, unsigned int r, unsigned int i, dtokfunc_t_ref dtok, cmpfunc_t_ref f, void *p)
+{
+ unsigned int stack[AVLNODE_MAXDEPTH] ;
+ int spin[AVLNODE_MAXDEPTH] ;
+ unsigned int sp = 0 ;
+
+ {
+ register void const *k = (*dtok)(s[i].data, p) ;
+ for (; r < max ; sp++)
+ {
+ spin[sp] = avlnode_ufroms((*f)(k, (*dtok)(s[r].data, p), p)) ;
+ stack[sp] = r ;
+ r = s[r].child[spin[sp]] ;
+ }
+ }
+ r = i ;
+ while (sp--)
+ {
+ s[stack[sp]].child[spin[sp]] = r ;
+ r = stack[sp] ;
+ if (s[r].balance) goto lastfix ;
+ s[r].balance = avlnode_sfromu(spin[sp]) ;
+ }
+ return r ;
+
+ lastfix:
+ if (avlnode_ufroms(s[r].balance) != spin[sp])
+ {
+ s[r].balance = 0 ;
+ return stack[0] ;
+ }
+ r = avlnode_rotate_maydouble(s, max, r, !spin[sp], spin[sp] != spin[sp+1]) ;
+ if (!sp--) return r ;
+ s[stack[sp]].child[spin[sp]] = r ;
+ return stack[0] ;
+}