xref: /freebsd/contrib/libucl/src/tree.h (revision 97bd480fe38abb5950359b9d864a62037b4ab5f7)
1*97bd480fSBaptiste Daroussin /* tree.h -- AVL trees (in the spirit of BSD's 'queue.h')	-*- C -*-	*/
2*97bd480fSBaptiste Daroussin 
3*97bd480fSBaptiste Daroussin /* Copyright (c) 2005 Ian Piumarta
4*97bd480fSBaptiste Daroussin  *
5*97bd480fSBaptiste Daroussin  * All rights reserved.
6*97bd480fSBaptiste Daroussin  *
7*97bd480fSBaptiste Daroussin  * Permission is hereby granted, free of charge, to any person obtaining a copy
8*97bd480fSBaptiste Daroussin  * of this software and associated documentation files (the 'Software'), to deal
9*97bd480fSBaptiste Daroussin  * in the Software without restriction, including without limitation the rights
10*97bd480fSBaptiste Daroussin  * to use, copy, modify, merge, publish, distribute, and/or sell copies of the
11*97bd480fSBaptiste Daroussin  * Software, and to permit persons to whom the Software is furnished to do so,
12*97bd480fSBaptiste Daroussin  * provided that the above copyright notice(s) and this permission notice appear
13*97bd480fSBaptiste Daroussin  * in all copies of the Software and that both the above copyright notice(s) and
14*97bd480fSBaptiste Daroussin  * this permission notice appear in supporting documentation.
15*97bd480fSBaptiste Daroussin  *
16*97bd480fSBaptiste Daroussin  * THE SOFTWARE IS PROVIDED 'AS IS'.  USE ENTIRELY AT YOUR OWN RISK.
17*97bd480fSBaptiste Daroussin  */
18*97bd480fSBaptiste Daroussin 
19*97bd480fSBaptiste Daroussin /* This file defines an AVL balanced binary tree [Georgii M. Adelson-Velskii and
20*97bd480fSBaptiste Daroussin  * Evgenii M. Landis, 'An algorithm for the organization of information',
21*97bd480fSBaptiste Daroussin  * Doklady Akademii Nauk SSSR, 146:263-266, 1962 (Russian).  Also in Myron
22*97bd480fSBaptiste Daroussin  * J. Ricci (trans.), Soviet Math, 3:1259-1263, 1962 (English)].
23*97bd480fSBaptiste Daroussin  *
24*97bd480fSBaptiste Daroussin  * An AVL tree is headed by pointers to the root node and to a function defining
25*97bd480fSBaptiste Daroussin  * the ordering relation between nodes.  Each node contains an arbitrary payload
26*97bd480fSBaptiste Daroussin  * plus three fields per tree entry: the depth of the subtree for which it forms
27*97bd480fSBaptiste Daroussin  * the root and two pointers to child nodes (singly-linked for minimum space, at
28*97bd480fSBaptiste Daroussin  * the expense of direct access to the parent node given a pointer to one of the
29*97bd480fSBaptiste Daroussin  * children).  The tree is rebalanced after every insertion or removal.  The
30*97bd480fSBaptiste Daroussin  * tree may be traversed in two directions: forward (in-order left-to-right) and
31*97bd480fSBaptiste Daroussin  * reverse (in-order, right-to-left).
32*97bd480fSBaptiste Daroussin  *
33*97bd480fSBaptiste Daroussin  * Because of the recursive nature of many of the operations on trees it is
34*97bd480fSBaptiste Daroussin  * necessary to define a number of helper functions for each type of tree node.
35*97bd480fSBaptiste Daroussin  * The macro TREE_DEFINE(node_tag, entry_name) defines these functions with
36*97bd480fSBaptiste Daroussin  * unique names according to the node_tag.  This macro should be invoked,
37*97bd480fSBaptiste Daroussin  * thereby defining the necessary functions, once per node tag in the program.
38*97bd480fSBaptiste Daroussin  *
39*97bd480fSBaptiste Daroussin  * For details on the use of these macros, see the tree(3) manual page.
40*97bd480fSBaptiste Daroussin  */
41*97bd480fSBaptiste Daroussin 
42*97bd480fSBaptiste Daroussin #ifndef __tree_h
43*97bd480fSBaptiste Daroussin #define __tree_h
44*97bd480fSBaptiste Daroussin 
45*97bd480fSBaptiste Daroussin 
46*97bd480fSBaptiste Daroussin #define TREE_DELTA_MAX	1
47*97bd480fSBaptiste Daroussin 
48*97bd480fSBaptiste Daroussin #define TREE_ENTRY(type)			\
49*97bd480fSBaptiste Daroussin   struct {					\
50*97bd480fSBaptiste Daroussin     struct type	*avl_left;			\
51*97bd480fSBaptiste Daroussin     struct type	*avl_right;			\
52*97bd480fSBaptiste Daroussin     int		 avl_height;			\
53*97bd480fSBaptiste Daroussin   }
54*97bd480fSBaptiste Daroussin 
55*97bd480fSBaptiste Daroussin #define TREE_HEAD(name, type)				\
56*97bd480fSBaptiste Daroussin   struct name {						\
57*97bd480fSBaptiste Daroussin     struct type *th_root;				\
58*97bd480fSBaptiste Daroussin     int  (*th_cmp)(struct type *lhs, struct type *rhs);	\
59*97bd480fSBaptiste Daroussin   }
60*97bd480fSBaptiste Daroussin 
61*97bd480fSBaptiste Daroussin #define TREE_INITIALIZER(cmp) { 0, cmp }
62*97bd480fSBaptiste Daroussin 
63*97bd480fSBaptiste Daroussin #define TREE_DELTA(self, field)								\
64*97bd480fSBaptiste Daroussin   (( (((self)->field.avl_left)  ? (self)->field.avl_left->field.avl_height  : 0))	\
65*97bd480fSBaptiste Daroussin    - (((self)->field.avl_right) ? (self)->field.avl_right->field.avl_height : 0))
66*97bd480fSBaptiste Daroussin 
67*97bd480fSBaptiste Daroussin /* Recursion prevents the following from being defined as macros. */
68*97bd480fSBaptiste Daroussin 
69*97bd480fSBaptiste Daroussin #define TREE_DEFINE(node, field)									\
70*97bd480fSBaptiste Daroussin 													\
71*97bd480fSBaptiste Daroussin   struct node *TREE_BALANCE_##node##_##field(struct node *);						\
72*97bd480fSBaptiste Daroussin 													\
73*97bd480fSBaptiste Daroussin   struct node *TREE_ROTL_##node##_##field(struct node *self)						\
74*97bd480fSBaptiste Daroussin   {													\
75*97bd480fSBaptiste Daroussin     struct node *r= self->field.avl_right;								\
76*97bd480fSBaptiste Daroussin     self->field.avl_right= r->field.avl_left;								\
77*97bd480fSBaptiste Daroussin     r->field.avl_left= TREE_BALANCE_##node##_##field(self);						\
78*97bd480fSBaptiste Daroussin     return TREE_BALANCE_##node##_##field(r);								\
79*97bd480fSBaptiste Daroussin   }													\
80*97bd480fSBaptiste Daroussin 													\
81*97bd480fSBaptiste Daroussin   struct node *TREE_ROTR_##node##_##field(struct node *self)						\
82*97bd480fSBaptiste Daroussin   {													\
83*97bd480fSBaptiste Daroussin     struct node *l= self->field.avl_left;								\
84*97bd480fSBaptiste Daroussin     self->field.avl_left= l->field.avl_right;								\
85*97bd480fSBaptiste Daroussin     l->field.avl_right= TREE_BALANCE_##node##_##field(self);						\
86*97bd480fSBaptiste Daroussin     return TREE_BALANCE_##node##_##field(l);								\
87*97bd480fSBaptiste Daroussin   }													\
88*97bd480fSBaptiste Daroussin 													\
89*97bd480fSBaptiste Daroussin   struct node *TREE_BALANCE_##node##_##field(struct node *self)						\
90*97bd480fSBaptiste Daroussin   {													\
91*97bd480fSBaptiste Daroussin     int delta= TREE_DELTA(self, field);									\
92*97bd480fSBaptiste Daroussin 													\
93*97bd480fSBaptiste Daroussin     if (delta < -TREE_DELTA_MAX)									\
94*97bd480fSBaptiste Daroussin       {													\
95*97bd480fSBaptiste Daroussin 	if (TREE_DELTA(self->field.avl_right, field) > 0)						\
96*97bd480fSBaptiste Daroussin 	  self->field.avl_right= TREE_ROTR_##node##_##field(self->field.avl_right);			\
97*97bd480fSBaptiste Daroussin 	return TREE_ROTL_##node##_##field(self);							\
98*97bd480fSBaptiste Daroussin       }													\
99*97bd480fSBaptiste Daroussin     else if (delta > TREE_DELTA_MAX)									\
100*97bd480fSBaptiste Daroussin       {													\
101*97bd480fSBaptiste Daroussin 	if (TREE_DELTA(self->field.avl_left, field) < 0)						\
102*97bd480fSBaptiste Daroussin 	  self->field.avl_left= TREE_ROTL_##node##_##field(self->field.avl_left);			\
103*97bd480fSBaptiste Daroussin 	return TREE_ROTR_##node##_##field(self);							\
104*97bd480fSBaptiste Daroussin       }													\
105*97bd480fSBaptiste Daroussin     self->field.avl_height= 0;										\
106*97bd480fSBaptiste Daroussin     if (self->field.avl_left && (self->field.avl_left->field.avl_height > self->field.avl_height))	\
107*97bd480fSBaptiste Daroussin       self->field.avl_height= self->field.avl_left->field.avl_height;					\
108*97bd480fSBaptiste Daroussin     if (self->field.avl_right && (self->field.avl_right->field.avl_height > self->field.avl_height))	\
109*97bd480fSBaptiste Daroussin       self->field.avl_height= self->field.avl_right->field.avl_height;					\
110*97bd480fSBaptiste Daroussin     self->field.avl_height += 1;									\
111*97bd480fSBaptiste Daroussin     return self;											\
112*97bd480fSBaptiste Daroussin   }													\
113*97bd480fSBaptiste Daroussin 													\
114*97bd480fSBaptiste Daroussin   struct node *TREE_INSERT_##node##_##field								\
115*97bd480fSBaptiste Daroussin     (struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs))		\
116*97bd480fSBaptiste Daroussin   {													\
117*97bd480fSBaptiste Daroussin     if (!self)												\
118*97bd480fSBaptiste Daroussin       return elm;											\
119*97bd480fSBaptiste Daroussin     if (compare(elm, self) < 0)										\
120*97bd480fSBaptiste Daroussin       self->field.avl_left= TREE_INSERT_##node##_##field(self->field.avl_left, elm, compare);		\
121*97bd480fSBaptiste Daroussin     else												\
122*97bd480fSBaptiste Daroussin       self->field.avl_right= TREE_INSERT_##node##_##field(self->field.avl_right, elm, compare);		\
123*97bd480fSBaptiste Daroussin     return TREE_BALANCE_##node##_##field(self);								\
124*97bd480fSBaptiste Daroussin   }													\
125*97bd480fSBaptiste Daroussin 													\
126*97bd480fSBaptiste Daroussin   struct node *TREE_FIND_##node##_##field								\
127*97bd480fSBaptiste Daroussin     (struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs))		\
128*97bd480fSBaptiste Daroussin   {													\
129*97bd480fSBaptiste Daroussin     if (!self)												\
130*97bd480fSBaptiste Daroussin       return 0;												\
131*97bd480fSBaptiste Daroussin     if (compare(elm, self) == 0)									\
132*97bd480fSBaptiste Daroussin       return self;											\
133*97bd480fSBaptiste Daroussin     if (compare(elm, self) < 0)										\
134*97bd480fSBaptiste Daroussin       return TREE_FIND_##node##_##field(self->field.avl_left, elm, compare);				\
135*97bd480fSBaptiste Daroussin     else												\
136*97bd480fSBaptiste Daroussin       return TREE_FIND_##node##_##field(self->field.avl_right, elm, compare);				\
137*97bd480fSBaptiste Daroussin   }													\
138*97bd480fSBaptiste Daroussin 													\
139*97bd480fSBaptiste Daroussin   struct node *TREE_MOVE_RIGHT(struct node *self, struct node *rhs)					\
140*97bd480fSBaptiste Daroussin   {													\
141*97bd480fSBaptiste Daroussin     if (!self)												\
142*97bd480fSBaptiste Daroussin       return rhs;											\
143*97bd480fSBaptiste Daroussin     self->field.avl_right= TREE_MOVE_RIGHT(self->field.avl_right, rhs);					\
144*97bd480fSBaptiste Daroussin     return TREE_BALANCE_##node##_##field(self);								\
145*97bd480fSBaptiste Daroussin   }													\
146*97bd480fSBaptiste Daroussin 													\
147*97bd480fSBaptiste Daroussin   struct node *TREE_REMOVE_##node##_##field								\
148*97bd480fSBaptiste Daroussin     (struct node *self, struct node *elm, int (*compare)(struct node *lhs, struct node *rhs))		\
149*97bd480fSBaptiste Daroussin   {													\
150*97bd480fSBaptiste Daroussin     if (!self) return 0;										\
151*97bd480fSBaptiste Daroussin 													\
152*97bd480fSBaptiste Daroussin     if (compare(elm, self) == 0)									\
153*97bd480fSBaptiste Daroussin       {													\
154*97bd480fSBaptiste Daroussin 	struct node *tmp= TREE_MOVE_RIGHT(self->field.avl_left, self->field.avl_right);			\
155*97bd480fSBaptiste Daroussin 	self->field.avl_left= 0;									\
156*97bd480fSBaptiste Daroussin 	self->field.avl_right= 0;									\
157*97bd480fSBaptiste Daroussin 	return tmp;											\
158*97bd480fSBaptiste Daroussin       }													\
159*97bd480fSBaptiste Daroussin     if (compare(elm, self) < 0)										\
160*97bd480fSBaptiste Daroussin       self->field.avl_left= TREE_REMOVE_##node##_##field(self->field.avl_left, elm, compare);		\
161*97bd480fSBaptiste Daroussin     else												\
162*97bd480fSBaptiste Daroussin       self->field.avl_right= TREE_REMOVE_##node##_##field(self->field.avl_right, elm, compare);		\
163*97bd480fSBaptiste Daroussin     return TREE_BALANCE_##node##_##field(self);								\
164*97bd480fSBaptiste Daroussin   }													\
165*97bd480fSBaptiste Daroussin 													\
166*97bd480fSBaptiste Daroussin   void TREE_FORWARD_APPLY_ALL_##node##_##field								\
167*97bd480fSBaptiste Daroussin     (struct node *self, void (*function)(struct node *node, void *data), void *data)			\
168*97bd480fSBaptiste Daroussin   {													\
169*97bd480fSBaptiste Daroussin     if (self)												\
170*97bd480fSBaptiste Daroussin       {													\
171*97bd480fSBaptiste Daroussin 	TREE_FORWARD_APPLY_ALL_##node##_##field(self->field.avl_left, function, data);			\
172*97bd480fSBaptiste Daroussin 	function(self, data);										\
173*97bd480fSBaptiste Daroussin 	TREE_FORWARD_APPLY_ALL_##node##_##field(self->field.avl_right, function, data);			\
174*97bd480fSBaptiste Daroussin       }													\
175*97bd480fSBaptiste Daroussin   }													\
176*97bd480fSBaptiste Daroussin 													\
177*97bd480fSBaptiste Daroussin   void TREE_REVERSE_APPLY_ALL_##node##_##field								\
178*97bd480fSBaptiste Daroussin     (struct node *self, void (*function)(struct node *node, void *data), void *data)			\
179*97bd480fSBaptiste Daroussin   {													\
180*97bd480fSBaptiste Daroussin     if (self)												\
181*97bd480fSBaptiste Daroussin       {													\
182*97bd480fSBaptiste Daroussin 	TREE_REVERSE_APPLY_ALL_##node##_##field(self->field.avl_right, function, data);			\
183*97bd480fSBaptiste Daroussin 	function(self, data);										\
184*97bd480fSBaptiste Daroussin 	TREE_REVERSE_APPLY_ALL_##node##_##field(self->field.avl_left, function, data);			\
185*97bd480fSBaptiste Daroussin       }													\
186*97bd480fSBaptiste Daroussin   }
187*97bd480fSBaptiste Daroussin 
188*97bd480fSBaptiste Daroussin #define TREE_INSERT(head, node, field, elm)						\
189*97bd480fSBaptiste Daroussin   ((head)->th_root= TREE_INSERT_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
190*97bd480fSBaptiste Daroussin 
191*97bd480fSBaptiste Daroussin #define TREE_FIND(head, node, field, elm)				\
192*97bd480fSBaptiste Daroussin   (TREE_FIND_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
193*97bd480fSBaptiste Daroussin 
194*97bd480fSBaptiste Daroussin #define TREE_REMOVE(head, node, field, elm)						\
195*97bd480fSBaptiste Daroussin   ((head)->th_root= TREE_REMOVE_##node##_##field((head)->th_root, (elm), (head)->th_cmp))
196*97bd480fSBaptiste Daroussin 
197*97bd480fSBaptiste Daroussin #define TREE_DEPTH(head, field)			\
198*97bd480fSBaptiste Daroussin   ((head)->th_root->field.avl_height)
199*97bd480fSBaptiste Daroussin 
200*97bd480fSBaptiste Daroussin #define TREE_FORWARD_APPLY(head, node, field, function, data)	\
201*97bd480fSBaptiste Daroussin   TREE_FORWARD_APPLY_ALL_##node##_##field((head)->th_root, function, data)
202*97bd480fSBaptiste Daroussin 
203*97bd480fSBaptiste Daroussin #define TREE_REVERSE_APPLY(head, node, field, function, data)	\
204*97bd480fSBaptiste Daroussin   TREE_REVERSE_APPLY_ALL_##node##_##field((head)->th_root, function, data)
205*97bd480fSBaptiste Daroussin 
206*97bd480fSBaptiste Daroussin #define TREE_INIT(head, cmp) do {		\
207*97bd480fSBaptiste Daroussin     (head)->th_root= 0;				\
208*97bd480fSBaptiste Daroussin     (head)->th_cmp= (cmp);			\
209*97bd480fSBaptiste Daroussin   } while (0)
210*97bd480fSBaptiste Daroussin 
211*97bd480fSBaptiste Daroussin 
212*97bd480fSBaptiste Daroussin #endif /* __tree_h */
213