🌒

Stack Pub

平衡二叉(AVL)树

平衡二叉树(balance binary tree)是二叉排序树的进化体,由G.M.Adelson-Velsky和E.M. Landis提出的,所以又叫AVL树。

平衡二叉树是指它除了具备二叉排序树的基本特征之外,还具有一个重要的特定:它的左子树与右子树的深度之差(平衡因子)的绝对值不超过1,且都是平衡二叉树。

平衡因子

平衡因子(Balance Factor,BF):二叉树结点的左子树深度减去右子树深度的值。平衡二叉树的平衡因子的绝对值不超过1。平
衡因子绝对值大于1的结点为根节点的子树就是最小不平衡子树。调整节点之间的链接关的基本方法就是旋转

旋转

左旋(朝左旋转)

左旋

左旋规则:在产生的最小不平衡子树根结点右孩子的右孩子处插入结点,即最小不平衡子树的根结点及其右孩子的平衡因子都为负,则以根结点的右孩子为支点进行左旋转,根结点变为支点的左孩子。

static Node* right_right_rotation(AVLTree k1)
{
    AVLTree k2;

    k2 = k1->right;
    k1->right = k2->left;
    k2->left = k1;

    k1->height = MAX( HEIGHT(k1->left), HEIGHT(k1->right)) + 1;
    k2->height = MAX( HEIGHT(k2->right), k1->height) + 1;

    return k2;
}

右旋(朝右旋转)

右旋

右旋规则:在产生的最小不平衡子树的根结点及其左孩子平衡因子都为正,即在最小不平衡子树根结点的左孩子的左孩子出插入结点,则以根结点的左孩子为支点进行右旋。

static Node* left_left_rotation(AVLTree k2)
{
    AVLTree k1;

    k1 = k2->left;
    k2->left = k1->right;
    k1->right = k2;

    k2->height = MAX( HEIGHT(k2->left), HEIGHT(k2->right)) + 1;
    k1->height = MAX( HEIGHT(k1->left), k2->height) + 1;

    return k1;
}

左右旋(先向左旋在向右旋)

左右旋

static Node* left_right_rotation(AVLTree k3)
{
    k3->left = right_right_rotation(k3->left);

    return left_left_rotation(k3);
}

右左旋(先向右旋在向左旋)

右左旋

static Node* right_left_rotation(AVLTree k1)
{
    k1->right = left_left_rotation(k1->right);

    return right_right_rotation(k1);
}

插入

Node* avltree_insert(AVLTree tree, Type key)
{
  if (tree == NULL) 
  {
    tree = avltree_create_node(key, NULL, NULL);
    if (tree==NULL)
    {
      printf("ERROR: create avltree node failed!\n");
      return NULL;
    }
  }
  else if (key < tree->key) /* 将key插入到tree的左子树 */
  {
    tree->left = avltree_insert(tree->left, key);
    /* 插入节点后,若AVL树失去平衡,则进行相应的调节 */
    if (HEIGHT(tree->left) - HEIGHT(tree->right) == 2)
    {
      if (key < tree->left->key)
        tree = left_left_rotation(tree);
      else
        tree = left_right_rotation(tree);
    }
  }
  else if (key > tree->key) /* 将key插入到tree的右子树 */
  {
    tree->right = avltree_insert(tree->right, key);
    
		if (HEIGHT(tree->right) - HEIGHT(tree->left) == 2)
    {
      if (key > tree->right->key)
        tree = right_right_rotation(tree);
      else
        tree = right_left_rotation(tree);
    }
  }
  else /* key == tree->key */
  {
    printf("添加失败:不允许添加相同的节点!\n");
  }

  tree->height = MAX( HEIGHT(tree->left), HEIGHT(tree->right)) + 1;
 
  return tree;
}

删除

static Node* delete_node(AVLTree tree, Node *z)
{
  /* 根为空或者没有要删除的节点,直接返回NULL */
  if (tree==NULL || z==NULL)
    return NULL;
  
  if (z->key < tree->key)  /* 待删除的节点在tree的左子树中 */
  {
    tree->left = delete_node(tree->left, z);
    /* 删除节点后,若AVL树失去平衡,则进行相应的调节 */
    if (HEIGHT(tree->right) - HEIGHT(tree->left) == 2)
    {
      Node *r =  tree->right;

      if (HEIGHT(r->left) > HEIGHT(r->right))
        tree = right_left_rotation(tree);
      else
        tree = right_right_rotation(tree);
    }
  }
  else if (z->key > tree->key)/* 待删除的节点在tree的右子树中 */
  {
    tree->right = delete_node(tree->right, z);
    
		if (HEIGHT(tree->left) - HEIGHT(tree->right) == 2)
    {
      Node *l =  tree->left;
      if (HEIGHT(l->right) > HEIGHT(l->left))
        tree = left_right_rotation(tree);
      else
        tree = left_left_rotation(tree);
    }
  }
  else  /* tree是对应要删除的节点 */
  {
    /* tree的左右孩子都非空 */
    if ((tree->left) && (tree->right))
    {
      if (HEIGHT(tree->left) > HEIGHT(tree->right))
      {
        /* 如果tree的左子树比右子树高,则:
				 1. 找出tree的左子树中的最大节点(左子树的最大结点只小于该结点)
         2. 将该最大节点的值赋值给tree
         3. 删除该最大节点
         4. 这类似于用tree的左子树中最大节点做tree的替身 */
        Node *max = avltree_maximum(tree->left);
        tree->key = max->key;
        tree->left = delete_node(tree->left, max);
      }
      else
      {
        /* 如果tree的左子树不比右子树高(即它们相等,或右子树比左子树高1),则:
         1. 找出tree的右子树中的最小节点
         2. 将该最小节点的值赋值给tree
         3. 删除该最小节点 */
        Node *min = avltree_maximum(tree->right);
        tree->key = min->key;
        tree->right = delete_node(tree->right, min);
      }
    }
    else
    {
      Node *tmp = tree;
      tree = tree->left ? tree->left : tree->right;
      free(tmp);
    }
  }

  return tree;
}

Node* avltree_delete(AVLTree tree, Type key)
{
  Node *z;

  if ((z = avltree_search(tree, key)) != NULL)
    tree = delete_node(tree, z);
  
	return tree;
}

, — May 27, 2019

GitHub RSS