home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include "avl.h"
-
- /* --------------------------------------------------------------------------
- * Externally accessible routines:
- *
- * HEADER *insert(rootp, newnode, cmp) Insert newnode in tree
- * HEADER *talloc(size) Allocate a new tree node
- * void tfree(p) Free a tree node
- *
- * --------------------------------------------------------------------------
- */
-
- static int (*Cmp)();
- static HEADER *Newnode;
- static HEADER *Conflicting;
-
- /* ----------------------------------------------------------------------- */
-
- HEADER *talloc(size)
- int size;
- {
- HEADER *malloc();
- HEADER *p;
-
- if(p = malloc(size + sizeof(HEADER) ) )
- {
- p->left = NULL;
- p->right = NULL;
- p->size = size;
- p->bal = B;
- p++;
- }
- return p;
- }
-
- /* ----------------------------------------------------------------------- */
-
- void tfree(p)
- HEADER *p;
- {
- free(--p);
- }
-
- /* ----------------------------------------------------------------------- */
-
- static int ins(pp)
- HEADER **pp;
- {
- HEADER *p;
- HEADER *p1,*p2;
- int relation; /* relation > 0 <==> p > Newnode
- * relation < 0 <==> p < Newnode
- * relation == 0 <==> p == Newnode
- */
-
- static int h = 0; /* Set by recursive calls to search to
- * indicate that the tree has grown.
- * It will magically change its value
- * everytime ins() is called recursively.
- */
-
- if( !(p = *pp) )
- {
- p = Newnode; /* insert node in tree */
- h = 1;
- }
- else if( (relation=(* Cmp) (p+1, Newnode+1)) == 0)
- {
- Conflicting = p + 1;
- }
- else if( relation > 0)
- {
- ins(&p->left);
-
- if(h) /* left branch has grown */
- {
- switch(p->bal)
- {
- case R:
- p->bal = B;
- h = 0;
- break;
- case B:
- p->bal = L;
- break;
- case L: /* Rebalance */
- p1 = p->left;
- if(p1->bal == L) /* Single LL */
- {
- p->left = p1->right;
- p1->right = p;
- p->bal = B;
- p = p1;
- }
- else /* Double LR */
- {
- p2 = p1->right;
- p1->right = p2->left;
- p2->left = p1;
- p->left = p2->right;
- p2->right = p;
- p->bal = (p2->bal == L) ? R : B;
- p1->bal = (p2->bal == R) ? L : B;
- p = p2;
- }
- p->bal = B;
- h = 0;
- }
- }
- }
- else
- {
- ins(&p->right);
-
- if(h) /* right branch has grown */
- {
- switch(p->bal)
- {
- case L:
- p->bal = B;
- h = 0;
- break;
- case B:
- p->bal = R;
- break;
- case R:
- p1 = p->right;
- if(p1->bal == R)
- {
- p->right = p1->left;
- p1->left = p;
- p->bal = B;
- p = p1;
- }
- else
- {
- p2 = p1->left;
- p1->left = p2->right;
- p2->right = p1;
- p->right = p2->left;
- p2->left = p;
- p->bal = (p2->bal == R) ? L : B;
- p1->bal = (p2->bal == L) ? R : B;
- p = p2;
- }
- p->bal = B;
- h = 0;
- }
- }
- }
- *pp = p;
- }
-
- /* ----------------------------------------------------------------------- */
-
- HEADER *insert(rootp, newnode, cmp)
- HEADER **rootp;
- HEADER *newnode;
- int (*cmp)();
- {
- /* Insert newnode into tree pointed to by *rootp. Cmp is passed
- * two pointers to HEADER and should work like strcmp().
- * Return NULL on success or a pointer to the conflicting node
- * on error.
- */
-
- Cmp = cmp;
- Newnode = newnode - 1;
- Conflicting = NULL;
-
- ins(rootp);
-
- return Conflicting;
- }