Binary Search Tree



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

	typedef struct node {
		int data;
		struct node *left, *right;
	} node;

	typedef struct BST {
		struct node *root;
	} BST;

	// Function Prototypes
	BST *createBST();
	node *createNode(int data);
	void addNodeRecWrapper(BST *bst, int data);
	node *addNodeRec(node *root, node *newNode);
	void addNodeIterative(BST *bst, int data);
	int nodeExists(BST *bst, int target);
	node *targetNodeParent(node *root, int target);
	int deleteNode(BST *bst, int data);
	node *minNode(node *root);
	void printPreorder(node *root);
	void printInorder(node *root);
	void printPostorder(node *root);
	int smallestValue(node *root);
	void printOptions();
	void freeBST(BST *bst);
	void freeBSTNodes(node *root);

	// Initialize BST struct
	BST *createBST() {
		BST *b = malloc(sizeof(BST));
		b->root = NULL;
		return b;
	}

	// Initialize BST node
	node *createNode(int data) {
		node *n = malloc(sizeof(node));
		n->data = data;
		n->left = NULL;
		n->right = NULL;
		return n;
	}

	// Calls recursive addNodeRec function
	void addNodeRecWrapper(BST *bst, int data) {
		if (!bst)
			return;
		node *newNode = createNode(data);
		bst->root = addNodeRec(bst->root, newNode);
	}

	// Recursively traverses the BST to find the correct insertion position
	// Once a NULL child pointer is reached, the new node is inserted as a leaf
	node *addNodeRec(node *root, node *newNode) {
		if (!root)
			return newNode;

		if (newNode->data < root->data)
			root->left = addNodeRec(root->left, newNode);
		else
			root->right = addNodeRec(root->right, newNode);

		return root;
	}

	// Iterative version of adding a BST node
	// Not called by menu in main
	void addNodeIterative(BST *bst, int data) {
		if (!bst)
			return;

		node *newNode = createNode(data);

		if (!(bst->root)) {
			bst->root = newNode;
			return;
		}
		node *walker = bst->root;
		while (walker) {
			if (data < walker->data) {
				if (walker->left) {
					walker = walker->left;
				} else {
					walker->left = newNode;
					return;
				}
			} else {
				if (walker->right) {
					walker = walker->right;
				} else {
					walker->right = newNode;
					return;
				}
			}
		}
	}

	// Returns 1 if node exists in list
	// Otherwise returns 0
	int nodeExists(BST *bst, int target) {
		if (!bst || !(bst->root))
			return 0;
		return (bst->root->data == target) || targetNodeParent(bst->root, target);
	}

	// Returns the parent node of node with specified target data value
	// If no such node exists, returns NULL
	node *targetNodeParent(node *root, int target) {
		if (!root)
			return NULL;

		if (root->left && root->left->data == target)
			return root;
		else if (root->right && root->right->data == target)
			return root;

		if (target < root->data)
			return targetNodeParent(root->left, target);
		else
			return targetNodeParent(root->right, target);
	}

	// Deletes a node with target data value
	// Assumes no duplicates exist
	int deleteNode(BST *bst, int target) {
		if (!bst || !(bst->root))
			return 0;

		node *parent;
		if (bst->root->data == target)
			parent = NULL;
		else {
			parent = targetNodeParent(bst->root, target);
			if (!parent)
				return 0;
		}

		node *delNode;
		// If !parent, target is at root
		if (!parent)
			delNode = bst->root;
		else
			delNode = target < parent->data ? parent->left : parent->right;

		// Check if leaf node
		if (!(delNode->left) && !(delNode->right)) {
			if (parent) {
				if (target < parent->data) {
					parent->left = NULL;
				} else {
					parent->right = NULL;
				}
			} else {
				bst->root = NULL;
			}
			free(delNode);
		}
		// Left child only
		else if (!(delNode->right)) {
			if (parent) {
				if (target < parent->data) {
					parent->left = delNode->left;
				} else {
					parent->right = delNode->left;
				}
			} else {
				bst->root = delNode->left;
			}
			free(delNode);
		}
		// Right child only
		else if (!(delNode->left)) {
			if (parent) {
				if (target < parent->data) {
					parent->left = delNode->right;
				} else {
					parent->right = delNode->right;
				}
			} else {
				bst->root = delNode->right;
			}
			free(delNode);
		}
		// node has two children
		else {
			node *minRight = minNode(delNode->right);
			int newDataAtDel = minRight->data;
			deleteNode(bst, newDataAtDel);
			delNode->data = newDataAtDel;
		}
		return 1;
	}

	// Returns pointer to the smallest node of given sub-tree
	// If root is NULL, returns NULL
	node *minNode(node *root) {
		if (!root)
			return NULL;
		if (root->left)
			return minNode(root->left);
		return root;
	}

	// Prints in preorder
	void printPreorder(node *root) {
		if (!root)
			return;
		printf("%d ", root->data);
		printPreorder(root->left);
		printPreorder(root->right);
	}

	// Prints in inorder
	void printInorder(node *root) {
		if (!root)
			return;
		printInorder(root->left);
		printf("%d ", root->data);
		printInorder(root->right);
	}

	// Prints in postorder
	void printPostorder(node *root) {
		if (!root)
			return;
		printPostorder(root->left);
		printPostorder(root->right);
		printf("%d ", root->data);
	}

	// Returns smallest data value in tree
	int smallestValue(node *root) {
		return !(root->left) ? root->data : smallestValue(root->left);
	}

	// Print options menu
	void printOptions() {
		printf("1) Add data to BST\n");
		printf("2) Delete data from BST\n");
		printf("3) Check if data is in BST\n");
		printf("4) Print BST preorder\n");
		printf("5) Print BST inorder\n");
		printf("6) Print BST postorder\n");
		printf("7) Print smallest value in tree\n");
		printf("8) Quit\n");
		printf("\n:");
	}

	// Frees BST
	void freeBST(BST *bst) {
		if (!bst)
			return;
		freeBSTNodes(bst->root);
		free(bst);
	}

	// Frees all nodes within a BST
	void freeBSTNodes(node *root) {
		if (!root)
			return;
		freeBSTNodes(root->left);
		freeBSTNodes(root->right);
		free(root);
	}

	int main(void) {
		BST *binSearchTree = createBST();

		int choice = 0;
		int data;

		while (choice != 8) {
			printOptions();
			scanf("%d", &choice);

			switch (choice) {

			case 1: // Add data
				printf("Enter an integer to add to the tree\n:");
				scanf("%d", &data);
				if (!nodeExists(binSearchTree, data)) {
					addNodeRecWrapper(binSearchTree, data);
					printf("%d added to list\n", data);
				} else {
					printf("%d is already in the tree\n", data);
				}
				break;

			case 2: // Delete data
				printf("Enter an integer to delete from the tree\n:");
				scanf("%d", &data);
				if (nodeExists(binSearchTree, data)) {
					deleteNode(binSearchTree, data);
					printf("%d deleted\n", data);
				} else
					printf("%d is not in the tree\n", data);
				break;

			case 3: // Does data exist?
				printf("Enter an integer to check if it exists in the tree\n:");
				scanf("%d", &data);
				printf("%d is %sin the tree\n", data,
							 nodeExists(binSearchTree, data) ? "" : "NOT ");
				break;

			case 4: // Print tree preorder
				printf("\nPrinting BST preorder\n\n ");
				printPreorder(binSearchTree->root);
				printf("\n");
				break;

			case 5: // Print tree inorder
				printf("\nPrinting BST inorder\n\n ");
				printInorder(binSearchTree->root);
				printf("\n");
				break;

			case 6: // Print tree postorder
				printf("\nPrinting BST postorder\n\n");
				printPostorder(binSearchTree->root);
				printf("\n");
				break;

			case 7: // Print smallest value in tree
				if (binSearchTree->root) {
					printf("\nThe smallest value in the tree is: %d\n",
								 smallestValue(binSearchTree->root));
				} else {
					printf("\nThe tree is currently empty\n");
				}
				break;

			default:
				break;
			}
			printf("\n");
		}

		freeBST(binSearchTree);

		return 0;
	}
						
						

Academic Notice: The code shown here is provided solely as a learning reference. Copying and pasting is intentionally disabled to encourage independent practice. Students should implement solutions on their own to demonstrate understanding. This material is not intended for direct submission in assignments.

Additionally: This code was written by a former CS1 student and may not reflect your professor’s intended solution or instructional approach. For coursework, students are expected to follow examples, conventions, and requirements presented in class and in professor-assigned materials.