AVL平衡二叉樹

一.AVL簡介

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

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數據結構

 

參考:less

1. 【數據結構】AVL樹詳解post

2. 數據結構圖文解析之:AVL樹詳解及C++模板實現學習

3. 數據結構學習之二叉樹(理論篇)this

4. 數據結構學習之二叉樹(實踐篇)url

相關文章
相關標籤/搜索