AVL Tree | Set 2 (Deletion)

原文链接:https://www.geeksforgeeks.org/avl-tree-set-2-deletion/

Steps to follow for deletion.
To make sure that the given tree remains AVL after every deletion, we must augment the standard BST delete operation to perform some re-balancing. Following are two basic operations that can be performed to re-balance a BST without violating the BST property (keys(left) < key(root) < keys(right)).

  1. Left Rotation
  2. Right Rotation
T1, T2 and T3 are subtrees of the tree rooted with y (on left side)
or x (on right side)
                y                               x
               / \     Right Rotation          /  \
              x   T3   – --->        T1   y
             / \       < - - - - - - -            / \
            T1  T2     Left Rotation            T2  T3
Keys in both of the above trees follow the following order
      keys(T1) < key(x) < keys(T2) < key(y) < keys(T3)
So BST property is not violated anywhere.

c) Right Right Case

  z                                y
 /  \                            /   \ 
T1   y     Left Rotate(z)       z      x
    /  \   - - - - - - - ->    / \    / \
   T2   x                     T1  T2 T3  T4
       / \
     T3  T4

C implementation
Following is the C implementation for AVL Tree Deletion. The following C implementation uses the recursive BST delete as basis. In the recursive BST delete, after deletion, we get pointers to all ancestors one by one in bottom up manner. So we don’t need parent pointer to travel up. The recursive code itself travels up and visits all the ancestors of the deleted node.

我们使用递归的程序进行AVL树删除结点,在用递归程序时,在删除节点后,这个时候的指针就是指向其父亲,再自动递归返回时,就会进行从下到上访问其祖父结点。

  1. Perform the normal BST deletion.
    1)进行正常的BST删除。

  2. The current node must be one of the ancestors of the deleted node. Update the height of the current node.
    现在结点指向删除结点的父亲结点,更新其高度。

  3. Get the balance factor (left subtree height – right subtree height) of the current node.
    再计算其平衡因子。

  4. If balance factor is greater than 1, then the current node is unbalanced and we are either in Left Left case or Left Right case. To check whether it is Left Left case or Left Right case, get the balance factor of left subtree. If balance factor of the left subtree is greater than or equal to 0, then it is Left Left case, else Left Right case.
    如果平衡因子大于1,那么现在结点是不平衡的,也么是left left case or left right case,为了检查到底是哪一个,我们进行得到他左子树的平衡因子。如果左子树的平衡因子>=0,那么就是left left case,否则就是left right case.

  5. If balance factor is less than -1, then the current node is unbalanced and we are either in Right Right case or Right Left case. To check whether it is Right Right case or Right Left case, get the balance factor of right subtree. If the balance factor of the right subtree is smaller than or equal to 0, then it is Right Right case, else Right Left case.

#include
#include
using namespace std;
class Node{
public:
    int data;
    Node *left,*right;
    int height;
    Node():data(0),left(NULL),right(NULL),height(0){};
};

int getHeight(Node *node);
int max(int a,int b);
Node* newNode(int key);
Node *rightRotate(Node *node);
Node *leftRotate(Node *node);
int getBalance(Node *node);
Node *insert(Node *node,int key);
Node *minValueNode(Node *node);
Node *deletNode(Node *root,int key);
void preOrder(Node *node);

int main(){
    Node *root=NULL;
    root = insert(root, 9);
    root = insert(root, 11);
    root = insert(root, 10);
    root = insert(root, 6);
    root = insert(root, 5);
    root = insert(root, 0);
    root = insert(root, 2);
    root = insert(root, -1);
    root = insert(root, 1);
    preOrder(root);
    printf("\n");
    root = deletNode(root,10);
    preOrder(root);
    printf("\n");
    return 0;
}

int getHeight(Node *node){
    if(node==NULL){
        return 0;
    }return node->height;
}
// A utility function to get maximum of two integers
int max(int a,int b){
    return (a>b)?a:b;
}
Node* newNode(int key){
    Node* node=new Node();
    node->data=key;
    return node;
}

Node *rightRotate(Node *node){
    Node *x=node->left;
    Node *T2=x->right;
    x->right=node;
    node->left=T2;
    node->height=max(getHeight(node->left),getHeight(node->right))+1;
    x->height=max(getHeight(x->left),getHeight(x->right))+1;
    return x;
}

Node *leftRotate(Node *node){
    Node *y=node->right;
    Node *T2=y->left;
    y->left=node;
    node->right=T2;
    node->height=max(getHeight(node->left),getHeight(node->right))+1;
    y->height=max(getHeight(y->left),getHeight(y->right))+1;
    return y;
}

int getBalance(Node *node){
    if(node==NULL){return 0;}
    return (getHeight(node->left)-getHeight(node->right));
}

Node *insert(Node *node,int key){
    if(node==NULL){return newNode(key);}
    else if(key>node->data){
        node->right=insert(node->right,key);
    }else if(key<node->data){
        node->left=insert(node->left,key);
    }else return node;
    node->height=max(getHeight(node->left),getHeight(node->right))+1;
    printf("node->data=%d,node->height=%d\n",node->data,node->height);
    int balfac=getBalance(node);
    // If this node becomes unbalanced,then there are 4 cases
    if(balfac>1&&key<node->left->data){
        printf("rightRotate:%d\n",node->data);
        return rightRotate(node);
    }
    if(balfac>1&&key>node->left->data){
        printf("001:leftRotate(%d)\n",node->left->data);
        node->left=leftRotate(node->left);
        printf("002:rightRotate(%d)\n",node->data);
        return  rightRotate(node);
    }
    if(balfac<-1&&key>node->right->data){
        cout<<"leftRotate:"<<node->data<<endl;
        return leftRotate(node);
    }
    if(balfac<-1&&key<node->right->data){
        printf("001:rightRotate(%d)\n",node->right->data);
        node->right=rightRotate(node->right);
        printf("002:leftRotate(%d)\n",node->data);
        return  leftRotate(node);
    }
    return node;        /* return the (unchanged) node pointer */
}
// Recursive function to delete a node with given key from subtree with
// given root. It returns root of the modified subtree.
Node *minValueNode(Node *node){
    Node *current=node;
    while(current->left!=NULL){
        current=current->left;
    }
    return current;
}
Node *deletNode(Node *root,int key){
    // STEP 1: PERFORM STANDARD BST DELETE
    if(root==NULL){return root;}
    else if(key>root->data){
        root->right=deletNode(root->right,key);
    }else if(key<root->data){
        root->left=deletNode(root->left,key);
    }else{      //找到了
        // node with only one child or no child
        if(root->left==NULL||root->right==NULL){
            Node *tmp=root->left?root->left:root->right;
            // No child case
            if(tmp==NULL){
                tmp=root;
                root=NULL;
            }else{
                *root=*tmp;     // Copy the contents of
                free(tmp);      // the non-empty child
            }
        }else{
            //node with two children: Get the inorder
            // successor (smallest in the right subtree)
            Node *tmp=minValueNode(root->right);
            // Copy the inorder successor's data to this node
            root->data=tmp->data;
            // Delete the inorder successor
            root->right=deletNode(root->right, tmp->data);
        }
    }
    // STEP 2: UPDATE HEIGHT OF THE CURRENT NODE
    root->height=1+max(getHeight(root->left),getHeight(root->right));
    // STEP 3: GET THE BALANCE FACTOR OF THIS NODE (to check whether this
    // node became unbalanced)
    int balfac=getBalance(root);
    // If this node becomes unbalanced,then there are 4 cases(just like insert operation)
    // Left Left Case
    if(balfac>1&&getBalance(root->left)>=0){
        return rightRotate(root);
    }
    // Left Right Case
    if(balfac>1&&getBalance(root->left)<0){
        root->left=leftRotate(root->left);
        return rightRotate(root);
    }
    // Right Right Case
    if(balfac<-1&&getBalance(root->right)<=0){
        return leftRotate(root);
    }
    if(balfac<-1&&getBalance(root->right)>0){
        root->right=rightRotate(root->right);
        return leftRotate(root);
    }
    return root;
}

void preOrder(Node *node){
    if(node==NULL){
        return ;
    }
    printf("%d->",node->data);
    preOrder(node->left);
    preOrder(node->right);
}


// C++ program to delete a node from AVL Tree
#include
#include
using namespace std;

// An AVL tree node
class Node
{
    public:
    int key;
    Node *left;
    Node *right;
    int height;
};

// A utility function to get maximum
// of two integers
int max(int a, int b);

// A utility function to get height
// of the tree
int height(Node *N)
{
    if (N == NULL)
        return 0;
    return N->height;
}

// A utility function to get maximum
// of two integers
int max(int a, int b)
{
    return (a > b)? a : b;
}

/* 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 = NULL;
    node->right = NULL;
    node->height = 0; // new node is initially
                    // added at leaf
    return(node);
}

// A utility function to right
// rotate subtree rooted with y
// See the diagram given above.
Node *rightRotate(Node *y)
{   printf("rightRotate:%d\n",y->key);
    Node *x = y->left;
    Node *T2 = x->right;

    // Perform rotation
    x->right = y;
    y->left = T2;

    // Update heights
    y->height = max(height(y->left),
                    height(y->right)) + 1;
    x->height = max(height(x->left),
                    height(x->right)) + 1;

    // Return new root
    return x;
}

// A utility function to left
// rotate subtree rooted with x
// See the diagram given above.
Node *leftRotate(Node *x)
{   printf("leftRotate:%d\n",x->key);
    Node *y = x->right;
    Node *T2 = y->left;

    // Perform rotation
    y->left = x;
    x->right = T2;

    // Update heights
    x->height = max(height(x->left),
                    height(x->right)) + 1;
    y->height = max(height(y->left),
                    height(y->right)) + 1;

    // Return new root
    return y;
}

// Get Balance factor of node N
int getBalance(Node *N)
{
    if (N == NULL)
        return 0;
    return height(N->left) -
        height(N->right);
}

Node* insert(Node* node, int key)
{
    /* 1. Perform the normal BST rotation */
    if (node == NULL)
        return(newNode(key));

    if (key < node->key)
        node->left = insert(node->left, key);
    else if (key > node->key)
        node->right = insert(node->right, key);
    else // Equal keys not allowed
        return node;

    /* 2. Update height of this ancestor node */
    node->height = 1 + max(height(node->left),
                        height(node->right));
    /* 3. Get the balance factor of this
        ancestor node to check whether
        this node became unbalanced */
    int balance = getBalance(node);
    printf("node->data=%d,height=%d,balance=%d\n",node->key,node->height,balance);
    // If this node becomes unbalanced,
    // then there are 4 cases

    // Left Left Case
    if (balance > 1 && key < node->left->key){
       
        return rightRotate(node);}

    // Right Right Case
    if (balance < -1 && key > node->right->key){
        return leftRotate(node);}

    // Left Right Case
    if (balance > 1 && key > node->left->key)
    {
        node->left = leftRotate(node->left);
        return rightRotate(node);
    }

    // Right Left Case
    if (balance < -1 && key < node->right->key)
    {
        node->right = rightRotate(node->right);
        return leftRotate(node);
    }

    /* return the (unchanged) node pointer */
    return node;
   // printf("root:%d\n",node->key);
}

/* Given a non-empty binary search tree,
return the node with minimum key value
found in that tree. Note that the entire
tree does not need to be searched. */
Node * minValueNode(Node* node)
{
    Node* current = node;

    /* loop down to find the leftmost leaf */
    while (current->left != NULL)
        current = current->left;

    return current;
}

// Recursive function to delete a node
// with given key from subtree with
// given root. It returns root of the
// modified subtree.
Node* deleteNode(Node* root, int key)
{
    
    // STEP 1: PERFORM STANDARD BST DELETE
    if (root == NULL)
        return root;

    // If the key to be deleted is smaller
    // than the root's key, then it lies
    // in left subtree
    if ( key < root->key )
        root->left = deleteNode(root->left, key);

    // If the key to be deleted is greater
    // than the root's key, then it lies
    // in right subtree
    else if( key > root->key )
        root->right = deleteNode(root->right, key);

    // if key is same as root's key, then
    // This is the node to be deleted
    else
    {
        // node with only one child or no child
        if( (root->left == NULL) ||(root->right == NULL) )
        {
            Node *temp = root->left ?
                        root->left :
                        root->right;

            // No child case
            if (temp == NULL)
            {
                temp = root;
                root = NULL;
            }
            else // One child case
            *root = *temp; // Copy the contents of
                        // the non-empty child
            free(temp);
        }
        else
        {
            // node with two children: Get the inorder
            // successor (smallest in the right subtree)
            Node* temp = minValueNode(root->right);

            // Copy the inorder successor's
            // data to this node
            root->key = temp->key;

            // Delete the inorder successor
            root->right = deleteNode(root->right,
                                    temp->key);
        }
    }

    // If the tree had only one node
    // then return
    if (root == NULL)
    return root;

    // STEP 2: UPDATE HEIGHT OF THE CURRENT NODE
    root->height = 1 + max(height(root->left),
                        height(root->right));

    // STEP 3: GET THE BALANCE FACTOR OF
    // THIS NODE (to check whether this
    // node became unbalanced)
    int balance = getBalance(root);

    // If this node becomes unbalanced,
    // then there are 4 cases

    // Left Left Case
    if (balance > 1 &&
        getBalance(root->left) >= 0)
        return rightRotate(root);

    // Left Right Case
    if (balance > 1 &&
        getBalance(root->left) < 0)
    {
        root->left = leftRotate(root->left);
        return rightRotate(root);
    }

    // Right Right Case
    if (balance < -1 &&
        getBalance(root->right) <= 0)
        return leftRotate(root);

    // Right Left Case
    if (balance < -1 &&
        getBalance(root->right) > 0)
    {
        root->right = rightRotate(root->right);
        return leftRotate(root);
    }
    return root;
}

// A utility function to print preorder
// traversal of the tree.
// The function also prints height
// of every node
void preOrder(Node *root)
{
    if(root != NULL)
    {
        cout << root->key << " ";
        preOrder(root->left);
        preOrder(root->right);
    }
}

// Driver Code
int main()
{
Node *root = NULL;

    /* Constructing tree given in
    the above figure */
    root = insert(root, 12);
    root = insert(root, 11);
    root = insert(root, 10);
    root = insert(root, 9);
    root = insert(root, 8);
    root = insert(root, -1);
    root = insert(root, 1);
    root = insert(root, 0);
    root = insert(root, 21);
    root = insert(root, 14);
    root = insert(root, 13);
    root = insert(root, 20);
    root = insert(root, 23);
    root = insert(root, 18);
    cout << "Preorder traversal of the "
            "constructed AVL tree is \n";
    preOrder(root);

    root = deleteNode(root, 20);


    cout << "\nPreorder traversal after"
        << " deletion of 10 \n";
    preOrder(root);

    return 0;
}

// This code is contributed by rathbhupendra

你可能感兴趣的:(数据结构)