📜  包含父节点指针的 AVL 树中的插入、搜索和删除

📅  最后修改于: 2022-05-13 01:57:20.269000             🧑  作者: Mango

包含父节点指针的 AVL 树中的插入、搜索和删除

AVL 树是一种自平衡二叉搜索树 (BST) ,其中所有节点的左右子树的高度差不能超过 1。 AVL树中的插入和删除在上一篇文章中已经讨论过了。在本文中,在结构中也有父指针的 AVL 树上讨论了插入、搜索和删除操作。

AVL树节点定义:

C++
struct AVLwithparent {
  
    // Pointer to the left and the
    // right subtree
    struct AVLwithparent* left;
    struct AVLwithparent* right;
  
    // Stores the data in the node
    int key;
  
    // Stores the parent pointer
    struct AVLwithparent* par;
  
    // Stores the height of the
    // current tree
    int height;
}


C++
// C++ program for the above approach
#include 
using namespace std;
  
// AVL tree node
struct AVLwithparent {
    struct AVLwithparent* left;
    struct AVLwithparent* right;
    int key;
    struct AVLwithparent* par;
    int height;
};
  
// Function to update the height of
// a node according to its children's
// node's heights
void Updateheight(
    struct AVLwithparent* root)
{
    if (root != NULL) {
  
        // Store the height of the
        // current node
        int val = 1;
  
        // Store the height of the left
        // and right substree
        if (root->left != NULL)
            val = root->left->height + 1;
  
        if (root->right != NULL)
            val = max(
                val, root->right->height + 1);
  
        // Update the height of the
        // current node
        root->height = val;
    }
}
  
// Function to handle Left Left Case
struct AVLwithparent* LLR(
    struct AVLwithparent* root)
{
    // Create a reference to the
    // left child
    struct AVLwithparent* tmpnode = root->left;
  
    // Update the left child of the
    // root to the right child of the
    // current left child of the root
    root->left = tmpnode->right;
  
    // Update parent pointer of the
    // left child of the root node
    if (tmpnode->right != NULL)
        tmpnode->right->par = root;
  
    // Update the right child of
    // tmpnode to root
    tmpnode->right = root;
  
    // Update parent pointer of
    // the tmpnode
    tmpnode->par = root->par;
  
    // Update the parent pointer
    // of the root
    root->par = tmpnode;
  
    // Update tmpnode as the left or the
    // right child of its parent pointer
    // according to its key value
    if (tmpnode->par != NULL
        && root->key < tmpnode->par->key) {
        tmpnode->par->left = tmpnode;
    }
    else {
        if (tmpnode->par != NULL)
            tmpnode->par->right = tmpnode;
    }
  
    // Make tmpnode as the new root
    root = tmpnode;
  
    // Update the heights
    Updateheight(root->left);
    Updateheight(root->right);
    Updateheight(root);
    Updateheight(root->par);
  
    // Return the root node
    return root;
}
  
// Function to handle Right Right Case
struct AVLwithparent* RRR(
    struct AVLwithparent* root)
{
    // Create a reference to the
    // right child
    struct AVLwithparent* tmpnode = root->right;
  
    // Update the right child of the
    // root as the left child of the
    // current right child of the root
    root->right = tmpnode->left;
  
    // Update parent pointer of the
    // right child of the root node
    if (tmpnode->left != NULL)
        tmpnode->left->par = root;
  
    // Update the left child of the
    // tmpnode to root
    tmpnode->left = root;
  
    // Update parent pointer of
    // the tmpnode
    tmpnode->par = root->par;
  
    // Update the parent pointer
    // of the root
    root->par = tmpnode;
  
    // Update tmpnode as the left or
    // the right child of its parent
    // pointer according to its key value
    if (tmpnode->par != NULL
        && root->key < tmpnode->par->key) {
        tmpnode->par->left = tmpnode;
    }
    else {
        if (tmpnode->par != NULL)
            tmpnode->par->right = tmpnode;
    }
  
    // Make tmpnode as the new root
    root = tmpnode;
  
    // Update the heights
    Updateheight(root->left);
    Updateheight(root->right);
    Updateheight(root);
    Updateheight(root->par);
  
    // Return the root node
    return root;
}
  
// Function to handle Left Right Case
struct AVLwithparent* LRR(
    struct AVLwithparent* root)
{
    root->left = RRR(root->left);
    return LLR(root);
}
  
// Function to handle right left case
struct AVLwithparent* RLR(
    struct AVLwithparent* root)
{
    root->right = LLR(root->right);
    return RRR(root);
}
  
// Function to insert a node in
// the AVL tree
struct AVLwithparent* Insert(
    struct AVLwithparent* root,
    struct AVLwithparent* parent,
    int key)
{
  
    if (root == NULL) {
  
        // Create and assign values
        // to a new node
        root = new struct AVLwithparent;
  
        // If the root is NULL
        if (root == NULL) {
            cout << "Error in memory"
                 << endl;
        }
  
        // Otherwise
        else {
            root->height = 1;
            root->left = NULL;
            root->right = NULL;
            root->par = parent;
            root->key = key;
        }
    }
  
    else if (root->key > key) {
  
        // Recur to the left subtree
        // to insert the node
        root->left = Insert(root->left,
                            root, key);
  
        // Store the heights of the
        // left and right subtree
        int firstheight = 0;
        int secondheight = 0;
  
        if (root->left != NULL)
            firstheight = root->left->height;
  
        if (root->right != NULL)
            secondheight = root->right->height;
  
        // Balance the tree if the
        // current node is not balanced
        if (abs(firstheight
                - secondheight)
            == 2) {
  
            if (root->left != NULL
                && key < root->left->key) {
  
                // Left Left Case
                root = LLR(root);
            }
            else {
  
                // Left Right Case
                root = LRR(root);
            }
        }
    }
  
    else if (root->key < key) {
  
        // Recur to the right subtree
        // to insert the node
        root->right = Insert(root->right,
                             root, key);
  
        // Store the heights of the
        // left and right subtree
        int firstheight = 0;
        int secondheight = 0;
  
        if (root->left != NULL)
            firstheight
                = root->left->height;
  
        if (root->right != NULL)
            secondheight = root->right->height;
  
        // Balance the tree if the
        // current node is not balanced
        if (abs(firstheight - secondheight) == 2) {
            if (root->right != NULL
                && key < root->right->key) {
  
                // Right Left Case
                root = RLR(root);
            }
            else {
  
                // Right Right Case
                root = RRR(root);
            }
        }
    }
  
    // Case when given key is already
    // in the tree
    else {
    }
  
    // Update the height of the
    // root node
    Updateheight(root);
  
    // Return the root node
    return root;
}
  
// Function to print the preorder
// traversal of the AVL tree
void printpreorder(
    struct AVLwithparent* root)
{
    // Print the node's value along
    // with its parent value
    cout << "Node: " << root->key
         << ", Parent Node: ";
  
    if (root->par != NULL)
        cout << root->par->key << endl;
    else
        cout << "NULL" << endl;
  
    // Recur to the left subtree
    if (root->left != NULL) {
        printpreorder(root->left);
    }
  
    // Recur to the right subtree
    if (root->right != NULL) {
        printpreorder(root->right);
    }
}
  
// Driver Code
int main()
{
    struct AVLwithparent* root;
    root = NULL;
  
    // Function Call to insert nodes
    root = Insert(root, NULL, 10);
    root = Insert(root, NULL, 20);
    root = Insert(root, NULL, 30);
    root = Insert(root, NULL, 40);
    root = Insert(root, NULL, 50);
    root = Insert(root, NULL, 25);
  
    // Function call to print the tree
    printpreorder(root);
}


C++
// C++ program for the above approach
#include 
using namespace std;
  
// AVL tree node
struct AVLwithparent {
    struct AVLwithparent* left;
    struct AVLwithparent* right;
    int key;
    struct AVLwithparent* par;
    int height;
};
  
// Function to update the height of
// a node according to its children's
// node's heights
void Updateheight(struct AVLwithparent* root)
{
    if (root != NULL) {
  
        // Store the height of the
        // current node
        int val = 1;
  
        // Store the height of the left
        // and the right substree
        if (root->left != NULL)
            val = root->left->height + 1;
  
        if (root->right != NULL)
            val = max(
                val, root->right->height + 1);
  
        // Update the height of the
        // current node
        root->height = val;
    }
}
  
// Function to handle Left Left Case
struct AVLwithparent* LLR(
    struct AVLwithparent* root)
{
    // Create a reference to the
    // left child
    struct AVLwithparent* tmpnode = root->left;
  
    // Update the left child of the
    // root to the right child of the
    // current left child of the root
    root->left = tmpnode->right;
  
    // Update parent pointer of the left
    // child of the root node
    if (tmpnode->right != NULL)
        tmpnode->right->par = root;
  
    // Update the right child of
    // tmpnode to root
    tmpnode->right = root;
  
    // Update parent pointer of tmpnode
    tmpnode->par = root->par;
  
    // Update the parent pointer of root
    root->par = tmpnode;
  
    // Update tmpnode as the left or
    // the right child of its parent
    // pointer according to its key value
    if (tmpnode->par != NULL
        && root->key < tmpnode->par->key) {
        tmpnode->par->left = tmpnode;
    }
    else {
        if (tmpnode->par != NULL)
            tmpnode->par->right = tmpnode;
    }
  
    // Make tmpnode as the new root
    root = tmpnode;
  
    // Update the heights
    Updateheight(root->left);
    Updateheight(root->right);
    Updateheight(root);
    Updateheight(root->par);
  
    // Return the root node
    return root;
}
  
// Function to handle Right Right Case
struct AVLwithparent* RRR(
    struct AVLwithparent* root)
{
    // Create a reference to the
    // right child
    struct AVLwithparent* tmpnode = root->right;
  
    // Update the right child of the
    // root as the left child of the
    // current right child of the root
    root->right = tmpnode->left;
  
    // Update parent pointer of the right
    // child of the root node
    if (tmpnode->left != NULL)
        tmpnode->left->par = root;
  
    // Update the left child of the
    // tmpnode to root
    tmpnode->left = root;
  
    // Update parent pointer of tmpnode
    tmpnode->par = root->par;
  
    // Update the parent pointer of root
    root->par = tmpnode;
  
    // Update tmpnode as the left or
    // the right child of its parent
    // pointer according to its key value
    if (tmpnode->par != NULL
        && root->key < tmpnode->par->key) {
        tmpnode->par->left = tmpnode;
    }
    else {
        if (tmpnode->par != NULL)
            tmpnode->par->right = tmpnode;
    }
  
    // Make tmpnode as the new root
    root = tmpnode;
  
    // Update the heights
    Updateheight(root->left);
    Updateheight(root->right);
    Updateheight(root);
    Updateheight(root->par);
  
    // Return the root node
    return root;
}
  
// Function to handle Left Right Case
struct AVLwithparent* LRR(
    struct AVLwithparent* root)
{
    root->left = RRR(root->left);
    return LLR(root);
}
  
// Function to handle right left case
struct AVLwithparent* RLR(
    struct AVLwithparent* root)
{
    root->right = LLR(root->right);
    return RRR(root);
}
  
// Function to insert a node in
// the AVL tree
struct AVLwithparent* Insert(
    struct AVLwithparent* root,
    struct AVLwithparent* parent,
    int key)
{
  
    if (root == NULL) {
  
        // Create and assign values
        // to a new node
        root = new struct AVLwithparent;
        if (root == NULL) {
            cout << "Error in memory" << endl;
        }
  
        // Otherwise
        else {
            root->height = 1;
            root->left = NULL;
            root->right = NULL;
            root->par = parent;
            root->key = key;
        }
    }
  
    else if (root->key > key) {
  
        // Recur to the left subtree
        // to insert the node
        root->left = Insert(root->left,
                            root, key);
  
        // Stores the heights of the
        // left and right subtree
        int firstheight = 0;
        int secondheight = 0;
  
        if (root->left != NULL)
            firstheight = root->left->height;
  
        if (root->right != NULL)
            secondheight = root->right->height;
  
        // Balance the tree if the
        // current node is not balanced
        if (abs(firstheight
                - secondheight)
            == 2) {
  
            if (root->left != NULL
                && key < root->left->key) {
  
                // Left Left Case
                root = LLR(root);
            }
            else {
  
                // Left Right Case
                root = LRR(root);
            }
        }
    }
  
    else if (root->key < key) {
  
        // Recur to the right subtree
        // to insert the node
        root->right = Insert(root->right, root, key);
  
        // Store the heights of the left
        // and right subtree
        int firstheight = 0;
        int secondheight = 0;
  
        if (root->left != NULL)
            firstheight = root->left->height;
  
        if (root->right != NULL)
            secondheight = root->right->height;
  
        // Balance the tree if the
        // current node is not balanced
        if (abs(firstheight
                - secondheight)
            == 2) {
            if (root->right != NULL
                && key < root->right->key) {
  
                // Right Left Case
                root = RLR(root);
            }
            else {
  
                // Right Right Case
                root = RRR(root);
            }
        }
    }
  
    // Case when given key is
    // already in tree
    else {
    }
  
    // Update the height of the
    // root node
    Updateheight(root);
  
    // Return the root node
    return root;
}
  
// Function to find a key in AVL tree
bool AVLsearch(
    struct AVLwithparent* root, int key)
{
    // If root is NULL
    if (root == NULL)
        return false;
  
    // If found, return true
    else if (root->key == key)
        return true;
  
    // Recur to the left subtree if
    // the current node's value is
    // greater than key
    else if (root->key > key) {
        bool val = AVLsearch(root->left, key);
        return val;
    }
  
    // Otherwise, recur to the
    // right subtree
    else {
        bool val = AVLsearch(root->right, key);
        return val;
    }
}
  
// Driver Code
int main()
{
    struct AVLwithparent* root;
    root = NULL;
  
    // Function call to insert the nodes
    root = Insert(root, NULL, 10);
    root = Insert(root, NULL, 20);
    root = Insert(root, NULL, 30);
    root = Insert(root, NULL, 40);
    root = Insert(root, NULL, 50);
    root = Insert(root, NULL, 25);
  
    // Function call to search for a node
    bool found = AVLsearch(root, 40);
    if (found)
        cout << "value found";
    else
        cout << "value not found";
  
    return 0;
}


C++
// C++ program for the above approach
#include 
using namespace std;
  
// AVL tree node
struct AVLwithparent {
    struct AVLwithparent* left;
    struct AVLwithparent* right;
    int key;
    struct AVLwithparent* par;
    int height;
};
  
// Function to print the preorder
// traversal of the AVL tree
void printpreorder(struct AVLwithparent* root)
{
    // Print the node's value along
    // with its parent value
    cout << "Node: " << root->key
         << ", Parent Node: ";
  
    if (root->par != NULL)
        cout << root->par->key << endl;
    else
        cout << "NULL" << endl;
  
    // Recur to the left subtree
    if (root->left != NULL) {
        printpreorder(root->left);
    }
  
    // Recur to the right subtree
    if (root->right != NULL) {
        printpreorder(root->right);
    }
}
  
// Function to update the height of
// a node according to its children's
// node's heights
void Updateheight(
    struct AVLwithparent* root)
{
    if (root != NULL) {
  
        // Store the height of the
        // current node
        int val = 1;
  
        // Store the height of the left
        // and right substree
        if (root->left != NULL)
            val = root->left->height + 1;
  
        if (root->right != NULL)
            val = max(
                val, root->right->height + 1);
  
        // Update the height of the
        // current node
        root->height = val;
    }
}
  
// Function to handle Left Left Case
struct AVLwithparent* LLR(
    struct AVLwithparent* root)
{
    // Create a reference to the
    // left child
    struct AVLwithparent* tmpnode = root->left;
  
    // Update the left child of the
    // root to the right child of the
    // current left child of the root
    root->left = tmpnode->right;
  
    // Update parent pointer of left
    // child of the root node
    if (tmpnode->right != NULL)
        tmpnode->right->par = root;
  
    // Update the right child of
    // tmpnode to root
    tmpnode->right = root;
  
    // Update parent pointer of tmpnode
    tmpnode->par = root->par;
  
    // Update the parent pointer of root
    root->par = tmpnode;
  
    // Update tmpnode as the left or
    // the right child of its parent
    // pointer according to its key value
    if (tmpnode->par != NULL
        && root->key < tmpnode->par->key) {
        tmpnode->par->left = tmpnode;
    }
    else {
        if (tmpnode->par != NULL)
            tmpnode->par->right = tmpnode;
    }
  
    // Make tmpnode as the new root
    root = tmpnode;
  
    // Update the heights
    Updateheight(root->left);
    Updateheight(root->right);
    Updateheight(root);
    Updateheight(root->par);
  
    // Return the root node
    return root;
}
  
// Function to handle Right Right Case
struct AVLwithparent* RRR(
    struct AVLwithparent* root)
{
    // Create a reference to the
    // right child
    struct AVLwithparent* tmpnode = root->right;
  
    // Update the right child of the
    // root as the left child of the
    // current right child of the root
    root->right = tmpnode->left;
  
    // Update parent pointer of the
    // right child of the root node
    if (tmpnode->left != NULL)
        tmpnode->left->par = root;
  
    // Update the left child of the
    // tmpnode to root
    tmpnode->left = root;
  
    // Update parent pointer of tmpnode
    tmpnode->par = root->par;
  
    // Update the parent pointer of root
    root->par = tmpnode;
  
    // Update tmpnode as the left or
    // the right child of its parent
    // pointer according to its key value
    if (tmpnode->par != NULL
        && root->key < tmpnode->par->key) {
        tmpnode->par->left = tmpnode;
    }
    else {
        if (tmpnode->par != NULL)
            tmpnode->par->right = tmpnode;
    }
  
    // Make tmpnode as the new root
    root = tmpnode;
  
    // Update the heights
    Updateheight(root->left);
    Updateheight(root->right);
    Updateheight(root);
    Updateheight(root->par);
  
    // Return the root node
    return root;
}
  
// Function to handle Left Right Case
struct AVLwithparent* LRR(
    struct AVLwithparent* root)
{
    root->left = RRR(root->left);
    return LLR(root);
}
  
// Function to handle right left case
struct AVLwithparent* RLR(
    struct AVLwithparent* root)
{
    root->right = LLR(root->right);
    return RRR(root);
}
  
// Function to balance the tree after
// deletion of a node
struct AVLwithparent* Balance(
    struct AVLwithparent* root)
{
    // Store the current height of
    // the left and right subtree
    int firstheight = 0;
    int secondheight = 0;
  
    if (root->left != NULL)
        firstheight = root->left->height;
  
    if (root->right != NULL)
        secondheight = root->right->height;
  
    // If current node is not balanced
    if (abs(firstheight - secondheight) == 2) {
        if (firstheight < secondheight) {
  
            // Store the height of the
            // left and right subtree
            // of the current node's
            // right subtree
            int rightheight1 = 0;
            int rightheight2 = 0;
            if (root->right->right != NULL)
                rightheight2 = root->right->right->height;
  
            if (root->right->left != NULL)
                rightheight1 = root->right->left->height;
  
            if (rightheight1 > rightheight2) {
  
                // Right Left Case
                root = RLR(root);
            }
            else {
  
                // Right Right Case
                root = RRR(root);
            }
        }
        else {
  
            // Store the height of the
            // left and right subtree
            // of the current node's
            // left subtree
            int leftheight1 = 0;
            int leftheight2 = 0;
            if (root->left->right != NULL)
                leftheight2 = root->left->right->height;
  
            if (root->left->left != NULL)
                leftheight1 = root->left->left->height;
  
            if (leftheight1 > leftheight2) {
  
                // Left Left Case
                root = LLR(root);
            }
            else {
  
                // Left Right Case
                root = LRR(root);
            }
        }
    }
  
    // Return the root node
    return root;
}
  
// Function to insert a node in
// the AVL tree
struct AVLwithparent* Insert(
    struct AVLwithparent* root,
    struct AVLwithparent* parent,
    int key)
{
  
    if (root == NULL) {
  
        // Create and assign values
        // to a new node
        root = new struct AVLwithparent;
        if (root == NULL)
            cout << "Error in memory" << endl;
        else {
            root->height = 1;
            root->left = NULL;
            root->right = NULL;
            root->par = parent;
            root->key = key;
        }
    }
  
    else if (root->key > key) {
  
        // Recur to the left subtree
        // to insert the node
        root->left = Insert(root->left,
                            root, key);
  
        // Store the heights of the
        // left and right subtree
        int firstheight = 0;
        int secondheight = 0;
  
        if (root->left != NULL)
            firstheight = root->left->height;
  
        if (root->right != NULL)
            secondheight = root->right->height;
  
        // Balance the tree if the
        // current node is not balanced
        if (abs(firstheight
                - secondheight)
            == 2) {
  
            if (root->left != NULL
                && key < root->left->key) {
  
                // Left Left Case
                root = LLR(root);
            }
            else {
  
                // Left Right Case
                root = LRR(root);
            }
        }
    }
  
    else if (root->key < key) {
  
        // Recur to the right subtree
        // to insert the node
        root->right = Insert(root->right,
                             root, key);
  
        // Store the heights of the left
        // and right subtree
        int firstheight = 0;
        int secondheight = 0;
  
        if (root->left != NULL)
            firstheight = root->left->height;
  
        if (root->right != NULL)
            secondheight = root->right->height;
  
        // Balance the tree if the
        // current node is not balanced
        if (abs(firstheight - secondheight) == 2) {
            if (root->right != NULL
                && key < root->right->key) {
  
                // Right Left Case
                root = RLR(root);
            }
            else {
  
                // Right Right Case
                root = RRR(root);
            }
        }
    }
  
    // Case when given key is
    // already in tree
    else {
    }
  
    // Update the height of the
    // root node
    Updateheight(root);
  
    // Return the root node
    return root;
}
  
// Function to delete a node from
// the AVL tree
struct AVLwithparent* Delete(
    struct AVLwithparent* root,
    int key)
{
    if (root != NULL) {
  
        // If the node is found
        if (root->key == key) {
  
            // Replace root with its
            // left child
            if (root->right == NULL
                && root->left != NULL) {
                if (root->par != NULL) {
                    if (root->par->key
                        < root->key)
                        root->par->right = root->left;
                    else
                        root->par->left = root->left;
  
                    // Update the height
                    // of root's parent
                    Updateheight(root->par);
                }
  
                root->left->par = root->par;
  
                // Balance the node
                // after deletion
                root->left = Balance(
                    root->left);
  
                return root->left;
            }
  
            // Replace root with its
            // right child
            else if (root->left == NULL
                     && root->right != NULL) {
                if (root->par != NULL) {
                    if (root->par->key
                        < root->key)
                        root->par->right = root->right;
                    else
                        root->par->left = root->right;
  
                    // Update the height
                    // of the root's parent
                    Updateheight(root->par);
                }
  
                root->right->par = root->par;
  
                // Balance the node after
                // deletion
                root->right = Balance(root->right);
                return root->right;
            }
  
            // Remove the references of
            // the current node
            else if (root->left == NULL
                     && root->right == NULL) {
                if (root->par->key < root->key) {
                    root->par->right = NULL;
                }
                else {
                    root->par->left = NULL;
                }
  
                if (root->par != NULL)
                    Updateheight(root->par);
  
                root = NULL;
                return NULL;
            }
  
            // Otherwise, replace the
            // current node with its
            // successor and then
            // recursively call Delete()
            else {
                struct AVLwithparent* tmpnode = root;
                tmpnode = tmpnode->right;
                while (tmpnode->left != NULL) {
                    tmpnode = tmpnode->left;
                }
  
                int val = tmpnode->key;
  
                root->right
                    = Delete(root->right, tmpnode->key);
  
                root->key = val;
  
                // Balance the node
                // after deletion
                root = Balance(root);
            }
        }
  
        // Recur to the right subtree to
        // delete the current node
        else if (root->key < key) {
            root->right = Delete(root->right, key);
  
            root = Balance(root);
        }
  
        // Recur into the right subtree
        // to delete the current node
        else if (root->key > key) {
            root->left = Delete(root->left, key);
  
            root = Balance(root);
        }
  
        // Update height of the root
        if (root != NULL) {
            Updateheight(root);
        }
    }
  
    // Handle the case when the key to be
    // deleted could not be found
    else {
        cout << "Key to be deleted "
             << "could not be found\n";
    }
  
    // Return the root node
    return root;
}
  
// Driver Code
int main()
{
    struct AVLwithparent* root;
    root = NULL;
  
    // Function call to insert the nodes
    root = Insert(root, NULL, 9);
    root = Insert(root, NULL, 5);
    root = Insert(root, NULL, 10);
    root = Insert(root, NULL, 0);
    root = Insert(root, NULL, 6);
  
    // Print the tree before deleting node
    cout << "Before deletion:\n";
    printpreorder(root);
  
    // Function Call to delete node 10
    root = Delete(root, 10);
  
    // Print the tree after deleting node
    cout << "After deletion:\n";
    printpreorder(root);
}


输出:
Node: 30, Parent Node: NULL
Node: 20, Parent Node: 30
Node: 10, Parent Node: 20
Node: 25, Parent Node: 20
Node: 40, Parent Node: 30
Node: 50, Parent Node: 40

节点的表示

下面是包含父指针的 AVL 树的示例:

插入操作:插入过程类似于没有父指针的普通 AVL 树,但在这种情况下,每次插入和旋转都需要相应地更新父指针。按照以下步骤执行插入操作:

  • 对要放置在正确位置的节点执行标准 BST 插入。
  • 将遇到的每个节点的高度增加 1,同时找到要插入的节点的正确位置。
  • 分别更新插入节点及其父节点的父子指针。
  • 从插入的节点开始直到根节点检查该路径上的每个节点是否满足 AVL 条件。
  • 如果w是不满足 AVL 条件的节点,那么我们有 4 种情况:
    • Left Left Case:(如果w的左孩子的左子树有插入的节点)
    • Left Right Case:(如果w的左孩子的右子树有插入的节点)
    • Right Left Case:(如果w的右孩子的左子树有插入的节点)
    • Right Right Case:(如果w的右孩子的右子树有插入的节点)

下面是上述方法的实现:

C++

// C++ program for the above approach
#include 
using namespace std;
  
// AVL tree node
struct AVLwithparent {
    struct AVLwithparent* left;
    struct AVLwithparent* right;
    int key;
    struct AVLwithparent* par;
    int height;
};
  
// Function to update the height of
// a node according to its children's
// node's heights
void Updateheight(
    struct AVLwithparent* root)
{
    if (root != NULL) {
  
        // Store the height of the
        // current node
        int val = 1;
  
        // Store the height of the left
        // and right substree
        if (root->left != NULL)
            val = root->left->height + 1;
  
        if (root->right != NULL)
            val = max(
                val, root->right->height + 1);
  
        // Update the height of the
        // current node
        root->height = val;
    }
}
  
// Function to handle Left Left Case
struct AVLwithparent* LLR(
    struct AVLwithparent* root)
{
    // Create a reference to the
    // left child
    struct AVLwithparent* tmpnode = root->left;
  
    // Update the left child of the
    // root to the right child of the
    // current left child of the root
    root->left = tmpnode->right;
  
    // Update parent pointer of the
    // left child of the root node
    if (tmpnode->right != NULL)
        tmpnode->right->par = root;
  
    // Update the right child of
    // tmpnode to root
    tmpnode->right = root;
  
    // Update parent pointer of
    // the tmpnode
    tmpnode->par = root->par;
  
    // Update the parent pointer
    // of the root
    root->par = tmpnode;
  
    // Update tmpnode as the left or the
    // right child of its parent pointer
    // according to its key value
    if (tmpnode->par != NULL
        && root->key < tmpnode->par->key) {
        tmpnode->par->left = tmpnode;
    }
    else {
        if (tmpnode->par != NULL)
            tmpnode->par->right = tmpnode;
    }
  
    // Make tmpnode as the new root
    root = tmpnode;
  
    // Update the heights
    Updateheight(root->left);
    Updateheight(root->right);
    Updateheight(root);
    Updateheight(root->par);
  
    // Return the root node
    return root;
}
  
// Function to handle Right Right Case
struct AVLwithparent* RRR(
    struct AVLwithparent* root)
{
    // Create a reference to the
    // right child
    struct AVLwithparent* tmpnode = root->right;
  
    // Update the right child of the
    // root as the left child of the
    // current right child of the root
    root->right = tmpnode->left;
  
    // Update parent pointer of the
    // right child of the root node
    if (tmpnode->left != NULL)
        tmpnode->left->par = root;
  
    // Update the left child of the
    // tmpnode to root
    tmpnode->left = root;
  
    // Update parent pointer of
    // the tmpnode
    tmpnode->par = root->par;
  
    // Update the parent pointer
    // of the root
    root->par = tmpnode;
  
    // Update tmpnode as the left or
    // the right child of its parent
    // pointer according to its key value
    if (tmpnode->par != NULL
        && root->key < tmpnode->par->key) {
        tmpnode->par->left = tmpnode;
    }
    else {
        if (tmpnode->par != NULL)
            tmpnode->par->right = tmpnode;
    }
  
    // Make tmpnode as the new root
    root = tmpnode;
  
    // Update the heights
    Updateheight(root->left);
    Updateheight(root->right);
    Updateheight(root);
    Updateheight(root->par);
  
    // Return the root node
    return root;
}
  
// Function to handle Left Right Case
struct AVLwithparent* LRR(
    struct AVLwithparent* root)
{
    root->left = RRR(root->left);
    return LLR(root);
}
  
// Function to handle right left case
struct AVLwithparent* RLR(
    struct AVLwithparent* root)
{
    root->right = LLR(root->right);
    return RRR(root);
}
  
// Function to insert a node in
// the AVL tree
struct AVLwithparent* Insert(
    struct AVLwithparent* root,
    struct AVLwithparent* parent,
    int key)
{
  
    if (root == NULL) {
  
        // Create and assign values
        // to a new node
        root = new struct AVLwithparent;
  
        // If the root is NULL
        if (root == NULL) {
            cout << "Error in memory"
                 << endl;
        }
  
        // Otherwise
        else {
            root->height = 1;
            root->left = NULL;
            root->right = NULL;
            root->par = parent;
            root->key = key;
        }
    }
  
    else if (root->key > key) {
  
        // Recur to the left subtree
        // to insert the node
        root->left = Insert(root->left,
                            root, key);
  
        // Store the heights of the
        // left and right subtree
        int firstheight = 0;
        int secondheight = 0;
  
        if (root->left != NULL)
            firstheight = root->left->height;
  
        if (root->right != NULL)
            secondheight = root->right->height;
  
        // Balance the tree if the
        // current node is not balanced
        if (abs(firstheight
                - secondheight)
            == 2) {
  
            if (root->left != NULL
                && key < root->left->key) {
  
                // Left Left Case
                root = LLR(root);
            }
            else {
  
                // Left Right Case
                root = LRR(root);
            }
        }
    }
  
    else if (root->key < key) {
  
        // Recur to the right subtree
        // to insert the node
        root->right = Insert(root->right,
                             root, key);
  
        // Store the heights of the
        // left and right subtree
        int firstheight = 0;
        int secondheight = 0;
  
        if (root->left != NULL)
            firstheight
                = root->left->height;
  
        if (root->right != NULL)
            secondheight = root->right->height;
  
        // Balance the tree if the
        // current node is not balanced
        if (abs(firstheight - secondheight) == 2) {
            if (root->right != NULL
                && key < root->right->key) {
  
                // Right Left Case
                root = RLR(root);
            }
            else {
  
                // Right Right Case
                root = RRR(root);
            }
        }
    }
  
    // Case when given key is already
    // in the tree
    else {
    }
  
    // Update the height of the
    // root node
    Updateheight(root);
  
    // Return the root node
    return root;
}
  
// Function to print the preorder
// traversal of the AVL tree
void printpreorder(
    struct AVLwithparent* root)
{
    // Print the node's value along
    // with its parent value
    cout << "Node: " << root->key
         << ", Parent Node: ";
  
    if (root->par != NULL)
        cout << root->par->key << endl;
    else
        cout << "NULL" << endl;
  
    // Recur to the left subtree
    if (root->left != NULL) {
        printpreorder(root->left);
    }
  
    // Recur to the right subtree
    if (root->right != NULL) {
        printpreorder(root->right);
    }
}
  
// Driver Code
int main()
{
    struct AVLwithparent* root;
    root = NULL;
  
    // Function Call to insert nodes
    root = Insert(root, NULL, 10);
    root = Insert(root, NULL, 20);
    root = Insert(root, NULL, 30);
    root = Insert(root, NULL, 40);
    root = Insert(root, NULL, 50);
    root = Insert(root, NULL, 25);
  
    // Function call to print the tree
    printpreorder(root);
}
输出:
Node: 30, Parent Node: NULL
Node: 20, Parent Node: 30
Node: 10, Parent Node: 20
Node: 25, Parent Node: 20
Node: 40, Parent Node: 30
Node: 50, Parent Node: 40

时间复杂度: O(log N),其中 N 是树的节点数
辅助空间: O(1)

搜索操作:具有父指针的 AVL 树中的搜索操作类似于普通二叉搜索树中的搜索操作。按照以下步骤进行搜索操作:

  • 从根节点开始。
  • 如果根节点为NULL ,则返回false
  • 检查当前节点的值是否等于要搜索的节点的值。如果是,则返回true
  • 如果当前节点的值小于搜索到的键,则递归到右子树。
  • 如果当前节点的值大于搜索到的键,则递归到左子树。

下面是上述方法的实现:

C++

// C++ program for the above approach
#include 
using namespace std;
  
// AVL tree node
struct AVLwithparent {
    struct AVLwithparent* left;
    struct AVLwithparent* right;
    int key;
    struct AVLwithparent* par;
    int height;
};
  
// Function to update the height of
// a node according to its children's
// node's heights
void Updateheight(struct AVLwithparent* root)
{
    if (root != NULL) {
  
        // Store the height of the
        // current node
        int val = 1;
  
        // Store the height of the left
        // and the right substree
        if (root->left != NULL)
            val = root->left->height + 1;
  
        if (root->right != NULL)
            val = max(
                val, root->right->height + 1);
  
        // Update the height of the
        // current node
        root->height = val;
    }
}
  
// Function to handle Left Left Case
struct AVLwithparent* LLR(
    struct AVLwithparent* root)
{
    // Create a reference to the
    // left child
    struct AVLwithparent* tmpnode = root->left;
  
    // Update the left child of the
    // root to the right child of the
    // current left child of the root
    root->left = tmpnode->right;
  
    // Update parent pointer of the left
    // child of the root node
    if (tmpnode->right != NULL)
        tmpnode->right->par = root;
  
    // Update the right child of
    // tmpnode to root
    tmpnode->right = root;
  
    // Update parent pointer of tmpnode
    tmpnode->par = root->par;
  
    // Update the parent pointer of root
    root->par = tmpnode;
  
    // Update tmpnode as the left or
    // the right child of its parent
    // pointer according to its key value
    if (tmpnode->par != NULL
        && root->key < tmpnode->par->key) {
        tmpnode->par->left = tmpnode;
    }
    else {
        if (tmpnode->par != NULL)
            tmpnode->par->right = tmpnode;
    }
  
    // Make tmpnode as the new root
    root = tmpnode;
  
    // Update the heights
    Updateheight(root->left);
    Updateheight(root->right);
    Updateheight(root);
    Updateheight(root->par);
  
    // Return the root node
    return root;
}
  
// Function to handle Right Right Case
struct AVLwithparent* RRR(
    struct AVLwithparent* root)
{
    // Create a reference to the
    // right child
    struct AVLwithparent* tmpnode = root->right;
  
    // Update the right child of the
    // root as the left child of the
    // current right child of the root
    root->right = tmpnode->left;
  
    // Update parent pointer of the right
    // child of the root node
    if (tmpnode->left != NULL)
        tmpnode->left->par = root;
  
    // Update the left child of the
    // tmpnode to root
    tmpnode->left = root;
  
    // Update parent pointer of tmpnode
    tmpnode->par = root->par;
  
    // Update the parent pointer of root
    root->par = tmpnode;
  
    // Update tmpnode as the left or
    // the right child of its parent
    // pointer according to its key value
    if (tmpnode->par != NULL
        && root->key < tmpnode->par->key) {
        tmpnode->par->left = tmpnode;
    }
    else {
        if (tmpnode->par != NULL)
            tmpnode->par->right = tmpnode;
    }
  
    // Make tmpnode as the new root
    root = tmpnode;
  
    // Update the heights
    Updateheight(root->left);
    Updateheight(root->right);
    Updateheight(root);
    Updateheight(root->par);
  
    // Return the root node
    return root;
}
  
// Function to handle Left Right Case
struct AVLwithparent* LRR(
    struct AVLwithparent* root)
{
    root->left = RRR(root->left);
    return LLR(root);
}
  
// Function to handle right left case
struct AVLwithparent* RLR(
    struct AVLwithparent* root)
{
    root->right = LLR(root->right);
    return RRR(root);
}
  
// Function to insert a node in
// the AVL tree
struct AVLwithparent* Insert(
    struct AVLwithparent* root,
    struct AVLwithparent* parent,
    int key)
{
  
    if (root == NULL) {
  
        // Create and assign values
        // to a new node
        root = new struct AVLwithparent;
        if (root == NULL) {
            cout << "Error in memory" << endl;
        }
  
        // Otherwise
        else {
            root->height = 1;
            root->left = NULL;
            root->right = NULL;
            root->par = parent;
            root->key = key;
        }
    }
  
    else if (root->key > key) {
  
        // Recur to the left subtree
        // to insert the node
        root->left = Insert(root->left,
                            root, key);
  
        // Stores the heights of the
        // left and right subtree
        int firstheight = 0;
        int secondheight = 0;
  
        if (root->left != NULL)
            firstheight = root->left->height;
  
        if (root->right != NULL)
            secondheight = root->right->height;
  
        // Balance the tree if the
        // current node is not balanced
        if (abs(firstheight
                - secondheight)
            == 2) {
  
            if (root->left != NULL
                && key < root->left->key) {
  
                // Left Left Case
                root = LLR(root);
            }
            else {
  
                // Left Right Case
                root = LRR(root);
            }
        }
    }
  
    else if (root->key < key) {
  
        // Recur to the right subtree
        // to insert the node
        root->right = Insert(root->right, root, key);
  
        // Store the heights of the left
        // and right subtree
        int firstheight = 0;
        int secondheight = 0;
  
        if (root->left != NULL)
            firstheight = root->left->height;
  
        if (root->right != NULL)
            secondheight = root->right->height;
  
        // Balance the tree if the
        // current node is not balanced
        if (abs(firstheight
                - secondheight)
            == 2) {
            if (root->right != NULL
                && key < root->right->key) {
  
                // Right Left Case
                root = RLR(root);
            }
            else {
  
                // Right Right Case
                root = RRR(root);
            }
        }
    }
  
    // Case when given key is
    // already in tree
    else {
    }
  
    // Update the height of the
    // root node
    Updateheight(root);
  
    // Return the root node
    return root;
}
  
// Function to find a key in AVL tree
bool AVLsearch(
    struct AVLwithparent* root, int key)
{
    // If root is NULL
    if (root == NULL)
        return false;
  
    // If found, return true
    else if (root->key == key)
        return true;
  
    // Recur to the left subtree if
    // the current node's value is
    // greater than key
    else if (root->key > key) {
        bool val = AVLsearch(root->left, key);
        return val;
    }
  
    // Otherwise, recur to the
    // right subtree
    else {
        bool val = AVLsearch(root->right, key);
        return val;
    }
}
  
// Driver Code
int main()
{
    struct AVLwithparent* root;
    root = NULL;
  
    // Function call to insert the nodes
    root = Insert(root, NULL, 10);
    root = Insert(root, NULL, 20);
    root = Insert(root, NULL, 30);
    root = Insert(root, NULL, 40);
    root = Insert(root, NULL, 50);
    root = Insert(root, NULL, 25);
  
    // Function call to search for a node
    bool found = AVLsearch(root, 40);
    if (found)
        cout << "value found";
    else
        cout << "value not found";
  
    return 0;
}
输出:
value found

时间复杂度: O(log N),其中 N 是树的节点数
辅助空间: O(1)

删除操作:删除过程类似于没有父指针的普通AVL树,但在这种情况下,每次删除和旋转都需要相应地更新对父指针的引用。请按照以下步骤执行删除操作:

  • 像在正常的 BST 中一样执行删除过程。
  • 从已删除的节点,向根移动。
  • 在路径上的每个节点处,更新节点的高度。
  • 检查每个节点的 AVL 条件。假设有 3 个节点: w, x, y ,其中w是当前节点, xw的高度较大的子树的根, yx的高度较大的子树的根。
  • 如果节点w不平衡,则存在以下 4 种情况之一:
    • Left Left Case( xw的左孩子, yx的左孩子)
    • Left Right Case ( xw的左孩子, yx的右孩子)
    • Right Left Case( xw的右孩子, yx的左孩子)
    • Right Right Case ( xw的右孩子, yx的右孩子)

下面是上述方法的实现:

C++

// C++ program for the above approach
#include 
using namespace std;
  
// AVL tree node
struct AVLwithparent {
    struct AVLwithparent* left;
    struct AVLwithparent* right;
    int key;
    struct AVLwithparent* par;
    int height;
};
  
// Function to print the preorder
// traversal of the AVL tree
void printpreorder(struct AVLwithparent* root)
{
    // Print the node's value along
    // with its parent value
    cout << "Node: " << root->key
         << ", Parent Node: ";
  
    if (root->par != NULL)
        cout << root->par->key << endl;
    else
        cout << "NULL" << endl;
  
    // Recur to the left subtree
    if (root->left != NULL) {
        printpreorder(root->left);
    }
  
    // Recur to the right subtree
    if (root->right != NULL) {
        printpreorder(root->right);
    }
}
  
// Function to update the height of
// a node according to its children's
// node's heights
void Updateheight(
    struct AVLwithparent* root)
{
    if (root != NULL) {
  
        // Store the height of the
        // current node
        int val = 1;
  
        // Store the height of the left
        // and right substree
        if (root->left != NULL)
            val = root->left->height + 1;
  
        if (root->right != NULL)
            val = max(
                val, root->right->height + 1);
  
        // Update the height of the
        // current node
        root->height = val;
    }
}
  
// Function to handle Left Left Case
struct AVLwithparent* LLR(
    struct AVLwithparent* root)
{
    // Create a reference to the
    // left child
    struct AVLwithparent* tmpnode = root->left;
  
    // Update the left child of the
    // root to the right child of the
    // current left child of the root
    root->left = tmpnode->right;
  
    // Update parent pointer of left
    // child of the root node
    if (tmpnode->right != NULL)
        tmpnode->right->par = root;
  
    // Update the right child of
    // tmpnode to root
    tmpnode->right = root;
  
    // Update parent pointer of tmpnode
    tmpnode->par = root->par;
  
    // Update the parent pointer of root
    root->par = tmpnode;
  
    // Update tmpnode as the left or
    // the right child of its parent
    // pointer according to its key value
    if (tmpnode->par != NULL
        && root->key < tmpnode->par->key) {
        tmpnode->par->left = tmpnode;
    }
    else {
        if (tmpnode->par != NULL)
            tmpnode->par->right = tmpnode;
    }
  
    // Make tmpnode as the new root
    root = tmpnode;
  
    // Update the heights
    Updateheight(root->left);
    Updateheight(root->right);
    Updateheight(root);
    Updateheight(root->par);
  
    // Return the root node
    return root;
}
  
// Function to handle Right Right Case
struct AVLwithparent* RRR(
    struct AVLwithparent* root)
{
    // Create a reference to the
    // right child
    struct AVLwithparent* tmpnode = root->right;
  
    // Update the right child of the
    // root as the left child of the
    // current right child of the root
    root->right = tmpnode->left;
  
    // Update parent pointer of the
    // right child of the root node
    if (tmpnode->left != NULL)
        tmpnode->left->par = root;
  
    // Update the left child of the
    // tmpnode to root
    tmpnode->left = root;
  
    // Update parent pointer of tmpnode
    tmpnode->par = root->par;
  
    // Update the parent pointer of root
    root->par = tmpnode;
  
    // Update tmpnode as the left or
    // the right child of its parent
    // pointer according to its key value
    if (tmpnode->par != NULL
        && root->key < tmpnode->par->key) {
        tmpnode->par->left = tmpnode;
    }
    else {
        if (tmpnode->par != NULL)
            tmpnode->par->right = tmpnode;
    }
  
    // Make tmpnode as the new root
    root = tmpnode;
  
    // Update the heights
    Updateheight(root->left);
    Updateheight(root->right);
    Updateheight(root);
    Updateheight(root->par);
  
    // Return the root node
    return root;
}
  
// Function to handle Left Right Case
struct AVLwithparent* LRR(
    struct AVLwithparent* root)
{
    root->left = RRR(root->left);
    return LLR(root);
}
  
// Function to handle right left case
struct AVLwithparent* RLR(
    struct AVLwithparent* root)
{
    root->right = LLR(root->right);
    return RRR(root);
}
  
// Function to balance the tree after
// deletion of a node
struct AVLwithparent* Balance(
    struct AVLwithparent* root)
{
    // Store the current height of
    // the left and right subtree
    int firstheight = 0;
    int secondheight = 0;
  
    if (root->left != NULL)
        firstheight = root->left->height;
  
    if (root->right != NULL)
        secondheight = root->right->height;
  
    // If current node is not balanced
    if (abs(firstheight - secondheight) == 2) {
        if (firstheight < secondheight) {
  
            // Store the height of the
            // left and right subtree
            // of the current node's
            // right subtree
            int rightheight1 = 0;
            int rightheight2 = 0;
            if (root->right->right != NULL)
                rightheight2 = root->right->right->height;
  
            if (root->right->left != NULL)
                rightheight1 = root->right->left->height;
  
            if (rightheight1 > rightheight2) {
  
                // Right Left Case
                root = RLR(root);
            }
            else {
  
                // Right Right Case
                root = RRR(root);
            }
        }
        else {
  
            // Store the height of the
            // left and right subtree
            // of the current node's
            // left subtree
            int leftheight1 = 0;
            int leftheight2 = 0;
            if (root->left->right != NULL)
                leftheight2 = root->left->right->height;
  
            if (root->left->left != NULL)
                leftheight1 = root->left->left->height;
  
            if (leftheight1 > leftheight2) {
  
                // Left Left Case
                root = LLR(root);
            }
            else {
  
                // Left Right Case
                root = LRR(root);
            }
        }
    }
  
    // Return the root node
    return root;
}
  
// Function to insert a node in
// the AVL tree
struct AVLwithparent* Insert(
    struct AVLwithparent* root,
    struct AVLwithparent* parent,
    int key)
{
  
    if (root == NULL) {
  
        // Create and assign values
        // to a new node
        root = new struct AVLwithparent;
        if (root == NULL)
            cout << "Error in memory" << endl;
        else {
            root->height = 1;
            root->left = NULL;
            root->right = NULL;
            root->par = parent;
            root->key = key;
        }
    }
  
    else if (root->key > key) {
  
        // Recur to the left subtree
        // to insert the node
        root->left = Insert(root->left,
                            root, key);
  
        // Store the heights of the
        // left and right subtree
        int firstheight = 0;
        int secondheight = 0;
  
        if (root->left != NULL)
            firstheight = root->left->height;
  
        if (root->right != NULL)
            secondheight = root->right->height;
  
        // Balance the tree if the
        // current node is not balanced
        if (abs(firstheight
                - secondheight)
            == 2) {
  
            if (root->left != NULL
                && key < root->left->key) {
  
                // Left Left Case
                root = LLR(root);
            }
            else {
  
                // Left Right Case
                root = LRR(root);
            }
        }
    }
  
    else if (root->key < key) {
  
        // Recur to the right subtree
        // to insert the node
        root->right = Insert(root->right,
                             root, key);
  
        // Store the heights of the left
        // and right subtree
        int firstheight = 0;
        int secondheight = 0;
  
        if (root->left != NULL)
            firstheight = root->left->height;
  
        if (root->right != NULL)
            secondheight = root->right->height;
  
        // Balance the tree if the
        // current node is not balanced
        if (abs(firstheight - secondheight) == 2) {
            if (root->right != NULL
                && key < root->right->key) {
  
                // Right Left Case
                root = RLR(root);
            }
            else {
  
                // Right Right Case
                root = RRR(root);
            }
        }
    }
  
    // Case when given key is
    // already in tree
    else {
    }
  
    // Update the height of the
    // root node
    Updateheight(root);
  
    // Return the root node
    return root;
}
  
// Function to delete a node from
// the AVL tree
struct AVLwithparent* Delete(
    struct AVLwithparent* root,
    int key)
{
    if (root != NULL) {
  
        // If the node is found
        if (root->key == key) {
  
            // Replace root with its
            // left child
            if (root->right == NULL
                && root->left != NULL) {
                if (root->par != NULL) {
                    if (root->par->key
                        < root->key)
                        root->par->right = root->left;
                    else
                        root->par->left = root->left;
  
                    // Update the height
                    // of root's parent
                    Updateheight(root->par);
                }
  
                root->left->par = root->par;
  
                // Balance the node
                // after deletion
                root->left = Balance(
                    root->left);
  
                return root->left;
            }
  
            // Replace root with its
            // right child
            else if (root->left == NULL
                     && root->right != NULL) {
                if (root->par != NULL) {
                    if (root->par->key
                        < root->key)
                        root->par->right = root->right;
                    else
                        root->par->left = root->right;
  
                    // Update the height
                    // of the root's parent
                    Updateheight(root->par);
                }
  
                root->right->par = root->par;
  
                // Balance the node after
                // deletion
                root->right = Balance(root->right);
                return root->right;
            }
  
            // Remove the references of
            // the current node
            else if (root->left == NULL
                     && root->right == NULL) {
                if (root->par->key < root->key) {
                    root->par->right = NULL;
                }
                else {
                    root->par->left = NULL;
                }
  
                if (root->par != NULL)
                    Updateheight(root->par);
  
                root = NULL;
                return NULL;
            }
  
            // Otherwise, replace the
            // current node with its
            // successor and then
            // recursively call Delete()
            else {
                struct AVLwithparent* tmpnode = root;
                tmpnode = tmpnode->right;
                while (tmpnode->left != NULL) {
                    tmpnode = tmpnode->left;
                }
  
                int val = tmpnode->key;
  
                root->right
                    = Delete(root->right, tmpnode->key);
  
                root->key = val;
  
                // Balance the node
                // after deletion
                root = Balance(root);
            }
        }
  
        // Recur to the right subtree to
        // delete the current node
        else if (root->key < key) {
            root->right = Delete(root->right, key);
  
            root = Balance(root);
        }
  
        // Recur into the right subtree
        // to delete the current node
        else if (root->key > key) {
            root->left = Delete(root->left, key);
  
            root = Balance(root);
        }
  
        // Update height of the root
        if (root != NULL) {
            Updateheight(root);
        }
    }
  
    // Handle the case when the key to be
    // deleted could not be found
    else {
        cout << "Key to be deleted "
             << "could not be found\n";
    }
  
    // Return the root node
    return root;
}
  
// Driver Code
int main()
{
    struct AVLwithparent* root;
    root = NULL;
  
    // Function call to insert the nodes
    root = Insert(root, NULL, 9);
    root = Insert(root, NULL, 5);
    root = Insert(root, NULL, 10);
    root = Insert(root, NULL, 0);
    root = Insert(root, NULL, 6);
  
    // Print the tree before deleting node
    cout << "Before deletion:\n";
    printpreorder(root);
  
    // Function Call to delete node 10
    root = Delete(root, 10);
  
    // Print the tree after deleting node
    cout << "After deletion:\n";
    printpreorder(root);
}
输出:
Before deletion:
Node: 9, Parent Node: NULL
Node: 5, Parent Node: 9
Node: 0, Parent Node: 5
Node: 6, Parent Node: 5
Node: 10, Parent Node: 9
After deletion:
Node: 6, Parent Node: NULL
Node: 5, Parent Node: 6
Node: 0, Parent Node: 5
Node: 9, Parent Node: 6

时间复杂度: O(log N),其中 N 是树的节点数
辅助空间: O(1)