xref: /freebsd/lib/libc/stdlib/tdelete.c (revision 64566a3e2ab2e0c5a7597e4a777e31d397fbfb91)
164566a3eSAlfred Perlstein /*	$NetBSD: tdelete.c,v 1.2 1999/09/16 11:45:37 lukem Exp $	*/
264566a3eSAlfred Perlstein /* $FreeBSD$ */
364566a3eSAlfred Perlstein 
464566a3eSAlfred Perlstein /*
564566a3eSAlfred Perlstein  * Tree search generalized from Knuth (6.2.2) Algorithm T just like
664566a3eSAlfred Perlstein  * the AT&T man page says.
764566a3eSAlfred Perlstein  *
864566a3eSAlfred Perlstein  * The node_t structure is for internal use only, lint doesn't grok it.
964566a3eSAlfred Perlstein  *
1064566a3eSAlfred Perlstein  * Written by reading the System V Interface Definition, not the code.
1164566a3eSAlfred Perlstein  *
1264566a3eSAlfred Perlstein  * Totally public domain.
1364566a3eSAlfred Perlstein  */
1464566a3eSAlfred Perlstein 
1564566a3eSAlfred Perlstein #include <sys/cdefs.h>
1664566a3eSAlfred Perlstein #if defined(LIBC_SCCS) && !defined(lint)
1764566a3eSAlfred Perlstein __RCSID("$NetBSD: tdelete.c,v 1.2 1999/09/16 11:45:37 lukem Exp $");
1864566a3eSAlfred Perlstein #endif /* LIBC_SCCS and not lint */
1964566a3eSAlfred Perlstein 
2064566a3eSAlfred Perlstein #include <assert.h>
2164566a3eSAlfred Perlstein #define _SEARCH_PRIVATE
2264566a3eSAlfred Perlstein #include <search.h>
2364566a3eSAlfred Perlstein #include <stdlib.h>
2464566a3eSAlfred Perlstein 
2564566a3eSAlfred Perlstein 
2664566a3eSAlfred Perlstein /* delete node with given key */
2764566a3eSAlfred Perlstein void *
2864566a3eSAlfred Perlstein tdelete(vkey, vrootp, compar)
2964566a3eSAlfred Perlstein 	const void *vkey;	/* key to be deleted */
3064566a3eSAlfred Perlstein 	void      **vrootp;	/* address of the root of tree */
3164566a3eSAlfred Perlstein 	int       (*compar) __P((const void *, const void *));
3264566a3eSAlfred Perlstein {
3364566a3eSAlfred Perlstein 	node_t **rootp = (node_t **)vrootp;
3464566a3eSAlfred Perlstein 	node_t *p, *q, *r;
3564566a3eSAlfred Perlstein 	int  cmp;
3664566a3eSAlfred Perlstein 
3764566a3eSAlfred Perlstein 	if (rootp == NULL || (p = *rootp) == NULL)
3864566a3eSAlfred Perlstein 		return NULL;
3964566a3eSAlfred Perlstein 
4064566a3eSAlfred Perlstein 	while ((cmp = (*compar)(vkey, (*rootp)->key)) != 0) {
4164566a3eSAlfred Perlstein 		p = *rootp;
4264566a3eSAlfred Perlstein 		rootp = (cmp < 0) ?
4364566a3eSAlfred Perlstein 		    &(*rootp)->llink :		/* follow llink branch */
4464566a3eSAlfred Perlstein 		    &(*rootp)->rlink;		/* follow rlink branch */
4564566a3eSAlfred Perlstein 		if (*rootp == NULL)
4664566a3eSAlfred Perlstein 			return NULL;		/* key not found */
4764566a3eSAlfred Perlstein 	}
4864566a3eSAlfred Perlstein 	r = (*rootp)->rlink;			/* D1: */
4964566a3eSAlfred Perlstein 	if ((q = (*rootp)->llink) == NULL)	/* Left NULL? */
5064566a3eSAlfred Perlstein 		q = r;
5164566a3eSAlfred Perlstein 	else if (r != NULL) {			/* Right link is NULL? */
5264566a3eSAlfred Perlstein 		if (r->llink == NULL) {		/* D2: Find successor */
5364566a3eSAlfred Perlstein 			r->llink = q;
5464566a3eSAlfred Perlstein 			q = r;
5564566a3eSAlfred Perlstein 		} else {			/* D3: Find NULL link */
5664566a3eSAlfred Perlstein 			for (q = r->llink; q->llink != NULL; q = r->llink)
5764566a3eSAlfred Perlstein 				r = q;
5864566a3eSAlfred Perlstein 			r->llink = q->rlink;
5964566a3eSAlfred Perlstein 			q->llink = (*rootp)->llink;
6064566a3eSAlfred Perlstein 			q->rlink = (*rootp)->rlink;
6164566a3eSAlfred Perlstein 		}
6264566a3eSAlfred Perlstein 	}
6364566a3eSAlfred Perlstein 	free(*rootp);				/* D4: Free node */
6464566a3eSAlfred Perlstein 	*rootp = q;				/* link parent to new node */
6564566a3eSAlfred Perlstein 	return p;
6664566a3eSAlfred Perlstein }
67