#include<iostream>
using namespace std;
struct node{
 int info;
 int height;
 node *left,*right;
};
int max(int a,int b)
{
 return (a>b)? a:b;
}
int height(node *n)
{
 if(n==NULL)
 {
  return 0;
 }
 else
 {
  return n->height;
 }
}
node* NewNode(int item)
{
 node *temp=new node;
 temp->left=temp->right=NULL;
 temp->info=item;
 return temp;
}
node* rightrotate(node *y)
{
 node *x=y->left;
 node *t2=x->right;
 x->right=y;
 y->left=t2;
 y->height=max(height(y->left),height(y->right));
 x->height=max(height(x->left),height(x->right));
 return x;
}
node* leftrotate(node *x)
{
 node *y=x->right;
 node *t2=x->left;
    y->left=x;
    x->right=t2;
    x->height=max(height(x->left),height(y->right));
    y->height=max(height(y->left),height(y->right));
    return y;
}
int getbalance(node *n)
{
 if(n==NULL)
 {
  return 0;
 }
 else
 {
  return (height(n->left)-height(n->right));
 }
}
node* insert(node *ptr,int item)
{
 if(ptr==NULL)
 {
  return NewNode(item);
 }
 if(item<ptr->info)
 {
  ptr->left=insert(ptr->left,item);
 }
 else if(item>ptr->info)
 {
  ptr->right=insert(ptr->right,item);
 }
 else
 {
  return ptr;
 }
 ptr->height=1+max(height(ptr->left),height(ptr->right));
 int balance=getbalance(ptr);
 if(balance>1 && item<ptr->left->info)
 {
  return rightrotate(ptr);
 }
 if(balance <-1 && item>ptr->right->info)
 {
  return rightrotate(ptr);
 }
 if(balance>1 && item>ptr->left->info)
 {
  ptr->left=leftrotate(ptr->left);
  return rightrotate(ptr);
 }
 if(balance<-1 && item<ptr->right->info)
 {
  ptr->right=rightrotate(ptr->right);
  return leftrotate(ptr);
 }
 return ptr;
}
void inorder(node *root)
{
 if(root)
 {
  inorder(root->left);
  cout<<root->info<<"t";
  inorder(root->right);
 }
}
node* minvalue(node *n)
{
   node *ptr=n;
   while(ptr->left)
   {
        ptr=ptr->left;
   }
   return ptr;
}
node* deletenode(node *ptr,int item)
{
 if(ptr==NULL)
 {
  return ptr;
 }
 if(item<ptr->info)
 {
  ptr->left=deletenode(ptr->left,item);
 }
 else if(item>ptr->info)
 {
  ptr->right=deletenode(ptr->right,item);
 }
 else
 {
  if((ptr->left==NULL)||(ptr->right==NULL))
  {
   node *temp=ptr->left?ptr->left:ptr->right;
   if(temp==NULL)//0 child
   {
    temp=ptr;
    ptr=NULL;
   }
   else//1 child
   {
    ptr->info=temp->info;
   }
   free(temp);
  }
  else
  {
   node *temp=minvalue(ptr->right);
   ptr->info=temp->info;
   ptr->right=deletenode(ptr->right,temp->info);
  }
 }
 if(ptr==NULL)
 {
  return ptr;
 }
 ptr->height=1+max(height(ptr->left),height(ptr->right));
 int balance=getbalance(ptr);
 
 if (balance > 1 && getbalance(ptr->left) >= 0) 
  return rightrotate(ptr); 

 // Left Right Case 
 if (balance > 1 && getbalance(ptr->left) < 0) 
 { 
  ptr->left = leftrotate(ptr->left); 
  return rightrotate(ptr); 
 } 

 // Right Right Case 
 if (balance < -1 && getbalance(ptr->right) <= 0) 
  return leftrotate(ptr); 

 // Right Left Case 
 if (balance < -1 && getbalance(ptr->right) > 0) 
 { 
  ptr ->right = rightrotate(ptr->right); 
  return leftrotate(ptr); 
 } 
 return ptr;
}
int main() 
{ 
struct node *root = NULL; 

/* Constructing tree given in the above figure */
 root = insert(root, 9); 
 root = insert(root, 5); 
 root = insert(root, 10); 
 root = insert(root, 0); 
 root = insert(root, 6); 
 root = insert(root, 11); 
 root = insert(root, 11); 
 root = insert(root, 10);
 root = insert(root, 1); 
 root = insert(root, 2); 
 inorder(root);
 root=deletenode(root,10);
 cout<<"nn";
 inorder(root);
 return 0;
}