#ifndef BINARYSEARCHTREE_H #define BINARYSEARCHTREE_H #include <cstdlib> #include <iostream> template <typename T> struct Node{ struct Node<T> *parent; struct Node<T> *left; struct Node<T> *right; T value; }; template <typename T> class BinarySearchTree { public: /** * @brief Default Constructor * * @param */ BinarySearchTree():mRoot(NULL){} /** * @brief Destructor */ ~BinarySearchTree(); /** * @brief Insert value into the tree * * @param value: the value to be inserted */ void Insert(T value); /** * @brief Inorder travel the tree */ void InorderTreeWalk(); /** * @brief Preorder travel the tree */ void PreorderTreeWalk(); /** * @brief Get the maximum node * * @return The maximum node's value */ T GetMax(); /** * @brief Get the minimum node * * @return The minimum node's value */ T GetMin(); /** * @brief Search the value in the tree * * @param value: the value to be searched * * @return The node's pointer. Return NULL if value is not in the tree */ struct Node<T>* Search(T value); /** * @brief Get the successor of value. If the value is not in the tree, throw an exception * * @param value: the value * * @return The successor */ T Successor(T value); /** * @brief Get the predecessor of value. If the value is not in the tree, throw an exception * * @param value: the value * * @return The Predecessor */ T Predecessor(T value); /** * @brief Delete the value in the tree. If the value is not in the tree, throw an exception * * @param value: the value */ void Delete(T value); private: /** * @brief Search the value in the tree * * @param root: the root of the tree * @param value: the value to be searched * * @return The node whose value is "value". Return NULL if value is not in the tree. */ struct Node<T>* SearchNode(struct Node<T> *root, T value); /** * @brief Delete the node in the tree * * @param node: the node to be deleted */ void DeleteNode(struct Node<T> *node); /** * @brief Get the maximum value in tree whose root is "root". If the tree is empty, throw an exception * * @param root: the root of the tree * * @return The maximum value */ T Maximum(struct Node<T> *root); /** * @brief Get the minimum value in tree whose root is "root". If the tree is empty, throw an exception * * @param root: the root of the tree * * @return The minimum value */ T Minimum(struct Node<T> *root); /** * @brief Free the space of the tree * * @param root: the root of the tree */ void FreeTree(struct Node<T> *root); /** * @brief Inorder travel the tree * * @param root: the root of the tree */ void InorderWalk(struct Node<T> *root); /** * @brief Preorder travel the tree * * @param root: the root of the tree */ void PreorderWalk(struct Node<T> *root); /** * @brief The root of the Binary Search Tree */ struct Node<T> *mRoot; }; template <typename T> BinarySearchTree<T>::~BinarySearchTree() { FreeTree(mRoot); } template <typename T> void BinarySearchTree<T>::FreeTree(struct Node<T> *root) { if (root == NULL) { return; } FreeTree(root->left); FreeTree(root->right); delete root; } template <typename T> void BinarySearchTree<T>::Insert(T value) { struct Node<T> *node = new struct Node<T>; node->value = value; node->left = node->right = node->parent = NULL; struct Node<T> *parent = mRoot; struct Node<T> *current = parent; while (current != NULL) { //equality means the value has been in the tree, so just return if (current->value == value) { return; } parent = current; if (current->value > value) { current = current->left; } else { current = current->right; } } //if the tree is empty if (parent == NULL) { mRoot = node; } //add the node into the tree else { if (parent->value > value) { parent->left = node; } else { parent->right = node; } node->parent = parent; } } template <typename T> void BinarySearchTree<T>::InorderTreeWalk() { InorderWalk(mRoot); } template <typename T> void BinarySearchTree<T>::InorderWalk(struct Node<T> *root) { if (root == NULL) { return; } InorderWalk(root->left); std::cout << root->value << " "; InorderWalk(root->right); } template <typename T> void BinarySearchTree<T>::PreorderTreeWalk() { PreorderWalk(mRoot); } template <typename T> void BinarySearchTree<T>::PreorderWalk(struct Node<T> *root) { if (root == NULL) { return; } std::cout << root->value << " "; PreorderWalk(root->left); PreorderWalk(root->right); } template <typename T> T BinarySearchTree<T>::GetMax() { return Maximum(mRoot); } template <typename T> T BinarySearchTree<T>::Maximum(struct Node<T> *root) { if (root == NULL) { std::cerr << "There's no node in the tree!" << std::endl; throw -1; } struct Node<T> *node = root; while (node->right) { node = node->right; } return node->value; } template <typename T> T BinarySearchTree<T>::GetMin() { return Minimum(mRoot); } template <typename T> T BinarySearchTree<T>::Minimum(struct Node<T> *root) { if (root == NULL) { std::cerr << "There's no node in the tree!" << std::endl; throw -1; } struct Node<T> *node = root; while (node->left) { node = node->left; } return node->value; } template <typename T> struct Node<T>* BinarySearchTree<T>::Search(T value) { return SearchNode(mRoot, value); } template <typename T> struct Node<T>* BinarySearchTree<T>::SearchNode(struct Node<T> *root, T value) { struct Node<T> *node = root; while (node != NULL && node->value != value) { if (value < node->value) { node = node->left; } else { node = node->right; } } return node; } template <typename T> T BinarySearchTree<T>::Successor(T value) { struct Node<T> *node = Search(value); if (node == NULL) { std::cerr << "There is no such node whose value hits parameter" << std::endl; throw -1; } //if node has right child, find the minimum node in the right tree if (node->right) { return Minimum(node->right); } //find the first ancestor turn right struct Node<T> *parent = node->parent; while (parent && parent->right == node) { node = parent; parent = node->parent; } if (parent) { return parent->value; } else { std::cerr << "The node is the last node in the tree" << std::endl; throw -1; } } template <typename T> T BinarySearchTree<T>::Predecessor(T value) { struct Node<T> *node = Search(value); if (node == NULL) { std::cerr << "There is no such node whose value hits parameter" << std::endl; throw -1; } //if node has left child, find the maximum node in the left tree if (node->left) { return Maximum(node->left); } //find the first ancestor turn left struct Node<T> *parent = node->parent; while (parent && parent->left == node) { node = parent; parent = node->parent; } if (parent) { return parent->value; } else { std::cerr << "The node is the first node in the tree" << std::endl; throw -1; } } template <typename T> void BinarySearchTree<T>::Delete(T value) { struct Node<T> *node = Search(value); if (node == NULL) { std::cerr << "There no such a node" << std::endl; throw -1; } DeleteNode(node); } template <typename T> void BinarySearchTree<T>::DeleteNode(struct Node<T> *node) { //if the node has no left or right child if (node->left == NULL && node->right == NULL) { if (node->parent) { if (node->parent->left == node) { node->parent->left = NULL; } else { node->parent->right = NULL; } } else { mRoot = NULL; } delete node; return; } //if the node has both left and right child if (node->left != NULL && node->right != NULL) { node->value = Maximum(node->left); DeleteNode(SearchNode(node->left, node->value)); return; } //the node has only one child //if the deleted node is mRoot if (node->parent == NULL) { if (node->left) { node->value = node->left->value; DeleteNode(node->left); } else { node->value = node->right->value; DeleteNode(node->right); } } else { if (node->parent->left == node) { if (node->left) { node->parent->left = node->left; node->left->parent = node->parent; } else { node->parent->left = node->right; node->right->parent = node->parent; } delete node; } else { if (node->left) { node->parent->right = node->left; node->left->parent = node->parent; } else { node->parent->right = node->right; node->right->parent = node->parent; } delete node; } } } #endif /* end of include guard: BINARYSEARCHTREE_H */