Problem p02285 (C++)

Buggy submission (status: Runtime Error):
#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>

using namespace std;

// ---------------------
// repetition
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)

// debug
#define dump(x) cerr << #x << " = " << (x) << endl;
#define debug(x)                                                               \
  cerr << #x << " = " << (x) << " (L" << __LINE__ << ")"                       \
       << " " << __FILE__ << endl;

// ---------------------
#define INF 922337203685477580
typedef long long ll;
#define NIL -INF

typedef struct Node_t {
  ll key;
  Node_t *parent;
  Node_t *left;
  Node_t *right;
} Node;

Node *root = NULL;

void insert(ll key) {
  Node *y = NULL;
  Node *x = root;

  Node *z = (Node *)malloc(sizeof(Node));
  z->key = key;
  z->parent = NULL;
  z->left = NULL;
  z->right = NULL;

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

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

int find(Node *r, ll key) {
  if (r == NULL)
    return 0;
  if (r->key == key)
    return 1;

  if (key < r->key) {
    return find(r->left, key);
  } else {
    return find(r->right, key);
  }
}

void delNode(Node *z) {
  // 1.
  if (z->left == NULL && z->right == NULL) {
    if (z->parent->key < z->key) {
      z->parent->right = NULL;
    } else {
      z->parent->left = NULL;
    }
    free(z);
  } else if (z->left == NULL) { // 2-1
    if (z->parent->key < z->key) {
      z->parent->right = z->right;
    } else {
      z->parent->left = z->right;
    }
    z->right->parent = z->parent;
    free(z);
  } else if (z->right == NULL) { // 2-2
    if (z->parent->key < z->key) {
      z->parent->right = z->left;
    } else {
      z->parent->left = z->left;
    }
    z->left->parent = z->parent;
    free(z);
  } else { // 3
    z->key = z->right->key;
    delNode(z->right);
  }
}

void del(Node *z, ll key) {
  if (z == NULL)
    return;
  if (z->key == key) {
    delNode(z);
  }

  if (key < z->key) {
    del(z->left, key);
  } else {
    del(z->right, key);
  }
}

void inorder(Node *n) {
  if (n == NULL)
    return;

  inorder(n->left);
  cout << " " << n->key;
  inorder(n->right);
}

void preorder(Node *n) {
  if (n == NULL)
    return;

  cout << " " << n->key;
  preorder(n->left);
  preorder(n->right);
}

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

  // REP(i, 500500) {
  //   Node n = {NIL, NIL, NIL, NIL};
  //   T[i] = n;
  // }

  REP(i, n) {
    string cmd;
    cin >> cmd;

    if (cmd == "insert") {
      ll key;
      cin >> key;
      insert(key);
    } else if (cmd == "find") {
      ll key;
      cin >> key;
      if (find(root, key)) {
        cout << "yes" << endl;
      } else {
        cout << "no" << endl;
      }
    } else if (cmd == "delete") {
      ll key;
      cin >> key;
      del(root, key);
    } else {
      inorder(root);
      cout << endl;
      preorder(root);
      cout << endl;
    }
  }

  return 0;
}

Fixed submission:
#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>

using namespace std;

// ---------------------
// repetition
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)

// debug
#define dump(x) cerr << #x << " = " << (x) << endl;
#define debug(x)                                                               \
  cerr << #x << " = " << (x) << " (L" << __LINE__ << ")"                       \
       << " " << __FILE__ << endl;

// ---------------------
#define INF 922337203685477580
typedef long long ll;
#define NIL -INF

typedef struct Node_t {
  ll key;
  Node_t *parent;
  Node_t *left;
  Node_t *right;
} Node;

Node *root = NULL;

void insert(ll key) {
  Node *y = NULL;
  Node *x = root;

  Node *z = (Node *)malloc(sizeof(Node));
  z->key = key;
  z->parent = NULL;
  z->left = NULL;
  z->right = NULL;

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

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

int find(Node *r, ll key) {
  if (r == NULL)
    return 0;
  if (r->key == key)
    return 1;

  if (key < r->key) {
    return find(r->left, key);
  } else {
    return find(r->right, key);
  }
}

void delNode(Node *z) {
  // 1.
  if (z->left == NULL && z->right == NULL) {
    if (z->parent->key < z->key) {
      z->parent->right = NULL;
    } else {
      z->parent->left = NULL;
    }
    free(z);
  } else if (z->left == NULL) { // 2-1
    if (z->parent->key < z->key) {
      z->parent->right = z->right;
    } else {
      z->parent->left = z->right;
    }
    z->right->parent = z->parent;
    free(z);
  } else if (z->right == NULL) { // 2-2
    if (z->parent->key < z->key) {
      z->parent->right = z->left;
    } else {
      z->parent->left = z->left;
    }
    z->left->parent = z->parent;
    free(z);
  } else { // 3
    Node *y = z->right;
    while (y->left != NULL) {
      y = y->left;
    }

    ll k = y->key;
    delNode(y);
    z->key = k;
  }
}

void del(Node *z, ll key) {
  if (z == NULL)
    return;
  if (z->key == key) {
    delNode(z);
  }

  if (key < z->key) {
    del(z->left, key);
  } else {
    del(z->right, key);
  }
}

void inorder(Node *n) {
  if (n == NULL)
    return;

  inorder(n->left);
  cout << " " << n->key;
  inorder(n->right);
}

void preorder(Node *n) {
  if (n == NULL)
    return;

  cout << " " << n->key;
  preorder(n->left);
  preorder(n->right);
}

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

  // REP(i, 500500) {
  //   Node n = {NIL, NIL, NIL, NIL};
  //   T[i] = n;
  // }

  REP(i, n) {
    string cmd;
    cin >> cmd;

    if (cmd == "insert") {
      ll key;
      cin >> key;
      insert(key);
    } else if (cmd == "find") {
      ll key;
      cin >> key;
      if (find(root, key)) {
        cout << "yes" << endl;
      } else {
        cout << "no" << endl;
      }
    } else if (cmd == "delete") {
      ll key;
      cin >> key;
      del(root, key);
    } else {
      inorder(root);
      cout << endl;
      preorder(root);
      cout << endl;
    }
  }

  return 0;
}