123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- /*
- * Copyright (c) 2006-2020, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2019-10-12 Jesven first version
- */
- #include <rtthread.h>
- #include <lwp_avl.h>
- static void lwp_avl_rebalance(struct lwp_avl_struct ***nodeplaces_ptr, int count)
- {
- for (; count > 0; count--)
- {
- struct lwp_avl_struct **nodeplace = *--nodeplaces_ptr;
- struct lwp_avl_struct *node = *nodeplace;
- struct lwp_avl_struct *nodeleft = node->avl_left;
- struct lwp_avl_struct *noderight = node->avl_right;
- int heightleft = heightof(nodeleft);
- int heightright = heightof(noderight);
- if (heightright + 1 < heightleft)
- {
- struct lwp_avl_struct *nodeleftleft = nodeleft->avl_left;
- struct lwp_avl_struct *nodeleftright = nodeleft->avl_right;
- int heightleftright = heightof(nodeleftright);
- if (heightof(nodeleftleft) >= heightleftright)
- {
- node->avl_left = nodeleftright;
- nodeleft->avl_right = node;
- nodeleft->avl_height = 1 + (node->avl_height = 1 + heightleftright);
- *nodeplace = nodeleft;
- }
- else
- {
- nodeleft->avl_right = nodeleftright->avl_left;
- node->avl_left = nodeleftright->avl_right;
- nodeleftright->avl_left = nodeleft;
- nodeleftright->avl_right = node;
- nodeleft->avl_height = node->avl_height = heightleftright;
- nodeleftright->avl_height = heightleft;
- *nodeplace = nodeleftright;
- }
- }
- else if (heightleft + 1 < heightright)
- {
- struct lwp_avl_struct *noderightright = noderight->avl_right;
- struct lwp_avl_struct *noderightleft = noderight->avl_left;
- int heightrightleft = heightof(noderightleft);
- if (heightof(noderightright) >= heightrightleft)
- {
- node->avl_right = noderightleft;
- noderight->avl_left = node;
- noderight->avl_height = 1 + (node->avl_height = 1 + heightrightleft);
- *nodeplace = noderight;
- }
- else
- {
- noderight->avl_left = noderightleft->avl_right;
- node->avl_right = noderightleft->avl_left;
- noderightleft->avl_right = noderight;
- noderightleft->avl_left = node;
- noderight->avl_height = node->avl_height = heightrightleft;
- noderightleft->avl_height = heightright;
- *nodeplace = noderightleft;
- }
- }
- else
- {
- int height = (heightleft < heightright ? heightright : heightleft) + 1;
- if (height == node->avl_height)
- break;
- node->avl_height = height;
- }
- }
- }
- void lwp_avl_remove(struct lwp_avl_struct *node_to_delete, struct lwp_avl_struct **ptree)
- {
- avl_key_t key = node_to_delete->avl_key;
- struct lwp_avl_struct **nodeplace = ptree;
- struct lwp_avl_struct **stack[avl_maxheight];
- uint32_t stack_count = 0;
- struct lwp_avl_struct ***stack_ptr = &stack[0]; /* = &stack[stackcount] */
- struct lwp_avl_struct **nodeplace_to_delete;
- for (;;)
- {
- struct lwp_avl_struct *node = *nodeplace;
- if (node == AVL_EMPTY)
- {
- return;
- }
- *stack_ptr++ = nodeplace;
- stack_count++;
- if (key == node->avl_key)
- break;
- if (key < node->avl_key)
- nodeplace = &node->avl_left;
- else
- nodeplace = &node->avl_right;
- }
- nodeplace_to_delete = nodeplace;
- if (node_to_delete->avl_left == AVL_EMPTY)
- {
- *nodeplace_to_delete = node_to_delete->avl_right;
- stack_ptr--;
- stack_count--;
- }
- else
- {
- struct lwp_avl_struct ***stack_ptr_to_delete = stack_ptr;
- struct lwp_avl_struct **nodeplace = &node_to_delete->avl_left;
- struct lwp_avl_struct *node;
- for (;;)
- {
- node = *nodeplace;
- if (node->avl_right == AVL_EMPTY)
- break;
- *stack_ptr++ = nodeplace;
- stack_count++;
- nodeplace = &node->avl_right;
- }
- *nodeplace = node->avl_left;
- node->avl_left = node_to_delete->avl_left;
- node->avl_right = node_to_delete->avl_right;
- node->avl_height = node_to_delete->avl_height;
- *nodeplace_to_delete = node;
- *stack_ptr_to_delete = &node->avl_left;
- }
- lwp_avl_rebalance(stack_ptr, stack_count);
- }
- void lwp_avl_insert(struct lwp_avl_struct *new_node, struct lwp_avl_struct **ptree)
- {
- avl_key_t key = new_node->avl_key;
- struct lwp_avl_struct **nodeplace = ptree;
- struct lwp_avl_struct **stack[avl_maxheight];
- int stack_count = 0;
- struct lwp_avl_struct ***stack_ptr = &stack[0]; /* = &stack[stackcount] */
- for (;;)
- {
- struct lwp_avl_struct *node = *nodeplace;
- if (node == AVL_EMPTY)
- break;
- *stack_ptr++ = nodeplace;
- stack_count++;
- if (key < node->avl_key)
- nodeplace = &node->avl_left;
- else
- nodeplace = &node->avl_right;
- }
- new_node->avl_left = AVL_EMPTY;
- new_node->avl_right = AVL_EMPTY;
- new_node->avl_height = 1;
- *nodeplace = new_node;
- lwp_avl_rebalance(stack_ptr, stack_count);
- }
- struct lwp_avl_struct *lwp_avl_find(avl_key_t key, struct lwp_avl_struct *ptree)
- {
- for (;;)
- {
- if (ptree == AVL_EMPTY)
- {
- return (struct lwp_avl_struct *)0;
- }
- if (key == ptree->avl_key)
- break;
- if (key < ptree->avl_key)
- ptree = ptree->avl_left;
- else
- ptree = ptree->avl_right;
- }
- return ptree;
- }
- int lwp_avl_traversal(struct lwp_avl_struct *ptree, int (*fun)(struct lwp_avl_struct *, void *), void *arg)
- {
- int ret;
- if (!ptree)
- {
- return 0;
- }
- if (ptree->avl_left)
- {
- ret = lwp_avl_traversal(ptree->avl_left, fun, arg);
- if (ret != 0)
- {
- return ret;
- }
- }
- ret = (*fun)(ptree, arg);
- if (ret != 0)
- {
- return ret;
- }
- if (ptree->avl_right)
- {
- ret = lwp_avl_traversal(ptree->avl_right, fun, arg);
- if (ret != 0)
- {
- return ret;
- }
- }
- return ret;
- }
- rt_weak struct lwp_avl_struct* lwp_map_find_first(struct lwp_avl_struct* ptree)
- {
- if (ptree == AVL_EMPTY)
- {
- return (struct lwp_avl_struct *)0;
- }
- while (1)
- {
- if (!ptree->avl_left)
- {
- break;
- }
- ptree = ptree->avl_left;
- }
- return ptree;
- }
|