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