zoukankan      html  css  js  c++  java
  • 平衡二叉树之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);
      }
    }
  • 相关阅读:
    【老生常谈】Attr与Prop的区别
    【NodeJs】入门笔记一
    absolute的left和right的妙用
    文本框选中文字却不出现蓝色选中状态
    Ajax
    Canvas 与 SVG 的区别
    如何学好英语
    xCode6中SizeClass的使用
    CocoaPods安装和使用教程
    Unity3D教程宝典之Shader篇:特别讲 CG函数
  • 原文地址:https://www.cnblogs.com/qionglouyuyu/p/4850717.html
Copyright © 2011-2022 走看看