Home | History | Annotate | Download | only in stdlib
      1 /*	$OpenBSD: tsearch.c,v 1.8 2014/03/16 18:38:30 guenther Exp $	*/
      2 
      3 /*
      4  * Tree search generalized from Knuth (6.2.2) Algorithm T just like
      5  * the AT&T man page says.
      6  *
      7  * The node_t structure is for internal use only
      8  *
      9  * Written by reading the System V Interface Definition, not the code.
     10  *
     11  * Totally public domain.
     12  */
     13 /*LINTLIBRARY*/
     14 
     15 #include <search.h>
     16 #include <stdlib.h>
     17 
     18 typedef struct node_t {
     19     char	  *key;
     20     struct node_t *left, *right;
     21 } node;
     22 
     23 /* find or insert datum into search tree */
     24 void *
     25 tsearch(const void *vkey, void **vrootp,
     26     int (*compar)(const void *, const void *))
     27 {
     28     node *q;
     29     char *key = (char *)vkey;
     30     node **rootp = (node **)vrootp;
     31 
     32     if (rootp == (struct node_t **)0)
     33 	return ((void *)0);
     34     while (*rootp != (struct node_t *)0) {	/* Knuth's T1: */
     35 	int r;
     36 
     37 	if ((r = (*compar)(key, (*rootp)->key)) == 0)	/* T2: */
     38 	    return ((void *)*rootp);		/* we found it! */
     39 	rootp = (r < 0) ?
     40 	    &(*rootp)->left :		/* T3: follow left branch */
     41 	    &(*rootp)->right;		/* T4: follow right branch */
     42     }
     43     q = (node *) malloc(sizeof(node));	/* T5: key not found */
     44     if (q != (struct node_t *)0) {	/* make new node */
     45 	*rootp = q;			/* link new node to old */
     46 	q->key = key;			/* initialize new node */
     47 	q->left = q->right = (struct node_t *)0;
     48     }
     49     return ((void *)q);
     50 }
     51 
     52 /* delete node with given key */
     53 void *
     54 tdelete(const void *vkey, void **vrootp,
     55     int (*compar)(const void *, const void *))
     56 {
     57     node **rootp = (node **)vrootp;
     58     char *key = (char *)vkey;
     59     node *p = (node *)1;
     60     node *q;
     61     node *r;
     62     int cmp;
     63 
     64     if (rootp == (struct node_t **)0 || *rootp == (struct node_t *)0)
     65 	return ((struct node_t *)0);
     66     while ((cmp = (*compar)(key, (*rootp)->key)) != 0) {
     67 	p = *rootp;
     68 	rootp = (cmp < 0) ?
     69 	    &(*rootp)->left :		/* follow left branch */
     70 	    &(*rootp)->right;		/* follow right branch */
     71 	if (*rootp == (struct node_t *)0)
     72 	    return ((void *)0);		/* key not found */
     73     }
     74     r = (*rootp)->right;			/* D1: */
     75     if ((q = (*rootp)->left) == (struct node_t *)0)	/* Left (struct node_t *)0? */
     76 	q = r;
     77     else if (r != (struct node_t *)0) {		/* Right link is null? */
     78 	if (r->left == (struct node_t *)0) {	/* D2: Find successor */
     79 	    r->left = q;
     80 	    q = r;
     81 	} else {			/* D3: Find (struct node_t *)0 link */
     82 	    for (q = r->left; q->left != (struct node_t *)0; q = r->left)
     83 		r = q;
     84 	    r->left = q->right;
     85 	    q->left = (*rootp)->left;
     86 	    q->right = (*rootp)->right;
     87 	}
     88     }
     89     free((struct node_t *) *rootp);	/* D4: Free node */
     90     *rootp = q;				/* link parent to new node */
     91     return(p);
     92 }
     93 
     94 /* Walk the nodes of a tree */
     95 static void
     96 trecurse(node *root, void (*action)(const void *, VISIT, int), int level)
     97 {
     98     if (root->left == (struct node_t *)0 && root->right == (struct node_t *)0)
     99 	(*action)(root, leaf, level);
    100     else {
    101 	(*action)(root, preorder, level);
    102 	if (root->left != (struct node_t *)0)
    103 	    trecurse(root->left, action, level + 1);
    104 	(*action)(root, postorder, level);
    105 	if (root->right != (struct node_t *)0)
    106 	    trecurse(root->right, action, level + 1);
    107 	(*action)(root, endorder, level);
    108     }
    109 }
    110 
    111 /* Walk the nodes of a tree */
    112 void
    113 twalk(const void *vroot, void (*action)(const void *, VISIT, int))
    114 {
    115     node *root = (node *)vroot;
    116 
    117     if (root != (node *)0 && action != (void (*)(const void *, VISIT, int))0)
    118 	trecurse(root, action, 0);
    119 }
    120