xref: /freebsd/contrib/libucl/src/tree.h (revision b626f5a73a48f44a31a200291b141e1da408a2ff)
197bd480fSBaptiste Daroussin /* tree.h -- AVL trees (in the spirit of BSD's 'queue.h')	-*- C -*-	*/
297bd480fSBaptiste Daroussin 
397bd480fSBaptiste Daroussin /* Copyright (c) 2005 Ian Piumarta
497bd480fSBaptiste Daroussin  *
597bd480fSBaptiste Daroussin  * All rights reserved.
697bd480fSBaptiste Daroussin  *
797bd480fSBaptiste Daroussin  * Permission is hereby granted, free of charge, to any person obtaining a copy
897bd480fSBaptiste Daroussin  * of this software and associated documentation files (the 'Software'), to deal
997bd480fSBaptiste Daroussin  * in the Software without restriction, including without limitation the rights
1097bd480fSBaptiste Daroussin  * to use, copy, modify, merge, publish, distribute, and/or sell copies of the
1197bd480fSBaptiste Daroussin  * Software, and to permit persons to whom the Software is furnished to do so,
1297bd480fSBaptiste Daroussin  * provided that the above copyright notice(s) and this permission notice appear
1397bd480fSBaptiste Daroussin  * in all copies of the Software and that both the above copyright notice(s) and
1497bd480fSBaptiste Daroussin  * this permission notice appear in supporting documentation.
1597bd480fSBaptiste Daroussin  *
1697bd480fSBaptiste Daroussin  * THE SOFTWARE IS PROVIDED 'AS IS'.  USE ENTIRELY AT YOUR OWN RISK.
1797bd480fSBaptiste Daroussin  */
1897bd480fSBaptiste Daroussin 
1997bd480fSBaptiste Daroussin /* This file defines an AVL balanced binary tree [Georgii M. Adelson-Velskii and
2097bd480fSBaptiste Daroussin  * Evgenii M. Landis, 'An algorithm for the organization of information',
2197bd480fSBaptiste Daroussin  * Doklady Akademii Nauk SSSR, 146:263-266, 1962 (Russian).  Also in Myron
2297bd480fSBaptiste Daroussin  * J. Ricci (trans.), Soviet Math, 3:1259-1263, 1962 (English)].
2397bd480fSBaptiste Daroussin  *
2497bd480fSBaptiste Daroussin  * An AVL tree is headed by pointers to the root node and to a function defining
2597bd480fSBaptiste Daroussin  * the ordering relation between nodes.  Each node contains an arbitrary payload
2697bd480fSBaptiste Daroussin  * plus three fields per tree entry: the depth of the subtree for which it forms
2797bd480fSBaptiste Daroussin  * the root and two pointers to child nodes (singly-linked for minimum space, at
2897bd480fSBaptiste Daroussin  * the expense of direct access to the parent node given a pointer to one of the
2997bd480fSBaptiste Daroussin  * children).  The tree is rebalanced after every insertion or removal.  The
3097bd480fSBaptiste Daroussin  * tree may be traversed in two directions: forward (in-order left-to-right) and
3197bd480fSBaptiste Daroussin  * reverse (in-order, right-to-left).
3297bd480fSBaptiste Daroussin  *
3397bd480fSBaptiste Daroussin  * Because of the recursive nature of many of the operations on trees it is
3497bd480fSBaptiste Daroussin  * necessary to define a number of helper functions for each type of tree node.
3597bd480fSBaptiste Daroussin  * The macro TREE_DEFINE(node_tag, entry_name) defines these functions with
3697bd480fSBaptiste Daroussin  * unique names according to the node_tag.  This macro should be invoked,
3797bd480fSBaptiste Daroussin  * thereby defining the necessary functions, once per node tag in the program.
3897bd480fSBaptiste Daroussin  *
3997bd480fSBaptiste Daroussin  * For details on the use of these macros, see the tree(3) manual page.
4097bd480fSBaptiste Daroussin  */
4197bd480fSBaptiste Daroussin 
4297bd480fSBaptiste Daroussin #ifndef __tree_h
4397bd480fSBaptiste Daroussin #define __tree_h
4497bd480fSBaptiste Daroussin 
4597bd480fSBaptiste Daroussin 
4697bd480fSBaptiste Daroussin #define TREE_DELTA_MAX	1
47*39ee7a7aSBaptiste Daroussin #ifndef _HU_FUNCTION
48*39ee7a7aSBaptiste Daroussin # if defined(__GNUC__) || defined(__clang__)
49*39ee7a7aSBaptiste Daroussin #   define _HU_FUNCTION(x) __attribute__((__unused__)) x
50*39ee7a7aSBaptiste Daroussin # else
51*39ee7a7aSBaptiste Daroussin #   define _HU_FUNCTION(x) x
52*39ee7a7aSBaptiste Daroussin # endif
53*39ee7a7aSBaptiste Daroussin #endif
5497bd480fSBaptiste Daroussin 
5597bd480fSBaptiste Daroussin #define TREE_ENTRY(type)			\
5697bd480fSBaptiste Daroussin   struct {					\
5797bd480fSBaptiste Daroussin     struct type	*avl_left;			\
5897bd480fSBaptiste Daroussin     struct type	*avl_right;			\
5997bd480fSBaptiste Daroussin     int		 avl_height;			\
6097bd480fSBaptiste Daroussin   }
6197bd480fSBaptiste Daroussin 
6297bd480fSBaptiste Daroussin #define TREE_HEAD(name, type)				\
6397bd480fSBaptiste Daroussin   struct name {						\
6497bd480fSBaptiste Daroussin     struct type *th_root;				\
6597bd480fSBaptiste Daroussin     int  (*th_cmp)(struct type *lhs, struct type *rhs);	\
6697bd480fSBaptiste Daroussin   }
6797bd480fSBaptiste Daroussin 
6897bd480fSBaptiste Daroussin #define TREE_INITIALIZER(cmp) { 0, cmp }
6997bd480fSBaptiste Daroussin 
7097bd480fSBaptiste Daroussin #define TREE_DELTA(self, field)								\
7197bd480fSBaptiste Daroussin   (( (((self)->field.avl_left)  ? (self)->field.avl_left->field.avl_height  : 0))	\
7297bd480fSBaptiste Daroussin    - (((self)->field.avl_right) ? (self)->field.avl_right->field.avl_height : 0))
7397bd480fSBaptiste Daroussin 
7497bd480fSBaptiste Daroussin /* Recursion prevents the following from being defined as macros. */
7597bd480fSBaptiste Daroussin 
7697bd480fSBaptiste Daroussin #define TREE_DEFINE(node, field)									\
7797bd480fSBaptiste Daroussin 													\
78*39ee7a7aSBaptiste Daroussin   static struct node *_HU_FUNCTION(TREE_BALANCE_##node##_##field)(struct node *);						\
7997bd480fSBaptiste Daroussin 													\
80*39ee7a7aSBaptiste Daroussin   static struct node *_HU_FUNCTION(TREE_ROTL_##node##_##field)(struct node *self)						\
8197bd480fSBaptiste Daroussin   {													\
8297bd480fSBaptiste Daroussin     struct node *r= self->field.avl_right;								\
8397bd480fSBaptiste Daroussin     self->field.avl_right= r->field.avl_left;								\
8497bd480fSBaptiste Daroussin     r->field.avl_left= TREE_BALANCE_##node##_##field(self);						\
8597bd480fSBaptiste Daroussin     return TREE_BALANCE_##node##_##field(r);								\
8697bd480fSBaptiste Daroussin   }													\
8797bd480fSBaptiste Daroussin 													\
88*39ee7a7aSBaptiste Daroussin   static struct node *_HU_FUNCTION(TREE_ROTR_##node##_##field)(struct node *self)						\
8997bd480fSBaptiste Daroussin   {													\
9097bd480fSBaptiste Daroussin     struct node *l= self->field.avl_left;								\
9197bd480fSBaptiste Daroussin     self->field.avl_left= l->field.avl_right;								\
9297bd480fSBaptiste Daroussin     l->field.avl_right= TREE_BALANCE_##node##_##field(self);						\
9397bd480fSBaptiste Daroussin     return TREE_BALANCE_##node##_##field(l);								\
9497bd480fSBaptiste Daroussin   }													\
9597bd480fSBaptiste Daroussin 													\
96*39ee7a7aSBaptiste Daroussin   static struct node *_HU_FUNCTION(TREE_BALANCE_##node##_##field)(struct node *self)						\
9797bd480fSBaptiste Daroussin   {													\
9897bd480fSBaptiste Daroussin     int delta= TREE_DELTA(self, field);									\
9997bd480fSBaptiste Daroussin 													\
10097bd480fSBaptiste Daroussin     if (delta < -TREE_DELTA_MAX)									\
10197bd480fSBaptiste Daroussin       {													\
10297bd480fSBaptiste Daroussin 	if (TREE_DELTA(self->field.avl_right, field) > 0)						\
10397bd480fSBaptiste Daroussin 	  self->field.avl_right= TREE_ROTR_##node##_##field(self->field.avl_right);			\
10497bd480fSBaptiste Daroussin 	return TREE_ROTL_##node##_##field(self);							\
10597bd480fSBaptiste Daroussin       }													\
10697bd480fSBaptiste Daroussin     else if (delta > TREE_DELTA_MAX)									\
10797bd480fSBaptiste Daroussin       {													\
10897bd480fSBaptiste Daroussin 	if (TREE_DELTA(self->field.avl_left, field) < 0)						\
10997bd480fSBaptiste Daroussin 	  self->field.avl_left= TREE_ROTL_##node##_##field(self->field.avl_left);			\
11097bd480fSBaptiste Daroussin 	return TREE_ROTR_##node##_##field(self);							\
11197bd480fSBaptiste Daroussin       }													\
11297bd480fSBaptiste Daroussin     self->field.avl_height= 0;										\
11397bd480fSBaptiste Daroussin     if (self->field.avl_left && (self->field.avl_left->field.avl_height > self->field.avl_height))	\
11497bd480fSBaptiste Daroussin       self->field.avl_height= self->field.avl_left->field.avl_height;					\
11597bd480fSBaptiste Daroussin     if (self->field.avl_right && (self->field.avl_right->field.avl_height > self->field.avl_height))	\
11697bd480fSBaptiste Daroussin       self->field.avl_height= self->field.avl_right->field.avl_height;					\
11797bd480fSBaptiste Daroussin     self->field.avl_height += 1;									\
11897bd480fSBaptiste Daroussin     return self;											\
11997bd480fSBaptiste Daroussin   }													\
12097bd480fSBaptiste Daroussin 													\
121*39ee7a7aSBaptiste Daroussin   static struct node *_HU_FUNCTION(TREE_INSERT_##node##_##field)								\
12297bd480fSBaptiste Daroussin     (struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs))		\
12397bd480fSBaptiste Daroussin   {													\
12497bd480fSBaptiste Daroussin     if (!self)												\
12597bd480fSBaptiste Daroussin       return elm;											\
12697bd480fSBaptiste Daroussin     if (compare(elm, self) < 0)										\
12797bd480fSBaptiste Daroussin       self->field.avl_left= TREE_INSERT_##node##_##field(self->field.avl_left, elm, compare);		\
12897bd480fSBaptiste Daroussin     else												\
12997bd480fSBaptiste Daroussin       self->field.avl_right= TREE_INSERT_##node##_##field(self->field.avl_right, elm, compare);		\
13097bd480fSBaptiste Daroussin     return TREE_BALANCE_##node##_##field(self);								\
13197bd480fSBaptiste Daroussin   }													\
13297bd480fSBaptiste Daroussin 													\
133*39ee7a7aSBaptiste Daroussin   static struct node *_HU_FUNCTION(TREE_FIND_##node##_##field)								\
13497bd480fSBaptiste Daroussin     (struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs))		\
13597bd480fSBaptiste Daroussin   {													\
13697bd480fSBaptiste Daroussin     if (!self)												\
13797bd480fSBaptiste Daroussin       return 0;												\
13897bd480fSBaptiste Daroussin     if (compare(elm, self) == 0)									\
13997bd480fSBaptiste Daroussin       return self;											\
14097bd480fSBaptiste Daroussin     if (compare(elm, self) < 0)										\
14197bd480fSBaptiste Daroussin       return TREE_FIND_##node##_##field(self->field.avl_left, elm, compare);				\
14297bd480fSBaptiste Daroussin     else												\
14397bd480fSBaptiste Daroussin       return TREE_FIND_##node##_##field(self->field.avl_right, elm, compare);				\
14497bd480fSBaptiste Daroussin   }													\
14597bd480fSBaptiste Daroussin 													\
146*39ee7a7aSBaptiste Daroussin   static struct node *_HU_FUNCTION(TREE_MOVE_RIGHT)(struct node *self, struct node *rhs)					\
14797bd480fSBaptiste Daroussin   {													\
14897bd480fSBaptiste Daroussin     if (!self)												\
14997bd480fSBaptiste Daroussin       return rhs;											\
15097bd480fSBaptiste Daroussin     self->field.avl_right= TREE_MOVE_RIGHT(self->field.avl_right, rhs);					\
15197bd480fSBaptiste Daroussin     return TREE_BALANCE_##node##_##field(self);								\
15297bd480fSBaptiste Daroussin   }													\
15397bd480fSBaptiste Daroussin 													\
154*39ee7a7aSBaptiste Daroussin   static struct node *_HU_FUNCTION(TREE_REMOVE_##node##_##field)								\
15597bd480fSBaptiste Daroussin     (struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs))		\
15697bd480fSBaptiste Daroussin   {													\
15797bd480fSBaptiste Daroussin     if (!self) return 0;										\
15897bd480fSBaptiste Daroussin 													\
15997bd480fSBaptiste Daroussin     if (compare(elm, self) == 0)									\
16097bd480fSBaptiste Daroussin       {													\
16197bd480fSBaptiste Daroussin 	struct node *tmp= TREE_MOVE_RIGHT(self->field.avl_left, self->field.avl_right);			\
16297bd480fSBaptiste Daroussin 	self->field.avl_left= 0;									\
16397bd480fSBaptiste Daroussin 	self->field.avl_right= 0;									\
16497bd480fSBaptiste Daroussin 	return tmp;											\
16597bd480fSBaptiste Daroussin       }													\
16697bd480fSBaptiste Daroussin     if (compare(elm, self) < 0)										\
16797bd480fSBaptiste Daroussin       self->field.avl_left= TREE_REMOVE_##node##_##field(self->field.avl_left, elm, compare);		\
16897bd480fSBaptiste Daroussin     else												\
16997bd480fSBaptiste Daroussin       self->field.avl_right= TREE_REMOVE_##node##_##field(self->field.avl_right, elm, compare);		\
17097bd480fSBaptiste Daroussin     return TREE_BALANCE_##node##_##field(self);								\
17197bd480fSBaptiste Daroussin   }													\
17297bd480fSBaptiste Daroussin 													\
173*39ee7a7aSBaptiste Daroussin   static void _HU_FUNCTION(TREE_FORWARD_APPLY_ALL_##node##_##field)								\
17497bd480fSBaptiste Daroussin     (struct node *self, void (*function)(struct node *node, void *data), void *data)			\
17597bd480fSBaptiste Daroussin   {													\
17697bd480fSBaptiste Daroussin     if (self)												\
17797bd480fSBaptiste Daroussin       {													\
17897bd480fSBaptiste Daroussin 	TREE_FORWARD_APPLY_ALL_##node##_##field(self->field.avl_left, function, data);			\
17997bd480fSBaptiste Daroussin 	function(self, data);										\
18097bd480fSBaptiste Daroussin 	TREE_FORWARD_APPLY_ALL_##node##_##field(self->field.avl_right, function, data);			\
18197bd480fSBaptiste Daroussin       }													\
18297bd480fSBaptiste Daroussin   }													\
18397bd480fSBaptiste Daroussin 													\
184*39ee7a7aSBaptiste Daroussin   static void _HU_FUNCTION(TREE_REVERSE_APPLY_ALL_##node##_##field)								\
18597bd480fSBaptiste Daroussin     (struct node *self, void (*function)(struct node *node, void *data), void *data)			\
18697bd480fSBaptiste Daroussin   {													\
18797bd480fSBaptiste Daroussin     if (self)												\
18897bd480fSBaptiste Daroussin       {													\
18997bd480fSBaptiste Daroussin 	TREE_REVERSE_APPLY_ALL_##node##_##field(self->field.avl_right, function, data);			\
19097bd480fSBaptiste Daroussin 	function(self, data);										\
19197bd480fSBaptiste Daroussin 	TREE_REVERSE_APPLY_ALL_##node##_##field(self->field.avl_left, function, data);			\
19297bd480fSBaptiste Daroussin       }													\
19397bd480fSBaptiste Daroussin   }
19497bd480fSBaptiste Daroussin 
19597bd480fSBaptiste Daroussin #define TREE_INSERT(head, node, field, elm)						\
19697bd480fSBaptiste Daroussin   ((head)->th_root= TREE_INSERT_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
19797bd480fSBaptiste Daroussin 
19897bd480fSBaptiste Daroussin #define TREE_FIND(head, node, field, elm)				\
19997bd480fSBaptiste Daroussin   (TREE_FIND_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
20097bd480fSBaptiste Daroussin 
20197bd480fSBaptiste Daroussin #define TREE_REMOVE(head, node, field, elm)						\
20297bd480fSBaptiste Daroussin   ((head)->th_root= TREE_REMOVE_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
20397bd480fSBaptiste Daroussin 
20497bd480fSBaptiste Daroussin #define TREE_DEPTH(head, field)			\
20597bd480fSBaptiste Daroussin   ((head)->th_root->field.avl_height)
20697bd480fSBaptiste Daroussin 
20797bd480fSBaptiste Daroussin #define TREE_FORWARD_APPLY(head, node, field, function, data)	\
20897bd480fSBaptiste Daroussin   TREE_FORWARD_APPLY_ALL_##node##_##field((head)->th_root, function, data)
20997bd480fSBaptiste Daroussin 
21097bd480fSBaptiste Daroussin #define TREE_REVERSE_APPLY(head, node, field, function, data)	\
21197bd480fSBaptiste Daroussin   TREE_REVERSE_APPLY_ALL_##node##_##field((head)->th_root, function, data)
21297bd480fSBaptiste Daroussin 
21397bd480fSBaptiste Daroussin #define TREE_INIT(head, cmp) do {		\
21497bd480fSBaptiste Daroussin     (head)->th_root= 0;				\
21597bd480fSBaptiste Daroussin     (head)->th_cmp= (cmp);			\
21697bd480fSBaptiste Daroussin   } while (0)
21797bd480fSBaptiste Daroussin 
21897bd480fSBaptiste Daroussin 
21997bd480fSBaptiste Daroussin #endif /* __tree_h */
220