平衡二叉树之AVL树

AVL树(命名来源于作者姓名,Adelson-Velskii和Landis),即平衡二叉树,满足以下的条件:

1)它的左子树和右子树都是AVL树

2)左子树和右子树的高度差不能超过1

从条件1可能看出是个递归定义。

AVL树中任何节点的两个儿子子树的高度最大差别为一,所以它也被称为高度平衡树。

AVL树插入节点的步骤,分为2类:

第1类:外侧插入,单旋转

第2类:内侧插入,双旋转(先旋转成外侧插入的情况,再单旋转)

由于调整以后,树高与插入前是相同的,所以无需再向上查看balance情况

 

代码实现:http://blog.chinaunix.net/uid-20662820-id-142440.html

struct node
{
  node* parent;
  node* left;
  node* right;
  int balance; //左右子树高度之差
  int key;
};

int searchNode(int key, node* root, node** parent) //如果没找到,parent也是指向要插入位置的父位置
{
  node* temp;
  assert(root != NULL);
  temp = root;
  *parent = root->parent;
  while (temp !=NULL)
  {
    if (temp->key == key)
      return 1;
    else
    {
       *parent = temp;
      if (temp->key > key)
        temp = temp->left;
      else 
        temp = temp->right;
    }
  }
  return 0;
}

node* adjustAVL(node* root, node* parent, node* child)
{
  node *cur;
  assert((parent != NULL)&&(child != NULL));
  switch (parent->balance)
  {
  case 2:
    if (child->balance == -1)//LR型(内侧插入):插入的节点的父节点直接升级做parent
    {
      cur = child->right;
      cur->parent = parent->parent;
      child->right = cur->left;
      if (cur->left != NULL)
        cur->left->parent = child;
      parent->left = cur->right;
      if (cur->right != NULL)
        cur->right->parent = parent;
      cur->left = child;
      child->parent = cur;
      cur->right = parent;
      if (parent->parent != NULL)
        if (parent->parent->left == parent)
          parent->parent->left = cur;
        else parent->parent->right = cur;
      else
        root = cur;
      parent->parent = cur;
      if (cur->balance == 0)
      {
        parent->balance = 0;
        child->balance = 0;
      }
      else if (cur->balance == -1)
      {
        parent->balance = 0;
        child->balance = 1;
      }
      else
      {
        parent->balance = -1;
        child->balance = 0;
      }
      cur->balance = 0;
    }
    else //LL型(外侧插入):插入的节点的父节点升级做child,child升级做parent
      child->parent = parent->parent;
      parent->left = child->right;
      if (child->right != NULL)
        child->right->parent = parent;
      child->right = parent;
      if (parent->parent != NULL)
        if (parent->parent->left == parent)
          parent->parent->left = child;
        else parent->parent->right = child;
      else
        root = child;
      parent->parent = child;
      if (child->balance == 1) //插入时
      {
        child->balance = 0;
        parent->balance = 0;
      }
      else //删除时
      {
        child->balance = -1;
        parent->balance = 1;
      }
    }
   break;
   
  case -2:
    if (child->balance == 1) //RL型
    {
      cur = child->left;
      cur->parent = parent->parent;
      child->left = cur->right;
      if (cur->right != NULL)
        cur->right->parent = child;
      parent->right = cur->left;
      if (cur->left != NULL)
        cur->left->parent = parent;
      cur->left = parent;
      cur->right = child;
      child->parent = cur;
      if (parent->parent != NULL)
        if (parent->parent->left == parent)
          parent->parent->left = cur;
        else parent->parent->right = cur;
      else
        root = cur;
      parent->parent = cur;
      if (cur->balance == 0)
      {
        parent->balance = 0;
        child->balance = 0;
      }
      else if (cur->balance == 1)
      {
        parent->balance = 0;
        child->balance = -1;
      }
      else
      {
        parent->balance = 1;
        child->balance = 0;
      }
      cur->balance = 0;
    }
    else //RR型
    {
      child->parent = parent->parent;
      parent->right = child->left;
      if (child->left != NULL)
        child->left->parent = parent;
      child->left = parent;
      if (parent->parent != NULL)
        if (parent->parent->left == parent)
          parent->parent->left = child;
        else parent->parent->right = child;
      else
        root = child;
      parent->parent = child;
      if (child->balance == -1) //插入时
      {
        child->balance = 0;
        parent->balance = 0;
      }
      else //删除时
      {
        child->balance = 1;
        parent->balance = -1;
      }
    }
    break;
  }
  return root;
}

node* insertNode(int key, node* root)
{
  node *parent, *cur, *child;
  assert (root != NULL);
  if (searchNode(key, root, &parent)) //结点已存在
    return root;
  else
  {
    cur = (node*)malloc(sizeof(node));
    cur->parent = parent;
    cur->key = key;
    cur->left = NULL;
    cur->right = NULL;
    cur->balance = 0;
    if (keykey)
    {
      parent->left = cur;
      child = parent->left;
    }
    else
    {
      parent->right = cur;
      child = parent->right;
    }
    
    while ((parent != NULL)) //查找需要调整的最小子树
    {
      if (child == parent->left)
        if (parent->balance == -1)
        {
          parent->balance = 0;
          return root;
        }
        else if (parent->balance == 1)
        {
          parent->balance = 2;
          break;
        }
        else
        {
          parent->balance = 1;
          child = parent;
          parent = parent->parent;
        }
      else if (parent->balance == 1) //是右孩子,不会引起不平衡
      {
        parent->balance = 0;
        return root;
      }
      else if (parent->balance == -1) //是右孩子,并且引起parent的不平衡
      {
        parent->balance = -2;
        break;
      }
      else //是右孩子,并且可能引起parent的parent的不平衡
      {
        parent->balance = -1;
        child = parent;
        parent = parent->parent;
      }
    }

    if (parent == NULL)
      return root;
    return adjustAVL(root, parent, child);
  }
}

 

posted on 2015-10-01 10:09  joannae  阅读(214)  评论(0编辑  收藏  举报

导航