AVL樹的名字來源於它的發明做者G.M. Adelson-Velsky 和 E.M. Landis。AVL樹是最早發明的自平衡二叉查找樹(Self-Balancing Binary Search Tree,簡稱平衡二叉樹)。html
AVL樹又稱平衡二叉搜索樹,它能保證二叉樹高度相對平衡,儘可能下降二叉樹的高度,提升搜索效率。單純的二叉搜索樹在最壞的狀況下插入查找刪除等操做時間複雜度會是O(N),AVL樹使得增刪查改的時間複雜度爲O(lgN). (ps:這裏的lgN指的是log以2爲底的N)node
AVL樹特色:git
struct avl_node { /** * Linked list node for supporting easy iteration and multiple * elments with the same key. * * this must be the first element of an avl_node to * make casting for lists easier */ struct list_head list; /** * Pointer to parent node in tree, NULL if root node */ struct avl_node *parent; /** * Pointer to left child */ struct avl_node *left; /** * Pointer to right child */ struct avl_node *right; /** * pointer to key of node */ const void *key; /** * balance state of AVL tree (0,-1,+1) */ signed char balance; /** * true if first of a series of nodes with same key */ bool leader; };
struct avl_tree { /** * Head of linked list node for supporting easy iteration * and multiple elments with the same key. */ struct list_head list_head; /** * pointer to the root node of the avl tree, NULL if tree is empty */ struct avl_node *root; /** * number of nodes in the avl tree */ unsigned int count; /** * true if multiple nodes with the same key are * allowed in the tree, false otherwise */ bool allow_dups; /** * pointer to the tree comparator * * First two parameters are keys to compare, * third parameter is a copy of cmp_ptr */ avl_tree_comp comp; /** * custom pointer delivered to the tree comparator */ void *cmp_ptr; };
/** * Prototype for avl comparators * @param k1 first key * @param k2 second key * @param ptr custom data for tree comparator * @return +1 if k1>k2, -1 if k1<k2, 0 if k1==k2 */ typedef int (*avl_tree_comp) (const void *k1, const void *k2, void *ptr);
void avl_init(struct avl_tree *tree, avl_tree_comp comp, bool allow_dups, void *ptr) { INIT_LIST_HEAD(&tree->list_head); tree->root = NULL; tree->count = 0; tree->comp = comp; tree->allow_dups = allow_dups; tree->cmp_ptr = ptr; }
#define AVL_TREE_INIT(_name, _comp, _allow_dups, _cmp_ptr) \ { \ .list_head = LIST_HEAD_INIT(_name.list_head), \ .comp = _comp, \ .allow_dups = _allow_dups, \ .cmp_ptr = _cmp_ptr \ } #define AVL_TREE(_name, _comp, _allow_dups, _cmp_ptr) \ struct avl_tree _name = \ AVL_TREE_INIT(_name, _comp, _allow_dups, _cmp_ptr)
/** * Inserts an avl_node into a tree * @param tree pointer to tree * @param new pointer to node * @return 0 if node was inserted successfully, -1 if it was not inserted * because of a key collision */ int avl_insert(struct avl_tree *tree, struct avl_node *new) { struct avl_node *node, *next, *last; int diff; new->parent = NULL; new->left = NULL; new->right = NULL; new->balance = 0; new->leader = true; if (tree->root == NULL) { list_add(&new->list, &tree->list_head); tree->root = new; tree->count = 1; return 0; } node = avl_find_rec(tree->root, new->key, tree->comp, tree->cmp_ptr, &diff); last = node; while (!list_is_last(&last->list, &tree->list_head)) { next = avl_next(last); if (next->leader) { break; } last = next; } diff = (*tree->comp) (new->key, node->key, tree->cmp_ptr); if (diff == 0) { if (!tree->allow_dups) return -1; new->leader = 0; avl_insert_after(tree, last, new); return 0; } if (node->balance == 1) { avl_insert_before(tree, node, new); node->balance = 0; new->parent = node; node->left = new; return 0; } if (node->balance == -1) { avl_insert_after(tree, last, new); node->balance = 0; new->parent = node; node->right = new; return 0; } if (diff < 0) { avl_insert_before(tree, node, new); node->balance = -1; new->parent = node; node->left = new; post_insert(tree, node); return 0; } avl_insert_after(tree, last, new); node->balance = 1; new->parent = node; node->right = new; post_insert(tree, node); return 0; }
void avl_delete(struct avl_tree *tree, struct avl_node *node) { struct avl_node *next; struct avl_node *parent; struct avl_node *left; struct avl_node *right; if (node->leader) { if (tree->allow_dups && !list_is_last(&node->list, &tree->list_head) && !(next = avl_next(node))->leader) { next->leader = true; next->balance = node->balance; parent = node->parent; left = node->left; right = node->right; next->parent = parent; next->left = left; next->right = right; if (parent == NULL) tree->root = next; else { if (node == parent->left) parent->left = next; else parent->right = next; } if (left != NULL) left->parent = next; if (right != NULL) right->parent = next; } else avl_delete_worker(tree, node); } avl_remove(tree, node); }
struct avl_node *EXPORT(avl_find)(const struct avl_tree *, const void *key); struct avl_node *EXPORT(avl_find_greaterequal)(const struct avl_tree *tree, const void *key); struct avl_node *EXPORT(avl_find_lessequal)(const struct avl_tree *tree, const void *key);
static inline bool avl_is_first(struct avl_tree *tree, struct avl_node *node) { return tree->list_head.next == &node->list; } static inline bool avl_is_last(struct avl_tree *tree, struct avl_node *node) { return tree->list_head.prev == &node->list; } static inline bool avl_is_empty(struct avl_tree *tree) { return tree->count == 0; }
static inline void * __avl_find_element(const struct avl_tree *tree, const void *key, size_t offset, enum avl_find_mode mode) { void *node = NULL; switch (mode) { case AVL_FIND_EQUAL: node = avl_find(tree, key); break; case AVL_FIND_LESSEQUAL: node = avl_find_lessequal(tree, key); break; case AVL_FIND_GREATEREQUAL: node = avl_find_greaterequal(tree, key); break; } return node == NULL ? NULL : (((char *)node) - offset); } #define avl_find_element(tree, key, element, node_element) \ ((typeof(*(element)) *)__avl_find_element(tree, key, offsetof(typeof(*(element)), node_element), AVL_FIND_EQUAL)) #define avl_find_le_element(tree, key, element, node_element) \ ((typeof(*(element)) *)__avl_find_element(tree, key, offsetof(typeof(*(element)), node_element), AVL_FIND_LESSEQUAL)) #define avl_find_ge_element(tree, key, element, node_element) \ ((typeof(*(element)) *)__avl_find_element(tree, key, offsetof(typeof(*(element)), node_element), AVL_FIND_GREATEREQUAL))
#define avl_first_element(tree, element, node_member) \ container_of((tree)->list_head.next, typeof(*(element)), node_member.list) #define avl_last_element(tree, element, node_member) \ container_of((tree)->list_head.prev, typeof(*(element)), node_member.list) #define avl_next_element(element, node_member) \ container_of((&(element)->node_member.list)->next, typeof(*(element)), node_member.list) #define avl_prev_element(element, node_member) \ container_of((&(element)->node_member.list)->prev, typeof(*(element)), node_member.list)
#define avl_for_element_range(first, last, element, node_member) \ for (element = (first); \ element->node_member.list.prev != &(last)->node_member.list; \ element = avl_next_element(element, node_member)) #define avl_for_element_range_reverse(first, last, element, node_member) \ for (element = (last); \ element->node_member.list.next != &(first)->node_member.list; \ element = avl_prev_element(element, node_member)) #define avl_for_each_element(tree, element, node_member) \ avl_for_element_range(avl_first_element(tree, element, node_member), \ avl_last_element(tree, element, node_member), \ element, node_member) #define avl_for_each_element_reverse(tree, element, node_member) \ avl_for_element_range_reverse(avl_first_element(tree, element, node_member), \ avl_last_element(tree, element, node_member), \ element, node_member) #define avl_for_element_to_last(tree, first, element, node_member) \ avl_for_element_range(first, avl_last_element(tree, element, node_member), element, node_member) #define avl_for_element_to_last_reverse(tree, first, element, node_member) \ avl_for_element_range_reverse(first, avl_last_element(tree, element, node_member), element, node_member) #define avl_for_first_to_element(tree, last, element, node_member) \ avl_for_element_range(avl_first_element(tree, element, node_member), last, element, node_member) #define avl_for_first_to_element_reverse(tree, last, element, node_member) \ avl_for_element_range_reverse(avl_first_element(tree, element, node_member), last, element, node_member)
完整代碼參考:http://git.openwrt.org/project/libubox.git數據結構
參考:less
1. 【數據結構】AVL樹詳解post
3. 數據結構學習之二叉樹(理論篇)this
4. 數據結構學習之二叉樹(實踐篇)url