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); } } }
/* * 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); } } }
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; } }
/* * 将结点插入到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; }
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; }
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; }
/* * 删除结点(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; }
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; }