Chinaunix首页 | 论坛 | 博客
  • 博客访问: 541030
  • 博文数量: 51
  • 博客积分: 345
  • 博客等级: 民兵
  • 技术积分: 534
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-21 12:02
个人简介

文章分类

全部博文(51)

文章存档

2023年(2)

2022年(1)

2021年(7)

2020年(10)

2019年(2)

2016年(20)

2015年(5)

2014年(1)

2011年(3)

我的朋友

分类: C/C++

2016-08-25 15:06:30

源码来自OpenWrt,本文对avlinit,插入,删除相关代码进行分析;最后给出了一个例子,来说明插入/删除node时,状态转变过程的截图;

Struct

主要结构如下:

/**

 * This element is a member of a avl-tree. It must be contained in all

 * larger structs that should be put into a tree.

 */

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;

};

/**

 * This struct is the central management part of an avl tree.

 * One of them is necessary for each avl_tree.

 */

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;

};

 

avl_init

avl_init(&services, avl_strcmp, false, NULL);

/**

 * Initialize a new avl_tree struct

 * @param tree pointer to avl-tree

 * @param comp pointer to comparator for the tree

 * @param allow_dups true if the tree allows multiple

 *   elements with the same      //是否可以复用,多个nodes使用同样的key

 * @param ptr custom parameter for comparator

 */

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;

}

int

avl_strcmp(const void *k1, const void *k2, void *ptr)

{

         return strcmp(k1, k2);

}

str1=str2,则返回零;

str1,则返回负数;

str1>str2,则返回正数。

 

插入节点---avl_insert

avl_insert(&services, &s->avl);

关于node->balance,初值为0

若节点左侧加入新node,则node->balance--;

若节点右侧加入新node,则node->balance++;

 

/**

 * 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);          //查找new的插入点;

 

  last = node;

 

  while (!list_is_last(&last->list, &tree->list_head)) {      //拥有同样key值的链表;

    next = avl_next(last);

    if (next->leader) {

      break;

    }

    last = next;

  }

 

  diff = (*tree->comp) (new->key, node->key, tree->cmp_ptr);//再次比较key

 

  if (diff == 0) {

    if (!tree->allow_dups)   //不允许复用key

      return -1;

 

    new->leader = 0;

 

    avl_insert_after(tree, last, new);    //允许复用key值;

    return 0;

  }

//node为最末尾的节点,若它存在左子树或者右子树,那么new插入到空的一边就可以了

  if (node->balance == 1) {

    avl_insert_before(tree, node, new);         //插入到node左面

 

    node->balance = 0;

    new->parent = node;

    node->left = new;

    return 0;

  }

 

  if (node->balance == -1) {

    avl_insert_after(tree, last, new);             //插入到last右面

 

    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;

}

static void

avl_insert_after(struct avl_tree *tree, struct avl_node *pos_node, struct avl_node *node)

{

  list_add(&node->list, &pos_node->list);

  tree->count++;

}

static void

avl_insert_before(struct avl_tree *tree, struct avl_node *pos_node, struct avl_node *node)

{

  list_add_tail(&node->list, &pos_node->list);

  tree->count++;

}

post_insert

static void

post_insert(struct avl_tree *tree, struct avl_node *node)

{

  struct avl_node *parent = node->parent;

 

  if (parent == NULL)  //noderoot node

    return;

 

  if (node == parent->left) { //node为左子树

    parent->balance--;        //减一

 

    if (parent->balance == 0)                 //已平衡

      return;

 

    if (parent->balance == -1) {    //parent node-1,继续判断上层节点是否平衡;

      post_insert(tree, parent);

      return;

    }

 

    if (node->balance == -1) {      //parent->balance == -2 & node->balance == -1 ; LL type

      avl_rotate_right(tree, parent);

      return;

    }

//parent->balance == -2 & node->balance ==1;  LR type

    avl_rotate_left(tree, node);

    avl_rotate_right(tree, node->parent->parent);

    return;

  }

 

  parent->balance++;  //node is right child;

 

  if (parent->balance == 0)  //ok

    return;

 

  if (parent->balance == 1) {         //判断上层是否平衡

    post_insert(tree, parent);

    return;

  }

 

  if (node->balance == 1) {            //parent->balance == 2&& node->balance==1; RR type

    avl_rotate_left(tree, parent);

    return;

  }

 

  avl_rotate_right(tree, node);     //parent->balance == 2&& node->balance== -1 ;;   RL type

  avl_rotate_left(tree, node->parent->parent);

}

static void

avl_rotate_right(struct avl_tree *tree, struct avl_node *node)

{

  struct avl_node *left, *parent;

 

  left = node->left;

  parent = node->parent;

 

  left->parent = parent;

  node->parent = left;

 

  if (parent == NULL)

    tree->root = left;

 

  else {

    if (parent->left == node)

      parent->left = left;

 

    else

      parent->right = left;

  }

 

  node->left = left->right;

  left->right = node;

 

  if (node->left != NULL)

    node->left->parent = node;

 

  node->balance += 1 - avl_min(left->balance, 0);

  left->balance += 1 + avl_max(node->balance, 0);

}

 

static void

avl_rotate_left(struct avl_tree *tree, struct avl_node *node)

{

  struct avl_node *right, *parent;

 

  right = node->right;

  parent = node->parent;

 

  right->parent = parent;

  node->parent = right;

 

  if (parent == NULL)

    tree->root = right;

 

  else {

    if (parent->left == node)

      parent->left = right;

 

    else

      parent->right = right;

  }

 

  node->right = right->left;

  right->left = node;

 

  if (node->right != NULL)

    node->right->parent = node;

 

  node->balance -= 1 + avl_max(right->balance, 0);

  right->balance -= 1 - avl_min(node->balance, 0);

}

 

avl_find_rec

返回一个nodecmp_result

若相等cmp_result == 0,存在;

cmp_result < 0,添加到node left侧;

cmp_result > 0,添加到node right侧;

static struct avl_node *

avl_find_rec(struct avl_node *node, const void *key, avl_tree_comp comp, void *cmp_ptr, int *cmp_result)

{

  int diff;

 

  diff = (*comp) (key, node->key, cmp_ptr);

  *cmp_result = diff;

 

  if (diff < 0) {

    if (node->left != NULL)  //key较小,则在左侧递归查找

      return avl_find_rec(node->left, key, comp, cmp_ptr, cmp_result);

 

    return node;

  }

 

  if (diff > 0) {

    if (node->right != NULL)                  //key较大,则在右侧递归查找

      return avl_find_rec(node->right, key, comp, cmp_ptr, cmp_result);

 

    return node;

  }

 

  return node;

}

删除节点avl_delete

/**

 * Remove a node from an avl tree

 * @param tree pointer to tree

 * @param node pointer to node

 */

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) {   //key值复用,若删除节点为首个节点

    if (tree->allow_dups

        && !list_is_last(&node->list, &tree->list_head)

        && !(next = avl_next(node))->leader) {     //存在相同key的其他节点

      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);   //拥有唯一key

  }

 

  avl_remove(tree, node);   //删除key值相同的,非首个node

}

 

avl_delete_worker

static void

avl_delete_worker(struct avl_tree *tree, struct avl_node *node)

{

  struct avl_node *parent, *min;

 

  parent = node->parent;

 

  if (node->left == NULL && node->right == NULL) {        //node 为叶子节点

    if (parent == NULL) {

      tree->root = NULL;

      return;

    }

 

    if (parent->left == node) {      //左叶子节点

      parent->left = NULL;

      parent->balance++;

 

      if (parent->balance == 1)

        return;

 

      if (parent->balance == 0) {

        avl_post_delete(tree, parent);

        return;

      }

 

      if (parent->right->balance == 0) {

        avl_rotate_left(tree, parent);

        return;

      }

 

      if (parent->right->balance == 1) {

        avl_rotate_left(tree, parent);

        avl_post_delete(tree, parent->parent);

        return;

      }

 

      avl_rotate_right(tree, parent->right);

      avl_rotate_left(tree, parent);

      avl_post_delete(tree, parent->parent);

      return;

    }

 

    if (parent->right == node) {

      parent->right = NULL;

      parent->balance--;

 

      if (parent->balance == -1)

        return;

 

      if (parent->balance == 0) {

        avl_post_delete(tree, parent);

        return;

      }

 

      if (parent->left->balance == 0) {

        avl_rotate_right(tree, parent);

        return;

      }

 

      if (parent->left->balance == -1) {

        avl_rotate_right(tree, parent);

        avl_post_delete(tree, parent->parent);

        return;

      }

 

      avl_rotate_left(tree, parent->left);

      avl_rotate_right(tree, parent);

      avl_post_delete(tree, parent->parent);

      return;

    }

  }

 

  if (node->left == NULL) {   //非叶子node,左子树为空

    if (parent == NULL) {

      tree->root = node->right;

      node->right->parent = NULL;

      return;

    }

 

    node->right->parent = parent;

 

    if (parent->left == node)

      parent->left = node->right;

 

    else

      parent->right = node->right;

 

    avl_post_delete(tree, node->right);

    return;

  }

 

  if (node->right == NULL) { //右子树为空

    if (parent == NULL) {

      tree->root = node->left;

      node->left->parent = NULL;

      return;

    }

 

    node->left->parent = parent;

 

    if (parent->left == node)

      parent->left = node->left;

 

    else

      parent->right = node->left;

 

    avl_post_delete(tree, node->left);

    return;

  }

 

  min = avl_local_min(node->right);      //左右子树非空;右子树上选择最小节点;

  avl_delete_worker(tree, min);   //avl数中删除min node

  parent = node->parent;

 

  min->balance = node->balance; //使用node节点,替换掉node

  min->parent = parent;

  min->left = node->left;

  min->right = node->right;

 

  if (min->left != NULL)

    min->left->parent = min;

 

  if (min->right != NULL)

    min->right->parent = min;

 

  if (parent == NULL) {

    tree->root = min;

    return;

  }

 

  if (parent->left == node) {

    parent->left = min;

    return;

  }

 

  parent->right = min;

}

添加node 6  LR旋转

左孩子的右子树+1, 两次旋转;先左在右;



上图中balance有错误;

5->balance = -1; 8->balance=-2

4->balance = -1;

删除node 1

 

阅读(2441) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~