zoukankan      html  css  js  c++  java
  • AVL平衡二叉树

    一.AVL简介

    AVL树的名字来源于它的发明作者G.M. Adelson-Velsky 和 E.M. Landis。AVL树是最先发明的自平衡二叉查找树(Self-Balancing Binary Search Tree,简称平衡二叉树)。

    AVL树又称平衡二叉搜索树,它能保证二叉树高度相对平衡,尽量降低二叉树的高度,提高搜索效率。单纯的二叉搜索树在最坏的情况下插入查找删除等操作时间复杂度会是O(N),AVL树使得增删查改的时间复杂度为O(lgN). (ps:这里的lgN指的是log以2为底的N)

    AVL树特点:

    1. 左子树和右子树的高度之差的绝对值不超过1。 
    2. 树中的每个左子树和右子树都是AVL树。
    3. 每个节点都有一个平衡因子(balance factor--bf),任一节点的平衡因子是-1,0,1。
    平衡因子:将二叉树上节点的左子树高度减去右子树高度的值称为该节点的平衡因子BF(Balance Factor)。

    二. AVL理论

     
     

    三. AVL实现

    C语言的实现部分参考openwrt的libubox。

    1. 节点node

    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;
    };

    2. AVL树

    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);

     3. alv树初始化

    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)

    4. avl树增加节点

    /**
     * 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;
    }

    5. avl树删除节点

    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);
    } 

    6. avl树查找节点

    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

    参考:

    1. 【数据结构】AVL树详解

    2. 数据结构图文解析之:AVL树详解及C++模板实现

    3. 数据结构学习之二叉树(理论篇)

    4. 数据结构学习之二叉树(实践篇)

  • 相关阅读:
    Spring-Security (学习记录四)--配置权限过滤器,采用数据库方式获取权限
    使用IDEA将代码托管到GitHub步骤和错误解决
    Windows 10 操作系统删除Administrator登录选项
    Android的四种储存方式(SQLite、FileSystem、SDCardSystem、SharedPreferences)
    php环境之Wampserver端口修改
    JAVA8新特性——方法引用
    JAVA8新特性——Lamda表达式
    HTTP通信模拟表单提交数据
    JAVA8新特性——接口定义增强
    修改SpringBoot 默认的小叶子图标
  • 原文地址:https://www.cnblogs.com/embedded-linux/p/9193038.html
Copyright © 2011-2022 走看看