2 splay_tree.c -- splay tree and linked list convenience
3 Copyright (C) 2004-2013 Guus Sliepen <guus@tinc-vpn.org>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include "splay_tree.h"
27 static splay_node_t *splay_top_down(splay_tree_t *tree, const void *data, int *result) {
28 splay_node_t left = {0}, right = {0};
29 splay_node_t *leftbottom = &left, *rightbottom = &right, *child, *grandchild;
30 splay_node_t *root = tree->root;
41 while((c = tree->compare(data, root->data))) {
42 if(c < 0 && (child = root->left)) {
43 c = tree->compare(data, child->data);
45 if(c < 0 && (grandchild = child->left)) {
46 rightbottom->left = child;
47 child->parent = rightbottom;
50 if((root->left = child->right)) {
51 child->right->parent = root;
58 grandchild->parent = NULL;
61 } else if(c > 0 && (grandchild = child->right)) {
62 leftbottom->right = child;
63 child->parent = leftbottom;
67 grandchild->parent = NULL;
69 rightbottom->left = root;
70 root->parent = rightbottom;
77 rightbottom->left = root;
78 root->parent = rightbottom;
87 } else if(c > 0 && (child = root->right)) {
88 c = tree->compare(data, child->data);
90 if(c > 0 && (grandchild = child->right)) {
91 leftbottom->right = child;
92 child->parent = leftbottom;
95 if((root->right = child->left)) {
96 child->left->parent = root;
100 root->parent = child;
103 grandchild->parent = NULL;
106 } else if(c < 0 && (grandchild = child->left)) {
107 rightbottom->left = child;
108 child->parent = rightbottom;
112 grandchild->parent = NULL;
114 leftbottom->right = root;
115 root->parent = leftbottom;
122 leftbottom->right = root;
123 root->parent = leftbottom;
127 child->parent = NULL;
141 leftbottom->right = root->left;
142 root->left->parent = leftbottom;
145 root->left = left.right;
146 left.right->parent = root;
151 rightbottom->left = root->right;
152 root->right->parent = rightbottom;
155 root->right = right.left;
156 right.left->parent = root;
170 static void splay_bottom_up(splay_tree_t *tree, splay_node_t *node) {
171 splay_node_t *parent, *grandparent, *greatgrandparent;
173 while((parent = node->parent)) {
174 if(!(grandparent = parent->parent)) { /* zig */
175 if(node == parent->left) {
176 if((parent->left = node->right)) {
177 parent->left->parent = parent;
180 node->right = parent;
182 if((parent->right = node->left)) {
183 parent->right->parent = parent;
189 parent->parent = node;
192 greatgrandparent = grandparent->parent;
194 if(node == parent->left && parent == grandparent->left) { /* left zig-zig */
195 if((grandparent->left = parent->right)) {
196 grandparent->left->parent = grandparent;
199 parent->right = grandparent;
200 grandparent->parent = parent;
202 if((parent->left = node->right)) {
203 parent->left->parent = parent;
206 node->right = parent;
207 parent->parent = node;
208 } else if(node == parent->right && parent == grandparent->right) { /* right zig-zig */
209 if((grandparent->right = parent->left)) {
210 grandparent->right->parent = grandparent;
213 parent->left = grandparent;
214 grandparent->parent = parent;
216 if((parent->right = node->left)) {
217 parent->right->parent = parent;
221 parent->parent = node;
222 } else if(node == parent->right && parent == grandparent->left) { /* left-right zig-zag */
223 if((parent->right = node->left)) {
224 parent->right->parent = parent;
228 parent->parent = node;
230 if((grandparent->left = node->right)) {
231 grandparent->left->parent = grandparent;
234 node->right = grandparent;
235 grandparent->parent = node;
236 } else { /* right-left zig-zag */
237 if((parent->left = node->right)) {
238 parent->left->parent = parent;
241 node->right = parent;
242 parent->parent = node;
244 if((grandparent->right = node->left)) {
245 grandparent->right->parent = grandparent;
248 node->left = grandparent;
249 grandparent->parent = node;
252 if((node->parent = greatgrandparent)) {
253 if(grandparent == greatgrandparent->left) {
254 greatgrandparent->left = node;
256 greatgrandparent->right = node;
265 /* (De)constructors */
267 splay_tree_t *splay_alloc_tree(splay_compare_t compare, splay_action_t delete) {
270 tree = xzalloc(sizeof(splay_tree_t));
271 tree->compare = compare;
272 tree->delete = delete;
277 void splay_free_tree(splay_tree_t *tree) {
281 splay_node_t *splay_alloc_node(void) {
282 return xzalloc(sizeof(splay_node_t));
285 void splay_free_node(splay_tree_t *tree, splay_node_t *node) {
286 if(node->data && tree->delete) {
287 tree->delete(node->data);
295 void *splay_search(splay_tree_t *tree, const void *data) {
298 node = splay_search_node(tree, data);
300 return node ? node->data : NULL;
303 void *splay_search_closest(splay_tree_t *tree, const void *data, int *result) {
306 node = splay_search_closest_node(tree, data, result);
308 return node ? node->data : NULL;
311 void *splay_search_closest_smaller(splay_tree_t *tree, const void *data) {
314 node = splay_search_closest_smaller_node(tree, data);
316 return node ? node->data : NULL;
319 void *splay_search_closest_greater(splay_tree_t *tree, const void *data) {
322 node = splay_search_closest_greater_node(tree, data);
324 return node ? node->data : NULL;
327 splay_node_t *splay_search_node(splay_tree_t *tree, const void *data) {
331 node = splay_search_closest_node(tree, data, &result);
333 return result ? NULL : node;
336 splay_node_t *splay_search_closest_node_nosplay(const splay_tree_t *tree, const void *data, int *result) {
351 c = tree->compare(data, node->data);
377 splay_node_t *splay_search_closest_node(splay_tree_t *tree, const void *data, int *result) {
378 return splay_top_down(tree, data, result);
381 splay_node_t *splay_search_closest_smaller_node(splay_tree_t *tree, const void *data) {
385 node = splay_search_closest_node(tree, data, &result);
394 splay_node_t *splay_search_closest_greater_node(splay_tree_t *tree, const void *data) {
398 node = splay_search_closest_node(tree, data, &result);
407 /* Insertion and deletion */
409 splay_node_t *splay_insert(splay_tree_t *tree, void *data) {
410 splay_node_t *closest, *new;
414 new = splay_alloc_node();
416 splay_insert_top(tree, new);
418 closest = splay_search_closest_node(tree, data, &result);
424 new = splay_alloc_node();
428 splay_insert_before(tree, closest, new);
430 splay_insert_after(tree, closest, new);
437 splay_node_t *splay_insert_node(splay_tree_t *tree, splay_node_t *node) {
438 splay_node_t *closest;
441 node->left = node->right = node->parent = node->next = node->prev = NULL;
444 splay_insert_top(tree, node);
446 closest = splay_search_closest_node(tree, node->data, &result);
453 splay_insert_before(tree, closest, node);
455 splay_insert_after(tree, closest, node);
462 void splay_insert_top(splay_tree_t *tree, splay_node_t *node) {
463 node->prev = node->next = node->left = node->right = node->parent = NULL;
464 tree->head = tree->tail = tree->root = node;
469 void splay_insert_before(splay_tree_t *tree, splay_node_t *before, splay_node_t *node) {
472 splay_insert_after(tree, tree->tail, node);
474 splay_insert_top(tree, node);
482 if((node->prev = before->prev)) {
483 before->prev->next = node;
490 splay_bottom_up(tree, before);
492 node->right = before;
493 before->parent = node;
495 if((node->left = before->left)) {
496 before->left->parent = node;
507 void splay_insert_after(splay_tree_t *tree, splay_node_t *after, splay_node_t *node) {
510 splay_insert_before(tree, tree->head, node);
512 splay_insert_top(tree, node);
520 if((node->next = after->next)) {
521 after->next->prev = node;
528 splay_bottom_up(tree, after);
531 after->parent = node;
533 if((node->right = after->right)) {
534 after->right->parent = node;
545 splay_node_t *splay_unlink(splay_tree_t *tree, void *data) {
548 node = splay_search_node(tree, data);
551 splay_unlink_node(tree, node);
557 void splay_unlink_node(splay_tree_t *tree, splay_node_t *node) {
559 node->prev->next = node->next;
561 tree->head = node->next;
565 node->next->prev = node->prev;
567 tree->tail = node->prev;
570 splay_bottom_up(tree, node);
573 node->left->parent = NULL;
574 tree->root = node->left;
576 if((node->prev->right = node->right)) {
577 node->right->parent = node->prev;
579 } else if(node->next) {
580 tree->root = node->right;
581 node->right->parent = NULL;
590 void splay_delete_node(splay_tree_t *tree, splay_node_t *node) {
591 splay_unlink_node(tree, node);
592 splay_free_node(tree, node);
595 void splay_delete(splay_tree_t *tree, void *data) {
598 node = splay_search_node(tree, data);
601 splay_delete_node(tree, node);
605 /* Fast tree cleanup */
607 void splay_empty_tree(splay_tree_t *tree) {
608 for(splay_node_t *node = tree->head, *next; node; node = next) {
610 splay_free_node(tree, node);
620 void splay_delete_tree(splay_tree_t *tree) {
621 splay_empty_tree(tree);
622 splay_free_tree(tree);
627 void splay_foreach(const splay_tree_t *tree, splay_action_t action) {
628 for(splay_node_t *node = tree->head, *next; node; node = next) {
634 void splay_foreach_node(const splay_tree_t *tree, splay_action_t action) {
635 for(splay_node_t *node = tree->head, *next; node; node = next) {