Zig-Zig (Left Left Case): G P X / \ / \ / \ P T4 rightRotate(G) X G rightRotate(P) T1 P / \ ============> / \ / \ ============> / \ X T3 T1 T2 T3 T4 T2 G / \ / \ T1 T2 T3 T4
Zag-Zag (Right Right Case): G P X / \ / \ / \ T1 P leftRotate(G) G X leftRotate(P) P T4 / \ ============> / \ / \ ============> / \ T2 X T1 T2 T3 T4 G T3 / \ / \ T3 T4 T1 T2
3.b. Zig-Zag and Zag-Zig 节点是父节点的左儿子,父节点是祖父节点的右儿子(左旋,接着右旋),或者,节点父节点的右儿子,父节点是祖父节点的左儿子(右旋,接着左旋)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Zag-Zig (Left Right Case): G G X / \ / \ / \ P T4 leftRotate(P) X T4 rightRotate(G) P G / \ ============> / \ ============> / \ / \ T1 X P T3 T1 T2 T3 T4 / \ / \ T2 T3 T1 T2
Zig-Zag (Right Left Case): G G X / \ / \ / \ T1 P rightRotate(P) T1 X leftRotate(P) G P / \ =============> / \ ============> / \ / \ X T4 T2 P T1 T2 T3 T4 / \ / \ T2 T3 T3 T4
// An AVL tree node classnode { public: int key; node *left, *right; };
/* Helper function that allocates a new node with the given key and NULL left and right pointers. */ node* newNode(int key) { node* Node = new node(); Node->key = key; Node->left = Node->right = NULL; return (Node); }
// A utility function to right // rotate subtree rooted with y // See the diagram given above. node *rightRotate(node *x) { node *y = x->left; x->left = y->right; y->right = x; return y; }
// A utility function to left // rotate subtree rooted with x // See the diagram given above. node *leftRotate(node *x) { node *y = x->right; x->right = y->left; y->left = x; return y; }
// This function brings the key at // root if key is present in tree. // If key is not present, then it // brings the last accessed item at // root. This function modifies the // tree and returns the new root node *splay(node *root, int key) { // Base cases: root is NULL or // key is present at root if (root == NULL || root->key == key) return root;
// Key lies in left subtree if (root->key > key) { // Key is not in tree, we are done if (root->left == NULL) return root;
// Zig-Zig (Left Left) if (root->left->key > key) { // First recursively bring the // key as root of left-left root->left->left = splay(root->left->left, key);
// Do first rotation for root, // second rotation is done after else root = rightRotate(root); } elseif (root->left->key < key) // Zig-Zag (Left Right) { // First recursively bring // the key as root of left-right root->left->right = splay(root->left->right, key);
// Do first rotation for root->left if (root->left->right != NULL) root->left = leftRotate(root->left); }
// Do second rotation for root return (root->left == NULL)? root: rightRotate(root); } else// Key lies in right subtree { // Key is not in tree, we are done if (root->right == NULL) return root;
// Zag-Zig (Right Left) if (root->right->key > key) { // Bring the key as root of right-left root->right->left = splay(root->right->left, key);
// Do first rotation for root->right if (root->right->left != NULL) root->right = rightRotate(root->right); } elseif (root->right->key < key)// Zag-Zag (Right Right) { // Bring the key as root of // right-right and do first rotation root->right->right = splay(root->right->right, key); root = leftRotate(root); }
// Do second rotation for root return (root->right == NULL)? root: leftRotate(root); } }
// The search function for Splay tree. // Note that this function returns the // new root of Splay Tree. If key is // present in tree then, it is moved to root. node *search(node *root, int key) { return splay(root, key); }
// A utility function to print // preorder traversal of the tree. // The function also prints height of every node voidpreOrder(node *root) { if (root != NULL) { cout<<root->key<<" "; preOrder(root->left); preOrder(root->right); } }