File Coverage

third_party/modest/source/mycore/utils/avl_tree.c
Criterion Covered Total %
statement 0 177 0.0
branch 0 80 0.0
condition n/a
subroutine n/a
pod n/a
total 0 257 0.0


line stmt bran cond sub pod time code
1             /*
2             Copyright (C) 2016-2017 Alexander Borisov
3            
4             This library is free software; you can redistribute it and/or
5             modify it under the terms of the GNU Lesser General Public
6             License as published by the Free Software Foundation; either
7             version 2.1 of the License, or (at your option) any later version.
8            
9             This library is distributed in the hope that it will be useful,
10             but WITHOUT ANY WARRANTY; without even the implied warranty of
11             MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12             Lesser General Public License for more details.
13            
14             You should have received a copy of the GNU Lesser General Public
15             License along with this library; if not, write to the Free Software
16             Foundation, Inc., 51 Franklin avl_treet, Fifth Floor, Boston, MA 02110-1301 USA
17            
18             Author: lex.borisov@gmail.com (Alexander Borisov)
19             */
20              
21             #include "mycore/utils/avl_tree.h"
22              
23 0           mycore_utils_avl_tree_t * mycore_utils_avl_tree_create(void)
24             {
25 0           return (mycore_utils_avl_tree_t*)mycore_calloc(1, sizeof(mycore_utils_avl_tree_t));
26             }
27              
28 0           mystatus_t mycore_utils_avl_tree_init(mycore_utils_avl_tree_t* avl_tree)
29             {
30             /* for raw declaration style */
31 0           avl_tree->mc_nodes = mcobject_create();
32 0 0         if(avl_tree->mc_nodes == NULL)
33 0           return MyCORE_STATUS_ERROR_MEMORY_ALLOCATION;
34            
35 0           mystatus_t mycore_status = mcobject_init(avl_tree->mc_nodes, 256, sizeof(mycore_utils_avl_tree_node_t));
36 0 0         if(mycore_status)
37 0           return MyCORE_STATUS_ERROR;
38            
39 0           return MyCORE_STATUS_OK;
40             }
41              
42 0           void mycore_utils_avl_tree_clean(mycore_utils_avl_tree_t* avl_tree)
43             {
44 0           mcobject_clean(avl_tree->mc_nodes);
45 0           }
46              
47 0           mycore_utils_avl_tree_t * mycore_utils_avl_tree_destroy(mycore_utils_avl_tree_t* avl_tree, bool self_destroy)
48             {
49 0 0         if(avl_tree == NULL)
50 0           return NULL;
51            
52 0           mcobject_destroy(avl_tree->mc_nodes, true);
53            
54 0 0         if(self_destroy) {
55 0           mycore_free(avl_tree);
56 0           return NULL;
57             }
58            
59 0           return avl_tree;
60             }
61              
62 0           mycore_utils_avl_tree_node_t * mycore_utils_avl_tree_node_create_root(mycore_utils_avl_tree_t* avl_tree, size_t type, void* value)
63             {
64 0           mycore_utils_avl_tree_node_t *node = mcobject_malloc(avl_tree->mc_nodes, NULL);
65 0           memset(node, 0, sizeof(mycore_utils_avl_tree_node_t));
66            
67 0           node->type = type;
68 0           node->value = value;
69            
70 0           return node;
71             }
72              
73 0           void mycore_utils_avl_tree_node_clean(mycore_utils_avl_tree_node_t* node)
74             {
75 0           memset(node, 0, sizeof(mycore_utils_avl_tree_node_t));
76 0           }
77              
78 0           short mycore_utils_avl_tree_node_height(mycore_utils_avl_tree_node_t* node)
79             {
80 0 0         return (node ? node->height : 0);
81             }
82              
83 0           short mycore_utils_avl_tree_node_balance_factor(mycore_utils_avl_tree_node_t* node)
84             {
85 0           return (mycore_utils_avl_tree_node_height(node->right) - mycore_utils_avl_tree_node_height(node->left));
86             }
87              
88 0           void mycore_utils_avl_tree_node_set_height(mycore_utils_avl_tree_node_t* node)
89             {
90 0           short left_height = mycore_utils_avl_tree_node_height(node->left);
91 0           short right_height = mycore_utils_avl_tree_node_height(node->right);
92            
93 0           node->height = (left_height > right_height ? left_height : right_height) + 1;
94 0           }
95              
96 0           mycore_utils_avl_tree_node_t * mycore_utils_avl_tree_node_rotate_right(mycore_utils_avl_tree_node_t* pos)
97             {
98 0           mycore_utils_avl_tree_node_t* node = pos->left;
99            
100 0           node->parent = pos->parent;
101            
102 0 0         if(node->right)
103 0           node->right->parent = pos;
104            
105 0           pos->left = node->right;
106 0           pos->parent = node;
107            
108 0           node->right = pos;
109            
110 0           mycore_utils_avl_tree_node_set_height(pos);
111 0           mycore_utils_avl_tree_node_set_height(node);
112            
113 0           return node;
114             }
115              
116 0           mycore_utils_avl_tree_node_t * mycore_utils_avl_tree_node_rotate_left(mycore_utils_avl_tree_node_t* pos)
117             {
118 0           mycore_utils_avl_tree_node_t* node = pos->right;
119            
120 0           node->parent = pos->parent;
121            
122 0 0         if(node->left)
123 0           node->left->parent = pos;
124            
125 0           pos->right = node->left;
126 0           pos->parent = node;
127            
128 0           node->left = pos;
129            
130 0           mycore_utils_avl_tree_node_set_height(pos);
131 0           mycore_utils_avl_tree_node_set_height(node);
132            
133 0           return node;
134             }
135              
136 0           mycore_utils_avl_tree_node_t * mycore_utils_avl_tree_node_balance(mycore_utils_avl_tree_node_t* node, mycore_utils_avl_tree_node_t** root)
137             {
138             /* set height */
139 0           short left_height = mycore_utils_avl_tree_node_height(node->left);
140 0           short right_height = mycore_utils_avl_tree_node_height(node->right);
141            
142 0           node->height = (left_height > right_height ? left_height : right_height) + 1;
143            
144             /* check balance */
145 0           switch ((right_height - left_height))
146             {
147             case 2: {
148 0 0         if(mycore_utils_avl_tree_node_balance_factor(node->right) < 0)
149 0           node->right = mycore_utils_avl_tree_node_rotate_right(node->right);
150            
151 0           mycore_utils_avl_tree_node_t* parent = node->parent;
152            
153 0 0         if(parent) {
154 0 0         if(parent->right == node)
155 0           return parent->right = mycore_utils_avl_tree_node_rotate_left(node);
156             else
157 0           return parent->left = mycore_utils_avl_tree_node_rotate_left(node);
158             }
159            
160 0           return mycore_utils_avl_tree_node_rotate_left(node);
161             }
162             case -2: {
163 0 0         if(mycore_utils_avl_tree_node_balance_factor(node->left) > 0)
164 0           node->left = mycore_utils_avl_tree_node_rotate_left(node->left);
165            
166 0           mycore_utils_avl_tree_node_t* parent = node->parent;
167            
168 0 0         if(parent) {
169 0 0         if(parent->right == node)
170 0           return parent->right = mycore_utils_avl_tree_node_rotate_right(node);
171             else
172 0           return parent->left = mycore_utils_avl_tree_node_rotate_right(node);
173             }
174            
175 0           return mycore_utils_avl_tree_node_rotate_right(node);
176             }
177             default:
178 0           break;
179             }
180            
181 0 0         if(node->parent == NULL)
182 0           *root = node;
183            
184 0           return node->parent;
185             }
186              
187 0           void mycore_utils_avl_tree_add(mycore_utils_avl_tree_t* avl_tree, mycore_utils_avl_tree_node_t** root, size_t type, void* value)
188             {
189 0 0         if(*root == NULL) {
190 0           *root = mycore_utils_avl_tree_node_create_root(avl_tree, type, value);
191 0           return;
192             }
193            
194 0           mycore_utils_avl_tree_node_t* node = *root;
195 0           mycore_utils_avl_tree_node_t* new_node = mcobject_malloc(avl_tree->mc_nodes, NULL);
196 0           mycore_utils_avl_tree_node_clean(new_node);
197            
198             while(1)
199             {
200 0 0         if(type == node->type) {
201 0           node->value = value;
202 0           return;
203             }
204 0 0         else if(type < node->type) {
205 0 0         if(node->left == NULL) {
206 0           node->left = new_node;
207            
208 0           new_node->parent = node;
209 0           new_node->type = type;
210 0           new_node->value = value;
211            
212 0           node = new_node;
213 0           break;
214             }
215            
216 0           node = node->left;
217             }
218             else {
219 0 0         if(node->right == NULL) {
220 0           node->right = new_node;
221            
222 0           new_node->parent = node;
223 0           new_node->type = type;
224 0           new_node->value = value;
225            
226 0           node = new_node;
227 0           break;
228             }
229            
230 0           node = node->right;
231             }
232 0           }
233            
234 0 0         while(node) {
235 0           node = mycore_utils_avl_tree_node_balance(node, root);
236             }
237             }
238              
239 0           mycore_utils_avl_tree_node_t * mycore_utils_avl_tree_find_min(mycore_utils_avl_tree_node_t* node)
240             {
241 0 0         if(node == NULL)
242 0           return NULL;
243            
244 0 0         while(node->right) {
245 0           node = node->right;
246             }
247            
248 0           return node;
249             }
250              
251 0           void mycore_utils_avl_tree_rotate_for_delete(mycore_utils_avl_tree_node_t* delete_node, mycore_utils_avl_tree_node_t* node, mycore_utils_avl_tree_node_t** root)
252             {
253             mycore_utils_avl_tree_node_t* balance_node;
254            
255 0 0         if(node) {
256 0 0         if(delete_node->left == node) {
257 0 0         balance_node = node->left ? node->left : node;
258            
259 0           node->parent = delete_node->parent;
260 0           node->right = delete_node->right;
261            
262 0 0         if(delete_node->right)
263 0           delete_node->right->parent = node;
264             }
265             else {
266 0           balance_node = node;
267            
268 0           node->parent->right = NULL;
269 0           node->parent = delete_node->parent;
270 0           node->right = delete_node->right;
271 0           node->left = delete_node->left;
272            
273 0 0         if(delete_node->left)
274 0           delete_node->left->parent = node;
275 0 0         if(delete_node->right)
276 0           delete_node->right->parent = node;
277             }
278            
279 0 0         if(delete_node->parent) {
280 0 0         if(delete_node->parent->left == delete_node) { delete_node->parent->left = node; }
281 0           else { delete_node->parent->right = node; }
282             }
283             else {
284 0           *root = node;
285             }
286             }
287             else {
288 0           balance_node = delete_node->parent;
289            
290 0 0         if(delete_node->parent) {
291 0 0         if(delete_node->parent->left == delete_node) { delete_node->parent->left = delete_node->right; }
292 0           else { delete_node->parent->right = delete_node->right; }
293             }
294             else {
295 0           *root = delete_node->right;
296             }
297             }
298            
299 0 0         while(balance_node) {
300 0           balance_node = mycore_utils_avl_tree_node_balance(balance_node, root);
301             }
302 0           }
303              
304 0           void * mycore_utils_avl_tree_delete(mycore_utils_avl_tree_t *avl_tree, mycore_utils_avl_tree_node_t** root, size_t type)
305             {
306 0           mycore_utils_avl_tree_node_t* node = *root;
307            
308 0 0         while(node)
309             {
310 0 0         if(type == node->type) {
311 0           mycore_utils_avl_tree_rotate_for_delete(node, mycore_utils_avl_tree_find_min(node->left), root);
312            
313 0           void *value = node->value;
314 0           mcobject_free(avl_tree->mc_nodes, node);
315            
316 0           return value;
317             }
318 0 0         else if(type < node->type)
319 0           node = node->left;
320             else
321 0           node = node->right;
322             }
323            
324 0           return NULL;
325             }
326              
327 0           mycore_utils_avl_tree_node_t * mycore_utils_avl_tree_search_by_type(mycore_utils_avl_tree_t *avl_tree, mycore_utils_avl_tree_node_t* node, size_t type)
328             {
329 0 0         while(node)
330             {
331 0 0         if(type == node->type)
332 0           return node;
333 0 0         else if(type < node->type)
334 0           node = node->left;
335             else
336 0           node = node->right;
337             }
338            
339 0           return NULL;
340             }
341              
342 0           void mycore_utils_avl_tree_list_all_nodes(mycore_utils_avl_tree_t *avl_tree, mycore_utils_avl_tree_node_t* root, mycore_utils_avl_tree_node_callback_f callback, void* ctx)
343             {
344 0 0         if(root == NULL)
345 0           return;
346            
347 0           callback(root, ctx);
348            
349 0           mycore_utils_avl_tree_list_all_nodes(avl_tree, root->left, callback, ctx);
350 0           mycore_utils_avl_tree_list_all_nodes(avl_tree, root->right, callback, ctx);
351             }
352              
353