#include <iostream>
#include <stack>
#include <algorithm>
using namespace std;
class Node {
public:
int key;
Node* left;
Node* right;
int height;
int bf; // Balance Factor
Node(int key) {
this->key = key;
this->left = nullptr;
this->right = nullptr;
this->height = 1;
this->bf = 0;
}
};
Node* getAVLNode(int key) {
return new Node(key);
}
int height(Node* T) {
return T ? T->height : 0;
}
Node* rotateLL(Node* x) {
Node* y = x->left;
x->left = y->right;
y->right = x;
x->height = 1 + max(height(x->left), height(x->right));
y->height = 1 + max(height(y->left), height(y->right));
x->bf = height(x->left) - height(x->right);
y->bf = height(y->left) - height(y->right);
return y;
}
Node* rotateRR(Node* x) {
Node* y = x->right;
x->right = y->left;
y->left = x;
x->height = 1 + max(height(x->left), height(x->right));
y->height = 1 + max(height(y->left), height(y->right));
x->bf = height(x->left) - height(x->right);
y->bf = height(y->left) - height(y->right);
return y;
}
Node* rotateLR(Node* x) {
x->left = rotateRR(x->left);
return rotateLL(x);
}
Node* rotateRL(Node* x) {
x->right = rotateLL(x->right);
return rotateRR(x);
}
bool insertAVL(Node*& T, int newKey) {
Node* p = T;
Node* q = nullptr;
stack<Node*> nodeStack;
// Find position to insert newKey while storing parent nodes on stack
while (p != nullptr) {
if (newKey == p->key) {
return false; // Avoid inserting duplicates
}
q = p;
nodeStack.push(q);
if (newKey < p->key) {
p = p->left;
} else {
p = p->right;
}
}
// Create new node
Node* y = getAVLNode(newKey);
// Insert y as a child of q
if (T == nullptr) {
T = y;
} else if (newKey < q->key) {
q->left = y;
} else {
q->right = y;
}
// Update height and balancing factor while popping parent nodes from stack
Node* x = nullptr;
Node* f = nullptr;
while (!nodeStack.empty()) {
q = nodeStack.top();
nodeStack.pop();
q->height = 1 + max(height(q->left), height(q->right));
q->bf = height(q->left) - height(q->right);
if (q->bf > 1 || q->bf < -1) {
if (x == nullptr) {
x = q;
f = nodeStack.empty() ? nullptr : nodeStack.top();
}
}
}
// Rebalance the tree
if (x != nullptr) {
if (x->bf > 1) {
if (x->left->bf >= 0) {
x = rotateLL(x);
} else {
x = rotateLR(x);
}
} else if (x->bf < -1) {
if (x->right->bf <= 0) {
x = rotateRR(x);
} else {
x = rotateRL(x);
}
}
if (f == nullptr) {
T = x;
} else if (f->left == x) {
f->left = x;
} else {
f->right = x;
}
}
return true;
}
bool deleteAVL(Node*& T, int deleteKey) {
Node* p = T;
Node* q = nullptr;
stack<Node*> nodeStack;
// Perform standard BST deletion
while (p != nullptr && deleteKey != p->key) {
q = p;
nodeStack.push(q);
if (deleteKey < p->key) {
p = p->left;
} else {
p = p->right;
}
}
if (p == nullptr) {
return false; // deleteKey was not found
}
// Case 1: Node has two children
if (p->left != nullptr && p->right != nullptr) {
nodeStack.push(p);
Node* tempNode = p;
if (height(p->left) < height(p->right)) {
p = p->right;
while (p->left != nullptr) {
nodeStack.push(p);
p = p->left;
}
} else {
p = p->left;
while (p->right != nullptr) {
nodeStack.push(p);
p = p->right;
}
}
tempNode->key = p->key;
q = nodeStack.top();
nodeStack.pop();
}
// Case 2: Node has 0 or 1 child
if (p->left == nullptr && p->right == nullptr) {
if (q == nullptr) {
T = nullptr;
} else if (q->left == p) {
q->left = nullptr;
} else {
q->right = nullptr;
}
} else {
Node* child = (p->left != nullptr) ? p->left : p->right;
if (q == nullptr) {
T = child;
} else if (q->left == p) {
q->left = child;
} else {
q->right = child;
}
}
delete p;
// Update height and balancing factor while popping parent nodes from stack
Node* x = nullptr;
Node* f = nullptr;
while (!nodeStack.empty()) {
q = nodeStack.top();
nodeStack.pop();
q->height = 1 + max(height(q->left), height(q->right));
q->bf = height(q->left) - height(q->right);
if (q->bf > 1 || q->bf < -1) {
x = q;
f = nodeStack.empty() ? nullptr : nodeStack.top();
// Rebalance the tree
if (x->bf > 1) {
if (x->left->bf >= 0) {
x = rotateLL(x);
} else {
x = rotateLR(x);
}
} else if (x->bf < -1) {
if (x->right->bf <= 0) {
x = rotateRR(x);
} else {
x = rotateRL(x);
}
}
if (f == nullptr) {
T = x;
} else if (f->left == x) {
f->left = x;
} else {
f->right = x;
}
}
}
return true;
}
void inorder(Node* T) {
if (T == nullptr) {
return;
}
cout << "<";
inorder(T->left);
cout << " " << T->key << " ";
inorder(T->right);
cout << ">";
}
void clear(Node* T) {
if (T == nullptr) {
return;
}
clear(T->left);
clear(T->right);
delete T;
}
int main() {
Node* root = nullptr;
char operation;
int key;
while (cin >> operation >> key) {
bool success = false;
if (operation == 'i') {
success = insertAVL(root, key);
} else if (operation == 'd') {
success = deleteAVL(root, key);
}
if (success) {
inorder(root);
cout << endl;
}
}
clear(root);
return 0;
}