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); } } }
avl_node* left_right_rotation(avl_node *parent) { avl_node *temp; temp= parent -> left; parent-> left = right_right_rotation(temp); return left_left_rotation(parent); }
avl_node* right_left_rotation(avl_node *parent) { avl_node *temp; temp = parent -> right; parent->right = left_left_rotation(temp); return right_right_rotation(parent); }
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; }
/* * RL:右左对应的情况(右双旋转)。 * * 返回值:旋转后的根节点 */ static Node* right_left_rotation(AVLTree k1) { k1->right = left_left_rotation(k1->right); return right_right_rotation(k1); }
/* * LR:左右对应的情况(左双旋转)。 * * 返回值:旋转后的根节点 */ static Node* left_right_rotation(AVLTree k3) { k3->left = right_right_rotation(k3->left); return left_left_rotation(k3); }
Node* right_left_rotation(AVLTree v1) { v1->right = left_left_rotation(v1->right); return right_right_rotation(v1); }
Node* left_right_rotation(AVLTree v3) { v3->left = right_right_rotation(v3->left); return left_left_rotation(v3); }
Node* left_right_rotation (Node* parent) { Node* node = parent->left; parent -> left = right_right_rotation (node); return left_left_rotation (parent); }
Node* right_left_rotation (Node* parent) { Node* node = parent -> right; parent->right = left_left_rotation (node); return right_right_rotation (parent); }
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; }