#include <stdio.h>
#include <stdlib.h>

// BST Node structure
typedef struct Node {
    int data;
    struct Node *left;
    struct Node *right;
} Node;

// Function to create a new node
Node* createNode(int value) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->data = value;
    newNode->left = NULL;
    newNode->right = NULL;
    return newNode;
}

// Iterative Insert function
Node* insert(Node* root, int value) {
    // If tree is empty, create root node
    if (root == NULL) return createNode(value);

    Node* current = root;
    while (1) {
        // If value is less than current node
        if (value < current->data) {
            if (current->left == NULL) {
                current->left = createNode(value);
                break;
            }
            current = current->left;
        }
        // If value is greater than current node
        else if (value > current->data) {
            if (current->right == NULL) {
                current->right = createNode(value);
                break;
            }
            current = current->right;
        }
        // If value already exists
        else break;
    }
    return root;
}

// Iterative Search function
Node* search(Node* root, int value) {
    Node* current = root;

    while (current != NULL) {
        // If value found
        if (value == current->data)
            return current;
        // If value is less than current node
        else if (value < current->data)
            current = current->left;
        // If value is greater than current node
        else
            current = current->right;
    }
    return NULL;
}

// Function to find minimum value node
Node* findMin(Node* root) {
    if (root == NULL) return NULL;

    Node* current = root;
    while (current->left != NULL)
        current = current->left;
    return current;
}

// Iterative Delete function
Node* delete(Node* root, int value) {
    if (root == NULL) return root;

    Node* current = root;
    Node* parent = NULL;

    // Find the node to delete and its parent
    while (current != NULL && current->data != value) {
        parent = current;
        if (value < current->data)
            current = current->left;
        else
            current = current->right;
    }

    // If value not found
    if (current == NULL) return root;

    // Case 1: Node has no children
    if (current->left == NULL && current->right == NULL) {
        if (current != root) {
            if (parent->left == current)
                parent->left = NULL;
            else
                parent->right = NULL;
        }
        else
            root = NULL;
        free(current);
    }

    // Case 2: Node has one child
    else if (current->left == NULL || current->right == NULL) {
        Node* child = (current->left) ? current->left : current->right;
        if (current != root) {
            if (parent->left == current)
                parent->left = child;
            else
                parent->right = child;
        }
        else
            root = child;
        free(current);
    }

    // Case 3: Node has two children
    else {
        Node* successor = findMin(current->right);
        int successorData = successor->data;
        delete(root, successor->data);
        current->data = successorData;
    }

    return root;
}

// Iterative Inorder traversal
void inorderTraversal(Node* root) {
    if (root == NULL) return;

    Node* stack[1000];
    int top = -1;
    Node* current = root;

    while (current != NULL || top != -1) {
        // Reach the leftmost node
        while (current != NULL) {
            stack[++top] = current;
            current = current->left;
        }

        current = stack[top--];
        printf("%d ", current->data);
        current = current->right;
    }
}

// Iterative Level Order traversal
void levelOrder(Node* root) {
    if (root == NULL) return;

    Node* queue[1000];
    int front = 0, rear = 0;
    queue[rear++] = root;

    while (front < rear) {
        Node* current = queue[front++];
        printf("%d ", current->data);

        if (current->left != NULL)
            queue[rear++] = current->left;
        if (current->right != NULL)
            queue[rear++] = current->right;
    }
}
