Problem p02285 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <cmath>
#include <iostream>
#include <list>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>

#define REP(i, n) for (int(i) = 0; (i) < (n); (i)++)
using namespace std;

class node {
public:
  int key;
  node *left, *right, *parent;
  node() : key(0), left(NULL), right(NULL), parent(NULL){};
  node(int n) : key(n), left(NULL), right(NULL), parent(NULL){};
};

class tree {
public:
  node *root;
  tree() : root(NULL){};
  tree(node *n) : root(n){};
  void insert(int n) {
    node N(n);
    this->insert(N);
  };
  void insert(node n) {
    node *y = NULL;
    node *x = root;
    while (x != NULL) {
      y = x;
      if (n.key < x->key)
        x = x->left;
      else
        x = x->right;
    }
    n.parent = y;
    if (y == NULL)
      root = new node(n);
    else if (n.key < y->key)
      y->left = new node(n);
    else
      y->right = new node(n);
  };
  bool find(int n) {
    if (root->key == n)
      return true;
    if (root->key > n) {
      tree t1(root->left);
      if (t1.root != NULL)
        return t1.find(n);
      else
        return false;
    }
    if (root->key < n) {
      tree t1(root->right);
      if (t1.root != NULL)
        return t1.find(n);
      else
        return false;
    }
  };
  void Delete(int n) {
    if (root->key > n) {
      tree t1(root->left);
      if (t1.root != NULL)
        t1.Delete(n);
      return;
    }
    if (root->key < n) {
      tree t1(root->right);
      if (t1.root != NULL)
        t1.Delete(n);
      return;
    }
    if (root->left == NULL && root->right == NULL) {
      if (root->parent->key > n)
        root->parent->left = NULL;
      else
        root->parent->right = NULL;
    } else if (root->left != NULL && root->right != NULL) {
      node *y = root->right;
      while (y->left != NULL)
        y = y->left;
      root->left->parent = y;
      root->right->parent = y;
      if (root->parent->key > n)
        root->parent->left = y;
      else
        root->parent->right = y;

      if (y->parent->key > y->key)
        y->parent->left = y->right;
      else
        y->parent->right = y->right;
      y->parent = root->parent;
      y->left = root->left;
      if (y != root->right)
        y->right = root->right;
      else
        y->right = y->right->right;
    } else {
      if (root->left != NULL) {
        if (root->parent->key > n)
          root->parent->left = root->left;
        else
          root->parent->right = root->left;
        root->left->parent = root->parent;
      } else {
        if (root->parent->key > n)
          root->parent->left = root->right;
        else
          root->parent->right = root->right;
        root->right->parent = root->parent;
      }
    }
  }
  void Pre() {
    tree t1(root->left), t2(root->right);
    cout << " " << root->key;
    if (t1.root != NULL)
      t1.Pre();
    if (t2.root != NULL)
      t2.Pre();
  };
  void Ino() {
    tree t1(root->left), t2(root->right);
    if (t1.root != NULL)
      t1.Ino();
    cout << " " << root->key;
    if (t2.root != NULL)
      t2.Ino();
  };
  void Pos() {
    tree t1(root->left), t2(root->right);
    if (t1.root != NULL)
      t1.Pos();
    if (t2.root != NULL)
      t2.Pos();
    cout << " " << root->key;
  };
};

int main() {
  int n, nd;
  string str;
  tree T;
  cin >> n;
  REP(i, n) {
    cin >> str;
    if (str == "insert") {
      cin >> nd;
      T.insert(nd);
    } else if (str == "find") {
      cin >> nd;
      cout << (T.find(nd) ? "yes" : "no") << endl;
    } else if (str == "delete") {
      cin >> nd;
      T.Delete(nd);
    } else {
      T.Ino();
      cout << endl;
      T.Pre();
      cout << endl;
    }
  }
  return 0;
}

Fixed submission:
#include <algorithm>
#include <cmath>
#include <iostream>
#include <list>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>

#define REP(i, n) for (int(i) = 0; (i) < (n); (i)++)
using namespace std;

class node {
public:
  int key;
  node *left, *right, *parent;
  node() : key(0), left(NULL), right(NULL), parent(NULL){};
  node(int n) : key(n), left(NULL), right(NULL), parent(NULL){};
};

class tree {
public:
  node *root;
  tree() : root(NULL){};
  tree(node *n) : root(n){};
  void insert(int n) {
    node N(n);
    this->insert(N);
  };
  void insert(node n) {
    node *y = NULL;
    node *x = root;
    while (x != NULL) {
      y = x;
      if (n.key < x->key)
        x = x->left;
      else
        x = x->right;
    }
    n.parent = y;
    if (y == NULL)
      root = new node(n);
    else if (n.key < y->key)
      y->left = new node(n);
    else
      y->right = new node(n);
  };
  bool find(int n) {
    if (root->key == n)
      return true;
    if (root->key > n) {
      tree t1(root->left);
      if (t1.root != NULL)
        return t1.find(n);
      else
        return false;
    }
    if (root->key < n) {
      tree t1(root->right);
      if (t1.root != NULL)
        return t1.find(n);
      else
        return false;
    }
  };
  void Delete(int n) {
    if (root->key > n) {
      tree t1(root->left);
      if (t1.root != NULL)
        t1.Delete(n);
      return;
    }
    if (root->key < n) {
      tree t1(root->right);
      if (t1.root != NULL)
        t1.Delete(n);
      return;
    }
    if (root->left == NULL && root->right == NULL) {
      if (root->parent->key > n)
        root->parent->left = NULL;
      else
        root->parent->right = NULL;
    } else if (root->left != NULL && root->right != NULL) {
      node *y = root->right;
      while (y->left != NULL)
        y = y->left;
      root->left->parent = y;
      root->right->parent = y;
      if (root->parent->key > n)
        root->parent->left = y;
      else
        root->parent->right = y;

      if (y->parent->key > y->key)
        y->parent->left = y->right;
      else
        y->parent->right = y->right;
      y->parent = root->parent;
      y->left = root->left;
      if (y != root->right)
        y->right = root->right;
      else
        y->right = root->right->right;
    } else {
      if (root->left != NULL) {
        if (root->parent->key > n)
          root->parent->left = root->left;
        else
          root->parent->right = root->left;
        root->left->parent = root->parent;
      } else {
        if (root->parent->key > n)
          root->parent->left = root->right;
        else
          root->parent->right = root->right;
        root->right->parent = root->parent;
      }
    }
  }
  void Pre() {
    tree t1(root->left), t2(root->right);
    cout << " " << root->key;
    if (t1.root != NULL)
      t1.Pre();
    if (t2.root != NULL)
      t2.Pre();
  };
  void Ino() {
    tree t1(root->left), t2(root->right);
    if (t1.root != NULL)
      t1.Ino();
    cout << " " << root->key;
    if (t2.root != NULL)
      t2.Ino();
  };
  void Pos() {
    tree t1(root->left), t2(root->right);
    if (t1.root != NULL)
      t1.Pos();
    if (t2.root != NULL)
      t2.Pos();
    cout << " " << root->key;
  };
};

int main() {
  int n, nd;
  string str;
  tree T;
  cin >> n;
  REP(i, n) {
    cin >> str;
    if (str == "insert") {
      cin >> nd;
      T.insert(nd);
    } else if (str == "find") {
      cin >> nd;
      cout << (T.find(nd) ? "yes" : "no") << endl;
    } else if (str == "delete") {
      cin >> nd;
      T.Delete(nd);
    } else {
      T.Ino();
      cout << endl;
      T.Pre();
      cout << endl;
    }
  }
  return 0;
}