Problem p02285 (C++)

Buggy submission (status: Runtime Error):
#include <bits/stdc++.h>
using namespace std;

struct Node {
  int key;
  Node *right, *left, *parent;
};

Node *NIL;

struct BST {
  Node *root;

  BST() { root = NIL; }

  void insert(int k) {
    Node *y = NIL;
    Node *x = root;
    Node *z = (Node *)malloc(sizeof(Node));
    z->key = k;
    z->left = NIL;
    z->right = NIL;

    while (x != NIL) {
      y = x;
      if (z->key < x->key) {
        x = x->left;
      } else {
        x = x->right;
      }
    }

    z->parent = y;
    if (y == NIL) {
      root = z;
    } else {
      if (z->key < y->key) {
        y->left = z;
      } else {
        y->right = z;
      }
    }
  }

  Node *find(int k) {
    Node *u = root;
    while (u != NIL) {
      if (k == u->key) {
        return u;
      } else if (k < u->key) {
        u = u->left;
      } else {
        u = u->right;
      }
    }

    return NIL;
  }

  void deletes(int k) {
    Node *z = find(k);

    if (z == NIL)
      return;

    if (z->left == NIL && z->right == NIL) {
      Node *p = z->parent;
      if (k < p->key) {
        p->left = NIL;
      } else {
        p->right = NIL;
      }
      free(z);
    } else if (z->left != NIL && z->right != NIL) {
      Node *d = z->right;
      while (d->left != NIL)
        d = d->left;
      z->key = d->key;
      (d->parent)->left = NIL;
      free(d);
    } else if (z->left != NIL) {
      Node *p = z->parent;
      Node *c = z->left;
      if (p->key > c->key) {
        p->left = c;
      } else {
        p->right = c;
      }
      c->parent = p;
      free(z);
    } else {
      Node *p = z->parent;
      Node *c = z->right;
      if (p->key > c->key) {
        p->left = c;
      } else {
        p->right = c;
      }
      c->parent = p;
      free(z);
    }
  }
};

void inorder(Node *u) {
  if (u == NIL)
    return;
  inorder(u->left);
  cout << " " << u->key;
  inorder(u->right);
}

void preorder(Node *u) {
  if (u == NIL)
    return;
  cout << " " << u->key;
  preorder(u->left);
  preorder(u->right);
}

int main() {
  int m;
  cin >> m;

  BST bst;
  while (m--) {
    string c;
    cin >> c;
    int n;
    if (c == "insert") {
      cin >> n;
      bst.insert(n);
    } else if (c == "find") {
      cin >> n;
      if (bst.find(n) != NIL)
        cout << "yes" << endl;
      else
        cout << "no" << endl;
    } else if (c == "delete") {
      cin >> n;
      bst.deletes(n);
    } else {
      inorder(bst.root);
      cout << endl;
      preorder(bst.root);
      cout << endl;
    }
  }

  return 0;
}


Fixed submission:
#include <bits/stdc++.h>
using namespace std;

struct Node {
  int key;
  Node *right, *left, *parent;
};

Node *NIL;

struct BST {
  Node *root;

  BST() { root = NIL; }

  void insert(int k) {
    Node *y = NIL;
    Node *x = root;
    Node *z = (Node *)malloc(sizeof(Node));
    z->key = k;
    z->left = NIL;
    z->right = NIL;

    while (x != NIL) {
      y = x;
      if (z->key < x->key) {
        x = x->left;
      } else {
        x = x->right;
      }
    }

    z->parent = y;
    if (y == NIL) {
      root = z;
    } else {
      if (z->key < y->key) {
        y->left = z;
      } else {
        y->right = z;
      }
    }
  }

  Node *find(int k) {
    Node *u = root;
    while (u != NIL) {
      if (k == u->key) {
        return u;
      } else if (k < u->key) {
        u = u->left;
      } else {
        u = u->right;
      }
    }

    return NIL;
  }

  void deletes(int k) {
    Node *z = find(k);

    if (z == NIL)
      return;

    if (z->left == NIL && z->right == NIL) {
      Node *p = z->parent;
      if (k < p->key) {
        p->left = NIL;
      } else {
        p->right = NIL;
      }
      free(z);
    } else if (z->left != NIL && z->right != NIL) {
      Node *d = z->right;
      while (d->left != NIL)
        d = d->left;
      z->key = d->key;
      if (z->right == d)
        (d->parent)->right = NIL;
      else if (d->right == NIL)
        (d->parent)->left = NIL;
      else
        (d->parent)->left = d->right;
      free(d);
    } else if (z->left != NIL) {
      Node *p = z->parent;
      Node *c = z->left;
      if (p->key > c->key) {
        p->left = c;
      } else {
        p->right = c;
      }
      c->parent = p;
      free(z);
    } else {
      Node *p = z->parent;
      Node *c = z->right;
      if (p->key > c->key) {
        p->left = c;
      } else {
        p->right = c;
      }
      c->parent = p;
      free(z);
    }
  }
};

void inorder(Node *u) {
  if (u == NIL)
    return;
  inorder(u->left);
  cout << " " << u->key;
  inorder(u->right);
}

void preorder(Node *u) {
  if (u == NIL)
    return;
  cout << " " << u->key;
  preorder(u->left);
  preorder(u->right);
}

int main() {
  int m;
  cin >> m;

  BST bst;
  while (m--) {
    string c;
    cin >> c;
    int n;
    if (c == "insert") {
      cin >> n;
      bst.insert(n);
    } else if (c == "find") {
      cin >> n;
      if (bst.find(n) != NIL)
        cout << "yes" << endl;
      else
        cout << "no" << endl;
    } else if (c == "delete") {
      cin >> n;
      bst.deletes(n);
    } else {
      inorder(bst.root);
      cout << endl;
      preorder(bst.root);
      cout << endl;
    }
  }

  return 0;
}