Example #1
0
 void Balance (Node* n) {
   //n is the parent node that has +-2 factor
   int bfactor = getFactor (n);
   //left subtree outweights the right one
   if (bfactor == 2) {
     //the bfactor on its left child needs to be checked
     int lchildfactor = getFactor (n->left);
     //left right rotation is needed
     if (lchildfactor == -1) {
       printf ("left right rotation\n");
       n = left_right_rotation (n);
     }
     //a single right rotation is needed
     else if (lchildfactor == 1) {
       printf ("left left rotation\n");
       n = left_left_rotation (n);
     }
   }
   //right subtree outweights the left one
   else if (bfactor == -2) {
     //the bfactor on its right child needs to be checked
     int rchildfactor = getFactor (n->right);
     //single left rotation is needed
     if (rchildfactor == -1) {
       printf ("right right rotation\n");
       n = right_right_rotation (n);
     }
     //right left rotation is needed
     else if (rchildfactor = 1) {
       printf ("right left rotation\n");
       n = right_left_rotation (n);
     }
   }
 }
Example #2
0
/*
 * if the balance of the node is greater than 1 or less than -1, 
 * then balance the tree. 
 * case 1. a: node->balance >= 2, b: node->right->balance > 0;
 *         left_rotation the node. a->balance = b->balance.
 * case 2. a: node->balance >=2, b: node->right->balance < 0, c: node->right->left->balance ==0;
 *         right_left_rotation the node. a->balance = b->balance = c->balance = 0.
 * case 3. a: node->balance >= 2, b: node->right->balance < 0, c: node->right->left->balance > 0; 
 *         right_left_roation the node. a->balance = -1, b->balance = 0, c->balance = 0;
 * case 4. a: node->balance >= 2, b: node->right->balance < 0, c: node->right->left->balance < 0;
 *         right_left_rotation the node. a->balance = 0, b->balance = 1, c->balance = 0;
 * case 5 - 8 is symmetrical to case 1-4. 
 */
static void tree_insert_balance(avl_node *node)
{
	if(node->balance > 0)
	{
		avl_node *child = node->right;
		if(child->balance > 0)
		{
			node->balance = child->balance = 0;
			left_rotation(node);
		}
		else
		{
			avl_node *left_child = child->left;
			if(left_child->balance == 0)
				node->balance = child->balance = 0;
			else if(left_child->balance > 0)
			{
				node->balance = -1;
				child->balance = 0;
			}
			else
			{
				node->balance = 0;
				child->balance = 1;
			}
			left_child->balance = 0;
			right_left_rotation(node);
		}
	}
	else
	{
		avl_node *child = node->left;
		if(child->balance < 0)
		{
			node->balance = child->balance = 0;
			right_rotation(node);
		}
		else
		{
			avl_node *right_child= child->right;
			if(right_child->balance == 0)
			{
				node->balance = child->balance = 0;
			}
			else if(right_child->balance > 0)
			{
				node->balance = 0;
				child->balance = -1;
			}
			else
			{
				node->balance = 1;
				child->balance = 0;
			}
			right_child->balance = 0;
			left_right_rotation(node);
		}
	}
}
Example #3
0
static void rebalance_grew(AvlNode *this_node, AvlNode **root)
{
	AvlNode *previous_node = this_node;
	this_node = this_node->links.parent;

	while (this_node)
	{
		if (this_node->links.left == previous_node)
			if (this_node->balance == RIGHT_IS_HEAVY)
			{
				this_node->balance = BALANCED;
				return;
			}
			else
				if (this_node->balance == BALANCED)
					this_node->balance = LEFT_IS_HEAVY;
				else
				{
					if (previous_node->balance == LEFT_IS_HEAVY)
						right_right_rotation(this_node, previous_node, root);
					else
						left_right_rotation(this_node, previous_node, previous_node->links.right, root);

					return;
				}
		else
			if (this_node->balance == LEFT_IS_HEAVY)
			{
				this_node->balance = BALANCED;
				return;
			}
			else
				if (this_node->balance == BALANCED)
					this_node->balance = RIGHT_IS_HEAVY;
				else
				{
					if (previous_node->balance == RIGHT_IS_HEAVY)
						left_left_rotation(this_node, previous_node, root);
					else
						right_left_rotation(this_node, previous_node, previous_node->links.left, root);

					return;
				}

		previous_node = this_node;
		this_node = this_node->links.parent;
	}
}
Example #4
0
/*
 * 将结点插入到AVL树中,并返回根节点
 *
 * 递归方法
 *
 * 参数说明:
 *     tree AVL树的根结点
 *     key 插入的结点的键值
 * 返回值:
 *     根节点
 */
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);
        // 插入节点后,若AVL树失去平衡,则进行相应的调节。
        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;
}
Example #5
0
Node* Insert(AVLTree tree, ElemType value)
{
    if (tree == NULL)
    {
        // 新建节点
        tree = CreateNode(value, NULL, NULL);
        if (tree==NULL)
        {
            printf("ERROR: create avltree node failed!\n");
            return NULL;
        }
    }
    else if (value < tree->value) // 应该将key插入到"tree的左子树"的情况
    {
        tree->left = Insert(tree->left, value);
        // 插入节点后,若AVL树失去平衡,则进行相应的调节。
        if (HEIGHT(tree->left) - HEIGHT(tree->right) == 2)
        {
            if (value < tree->left->value)
                tree = left_left_rotation(tree);
            else
                tree = left_right_rotation(tree);
        }
    }
    else if (value > tree->value) // 应该将key插入到"tree的右子树"的情况
    {
        tree->right = Insert(tree->right, value);
        // 插入节点后,若AVL树失去平衡,则进行相应的调节。
        if (HEIGHT(tree->right) - HEIGHT(tree->left) == 2)
        {
            if (value > tree->right->value)
                tree = right_right_rotation(tree);
            else
                tree = right_left_rotation(tree);
        }
    }
    else //value == tree->value)
    {
        printf("结点已经存在!\n");
    }
    tree->height = MAX( HEIGHT(tree->left), HEIGHT(tree->right)) + 1;
    return tree;
}
Example #6
0
avl_node* balancing(avl_node *node) {
    int b_factor = get_diff(node);
    
    if (b_factor > 1) {
        if (get_diff(node->left) > 0) {
            node = left_left_rotation(node);
        } else {
            node = left_right_rotation(node);
        }
    } else if (b_factor < -1) {
        if (get_diff(node->right) > 0) {
            node = right_left_rotation(node);
        } else {
            node = right_right_rotation(node);
        }
    }
    
    return node;
}
Example #7
0
/*
 * 删除结点(z),返回根节点
 *
 * 递归方法
 *
 * 参数说明:
 *     ptree AVL树的根结点
 *     z 待删除的结点
 * 返回值:
 *     根节点
 */
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);
        // 删除节点后,若AVL树失去平衡,则进行相应的调节。
        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的左子树比右子树高;
                // 则(01)找出tree的左子树中的最大节点
                //   (02)将该最大节点的值赋值给tree。
                //   (03)删除该最大节点。
                // 这类似于用"tree的左子树中最大节点"做"tree"的替身;
                // 采用这种方式的好处是:删除"tree的左子树中最大节点"之后,AVL树仍然是平衡的。
                Node *max = avltree_maximum(tree->left);
                tree->key = max->key;
                tree->left = delete_node(tree->left, max);
            }
            else
            {
                // 如果tree的左子树不比右子树高(即它们相等,或右子树比左子树高1)
                // 则(01)找出tree的右子树中的最小节点
                //   (02)将该最小节点的值赋值给tree。
                //   (03)删除该最小节点。
                // 这类似于用"tree的右子树中最小节点"做"tree"的替身;
                // 采用这种方式的好处是:删除"tree的右子树中最小节点"之后,AVL树仍然是平衡的。
                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;
}
Example #8
0
static void rebalance_shrunk(AvlNode *this_node, AvlNode **root)
{
	Links previous_node_links = {};
	AvlNode *previous_node = 0;
	AvlNode *node_to_remove = this_node;
	this_node = this_node->links.left;

	while (this_node)
	{
		previous_node = this_node;
		this_node = this_node->links.right;
	}

	if (previous_node == 0)
		previous_node = node_to_remove->links.right;

	if (previous_node)
	{
		if (previous_node->links.parent == node_to_remove)
			this_node = previous_node;
		else
			this_node = previous_node->links.parent;

		previous_node_links = previous_node->links;
		previous_node->balance = node_to_remove->balance;
		previous_node->links = node_to_remove->links;

		if (previous_node->links.parent == 0)
			(*root) = previous_node;
		else
			if (previous_node->links.parent->links.left == node_to_remove)
				previous_node->links.parent->links.left = previous_node;
			else
				previous_node->links.parent->links.right = previous_node;
	}
	else
	{
		this_node = node_to_remove->links.parent;
		previous_node = node_to_remove;
	}

	if (this_node)
	{
		if (this_node->links.left == previous_node)
		{
			this_node->links.left = previous_node_links.left;

			if (this_node->balance == LEFT_IS_HEAVY)
				this_node->balance = BALANCED;
			else
				if (this_node->balance == BALANCED)
					this_node->balance = RIGHT_IS_HEAVY;
				else
					if (this_node->links.right->balance == RIGHT_IS_HEAVY)
					{
						node_to_remove = this_node->links.right;
						left_left_rotation(this_node, this_node->links.right, root);
						this_node = node_to_remove;
					}
					else
					{
						node_to_remove = this_node->links.right->links.left;
						right_left_rotation(this_node, this_node->links.right, this_node->links.right->links.left, root);
						this_node = node_to_remove;
					}
		}
		else
		{
			this_node->links.right = previous_node_links.right;

			if (this_node->balance == RIGHT_IS_HEAVY)
				this_node->balance = BALANCED;
			else
				if (this_node->balance == BALANCED)
					this_node->balance = LEFT_IS_HEAVY;
				else
					if (this_node->links.left->balance == LEFT_IS_HEAVY)
					{
						node_to_remove = this_node->links.left;
						right_right_rotation(this_node, this_node->links.left, root);
						this_node = node_to_remove;
					}
					else
					{
						node_to_remove = this_node->links.left->links.right;
						left_right_rotation(this_node, this_node->links.left, this_node->links.left->links.right, root);
						this_node = node_to_remove;
					}
		}

		previous_node = this_node;
		this_node = this_node->links.parent;

		while (this_node)
		{
			if (this_node->links.left == previous_node)
				if (this_node->balance == LEFT_IS_HEAVY)
					this_node->balance = BALANCED;
				else
					if (this_node->balance == BALANCED)
						this_node->balance = RIGHT_IS_HEAVY;
					else
						if (this_node->links.right->balance == RIGHT_IS_HEAVY)
						{
							node_to_remove = this_node->links.right;
							left_left_rotation(this_node, this_node->links.right, root);
							this_node = node_to_remove;
						}
						else
						{
							node_to_remove = this_node->links.right->links.left;
							right_left_rotation(this_node, this_node->links.right, this_node->links.right->links.left, root);
							this_node = node_to_remove;
						}
			else
				if (this_node->balance == RIGHT_IS_HEAVY)
					this_node->balance = BALANCED;
				else
					if (this_node->balance == BALANCED)
						this_node->balance = LEFT_IS_HEAVY;
					else
						if (this_node->links.left->balance == LEFT_IS_HEAVY)
						{
							node_to_remove = this_node->links.left;
							right_right_rotation(this_node, this_node->links.left, root);
							this_node = node_to_remove;
						}
						else
						{
							node_to_remove = this_node->links.left->links.right;
							left_right_rotation(this_node, this_node->links.left, this_node->links.left->links.right, root);
							this_node = node_to_remove;
						}

			previous_node = this_node;
			this_node = this_node->links.parent;
		}
	}
	else
		(*root) = 0;
}