📜  挖矿|设置2(搜索,插入和删除的实现)

📅  最后修改于: 2021-04-17 12:14:05             🧑  作者: Mango

强烈建议将第1组作为此帖子的先决条件。

Treap(随机二叉搜索树)

在这篇文章中,讨论了搜索,插入和删除的实现。

搜索:
与标准BST搜索相同。不考虑优先搜索。

// C function to search a given key in a given BST
TreapNode* search(TreapNode* root, int key)
{
    // Base Cases: root is null or key is present at root
    if (root == NULL || root->key == key)
       return root;
      
    // Key is greater than root's key
    if (root->key < key)
       return search(root->right, key);
   
    // Key is smaller than root's key
    return search(root->left, key);
}


1)创建键等于x并且值等于随机值的新节点。

2)执行标准的BST插入。

3)新插入的节点获得随机优先级,因此可能会违反Max-Heap属性。

在插入期间,我们以递归方式遍历插入节点的所有祖先。
a)如果在左子树中插入了新节点,并且左子树的根具有更高的优先级,请执行右旋转。

b)如果在右子树中插入了新节点,并且右子树的根具有更高的优先级,请执行左旋转。

/* Recursive implementation of insertion in Treap */
TreapNode* insert(TreapNode* root, int key)
{
    // If root is NULL, create a new node and return it
    if (!root)
        return newNode(key);
  
    // If key is smaller than root
    if (key <= root->key)
    {
        // Insert in left subtree
        root->left = insert(root->left, key);
  
        // Fix Heap property if it is violated
        if (root->left->priority > root->priority)
            root = rightRotate(root);
    }
    else  // If key is greater
    {
        // Insert in right subtree
        root->right = insert(root->right, key);
  
        // Fix Heap property if it is violated
        if (root->right->priority > root->priority)
            root = leftRotate(root);
    }
    return root;
}

删除:
此处的删除实现与上一篇文章中讨论的步骤略有不同。
1)如果节点是叶子,则将其删除。
2)如果节点的一个子节点为NULL,而另一个子节点为非NULL,则将节点替换为非空子节点。
3)如果节点的两个子节点都为非NULL,则查找左子节点和右子节点的最大值。
….a)如果右子级的优先级更高,请在节点上执行左旋转
….b)如果左子节点的优先级更高,请在节点上执行右旋转。

第3步的想法是将节点下移,以便我们得到情况1或情况2。

/* Recursive implementation of Delete() */
TreapNode* deleteNode(TreapNode* root, int key)
{
    // Base case
    if (root == NULL) return root;
  
    // IF KEYS IS NOT AT ROOT
    if (key < root->key)
        root->left = deleteNode(root->left, key);
    else if (key > root->key)
        root->right = deleteNode(root->right, key);
  
    // IF KEY IS AT ROOT
  
    // If left is NULL
    else if (root->left == NULL)
    {
        TreapNode *temp = root->right;
        delete(root);
        root = temp;  // Make right child as root
    }
  
    // If Right is NULL
    else if (root->right == NULL)
    {
        TreapNode *temp = root->left;
        delete(root);
        root = temp;  // Make left child as root
    }
  
    // If ksy is at root and both left and right are not NULL
    else if (root->left->priority < root->right->priority)
    {
        root = leftRotate(root);
        root->left = deleteNode(root->left, key);
    }
    else
    {
        root = rightRotate(root);
        root->right = deleteNode(root->right, key);
    }
  
    return root;
}

演示所有操作的竞争计划

// C++ program to demosntrate search, insert and delete in Treap
#include 
using namespace std;
  
// A Treap Node
struct TreapNode
{
    int key, priority;
    TreapNode *left, *right;
};
  
/* 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 */
  
// A utility function to right rotate subtree rooted with y
// See the diagram given above.
TreapNode *rightRotate(TreapNode *y)
{
    TreapNode *x = y->left,  *T2 = x->right;
  
    // Perform rotation
    x->right = y;
    y->left = T2;
  
    // Return new root
    return x;
}
  
// A utility function to left rotate subtree rooted with x
// See the diagram given above.
TreapNode *leftRotate(TreapNode *x)
{
    TreapNode *y = x->right, *T2 = y->left;
  
    // Perform rotation
    y->left = x;
    x->right = T2;
  
    // Return new root
    return y;
}
  
/* Utility function to add a new key */
TreapNode* newNode(int key)
{
    TreapNode* temp = new TreapNode;
    temp->key = key;
    temp->priority = rand()%100;
    temp->left = temp->right = NULL;
    return temp;
}
  
// C function to search a given key in a given BST
TreapNode* search(TreapNode* root, int key)
{
    // Base Cases: root is null or key is present at root
    if (root == NULL || root->key == key)
       return root;
  
    // Key is greater than root's key
    if (root->key < key)
       return search(root->right, key);
  
    // Key is smaller than root's key
    return search(root->left, key);
}
  
/* Recursive implementation of insertion in Treap */
TreapNode* insert(TreapNode* root, int key)
{
    // If root is NULL, create a new node and return it
    if (!root)
        return newNode(key);
  
    // If key is smaller than root
    if (key <= root->key)
    {
        // Insert in left subtree
        root->left = insert(root->left, key);
  
        // Fix Heap property if it is violated
        if (root->left->priority > root->priority)
            root = rightRotate(root);
    }
    else  // If key is greater
    {
        // Insert in right subtree
        root->right = insert(root->right, key);
  
        // Fix Heap property if it is violated
        if (root->right->priority > root->priority)
            root = leftRotate(root);
    }
    return root;
}
  
/* Recursive implementation of Delete() */
TreapNode* deleteNode(TreapNode* root, int key)
{
    if (root == NULL)
        return root;
  
    if (key < root->key)
        root->left = deleteNode(root->left, key);
    else if (key > root->key)
        root->right = deleteNode(root->right, key);
  
    // IF KEY IS AT ROOT
  
    // If left is NULL
    else if (root->left == NULL)
    {
        TreapNode *temp = root->right;
        delete(root);
        root = temp;  // Make right child as root
    }
  
    // If Right is NULL
    else if (root->right == NULL)
    {
        TreapNode *temp = root->left;
        delete(root);
        root = temp;  // Make left child as root
    }
  
    // If ksy is at root and both left and right are not NULL
    else if (root->left->priority < root->right->priority)
    {
        root = leftRotate(root);
        root->left = deleteNode(root->left, key);
    }
    else
    {
        root = rightRotate(root);
        root->right = deleteNode(root->right, key);
    }
  
    return root;
}
  
// A utility function to print tree
void inorder(TreapNode* root)
{
    if (root)
    {
        inorder(root->left);
        cout << "key: "<< root->key << " | priority: %d "
            << root->priority;
        if (root->left)
            cout << " | left child: " << root->left->key;
        if (root->right)
            cout << " | right child: " << root->right->key;
        cout << endl;
        inorder(root->right);
    }
}
  
  
// Driver Program to test above functions
int main()
{
    srand(time(NULL));
  
    struct TreapNode *root = NULL;
    root = insert(root, 50);
    root = insert(root, 30);
    root = insert(root, 20);
    root = insert(root, 40);
    root = insert(root, 70);
    root = insert(root, 60);
    root = insert(root, 80);
  
    cout << "Inorder traversal of the given tree \n";
    inorder(root);
  
    cout << "\nDelete 20\n";
    root = deleteNode(root, 20);
    cout << "Inorder traversal of the modified tree \n";
    inorder(root);
  
    cout << "\nDelete 30\n";
    root = deleteNode(root, 30);
    cout << "Inorder traversal of the modified tree \n";
    inorder(root);
  
    cout << "\nDelete 50\n";
    root = deleteNode(root, 50);
    cout << "Inorder traversal of the modified tree \n";
    inorder(root);
  
    TreapNode *res = search(root, 50);
    (res == NULL)? cout << "\n50 Not Found ":
                   cout << "\n50 found";
  
    return 0;
}

输出:

Inorder traversal of the given tree 
key: 20 | priority: %d 92 | right child: 50
key: 30 | priority: %d 48 | right child: 40
key: 40 | priority: %d 21
key: 50 | priority: %d 73 | left child: 30 | right child: 60
key: 60 | priority: %d 55 | right child: 70
key: 70 | priority: %d 50 | right child: 80
key: 80 | priority: %d 44

Delete 20
Inorder traversal of the modified tree 
key: 30 | priority: %d 48 | right child: 40
key: 40 | priority: %d 21
key: 50 | priority: %d 73 | left child: 30 | right child: 60
key: 60 | priority: %d 55 | right child: 70
key: 70 | priority: %d 50 | right child: 80
key: 80 | priority: %d 44

Delete 30
Inorder traversal of the modified tree 
key: 40 | priority: %d 21
key: 50 | priority: %d 73 | left child: 40 | right child: 60
key: 60 | priority: %d 55 | right child: 70
key: 70 | priority: %d 50 | right child: 80
key: 80 | priority: %d 44

Delete 50
Inorder traversal of the modified tree 
key: 40 | priority: %d 21
key: 60 | priority: %d 55 | left child: 40 | right child: 70
key: 70 | priority: %d 50 | right child: 80
key: 80 | priority: %d 44

50 Not Found 

以上输出说明:

Every node is written as key(priority)

The above code constructs below tree
  20(92)
     \
     50(73)
     /     \
  30(48)   60(55) 
     \        \
  40(21)     70(50)
                \
                80(44)   


After deleteNode(20)
     50(73)
     /     \
  30(48)   60(55) 
     \        \
  40(21)     70(50)
                \
                80(44)   
 

After deleteNode(30)
     50(73)
     /     \
  40(21)   60(55) 
             \
             70(50)
               \
               80(44)   
 

After deleteNode(50)
     60(55)
     /     \
  40(21)  70(50)  
             \
            80(44)