强烈建议将第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)