Merge branch 'ds-ops' of github.com:foo290/C-Plus-Plus into ds-ops

This commit is contained in:
foo290
2021-07-17 21:25:11 +05:30

View File

@@ -1,29 +1,34 @@
/** /**
* @file * @file
* @brief An implementation for finding the [Inorder successor of a binary * @brief An implementation for finding the [Inorder successor of a binary
* search tree](https://www.youtube.com/watch?v=5cPbNCrdotA&t=904s) Inorder * search tree](https://www.youtube.com/watch?v=5cPbNCrdotA) Inorder
* successor of a node is the next node in Inorder traversal of the Binary Tree. * successor of a node is the next node in Inorder traversal of the Binary Tree.
* Inorder Successor is NULL for the last node in Inorder traversal. * Inorder Successor is NULL for the last node in Inorder traversal.
* @details * @details
* ### Case 1: The given node has the right node/subtree * ### Case 1: The given node has the right node/subtree
* *
* In this case the left most deepest node in the right subtree will come just * * In this case, the left-most deepest node in the right subtree will
* after the given node as we go to left deep in inorder. * come just after the given node as we go to left deep in inorder.
* - Go deep to left most node in right subtree. * - Go deep to left most node in right subtree.
* OR, we can also say in case if BST, find the minimum of the subtree for a given node. * OR, we can also say in case if BST, find the minimum of the subtree
* for a given node.
* *
* ### Case 2: The given node does not have a right node/subtree * ### Case 2: The given node does not have a right node/subtree
* *
* #### Method 1: Use parent pointer (store the address of parent nodes) * #### Method 1: Use parent pointer (store the address of parent nodes)
* * If a node does not have the right subtree, and we already visited the node itself, * * If a node does not have the right subtree, and we already visited the
* then the next node will be its parent node according to inorder traversal, * node itself, then the next node will be its parent node according to inorder
* and if we are going to parent from left, then the parent would be unvisited. * traversal, and if we are going to parent from left, then the parent would be
* * In other words, go to the nearest ancestor for which given node would be in left subtree. * unvisited.
* * In other words, go to the nearest ancestor for which given node would
* be in left subtree.
* *
* #### Method 2: Search from the root node * #### Method 2: Search from the root node
* * In case if there is no link from a child node to the parent node, we need to walk down the tree starting * * In case if there is no link from a child node to the parent node, we
* from the root node to the given node, by doing so, we are visiting every ancestor of the given node. * need to walk down the tree starting from the root node to the given node, by
* * In order successor would be the deepest node in this path for which given node is in left subtree. * doing so, we are visiting every ancestor of the given node.
* * In order successor would be the deepest node in this path for which
* given node is in left subtree.
* *
* @author [Nitin Sharma](https://github.com/foo290) * @author [Nitin Sharma](https://github.com/foo290)
* */ * */
@@ -98,12 +103,12 @@ namespace operations_on_datastructures {
} else if (root->data == data) { } else if (root->data == data) {
return root; /// Node found! return root; /// Node found!
} else if (data > root->data) { } else if (data > root->data) {
/// Traverse right subtree recursively as the given data is greater than the data in root node, /// Traverse right subtree recursively as the given data is greater than
/// data must be present in right subtree. /// the data in root node, data must be present in right subtree.
return getNode(root->right, data); return getNode(root->right, data);
} else { } else {
/// Traverse left subtree recursively as the given data is less than the data in root node, /// Traverse left subtree recursively as the given data is less than the
/// data must be present in left subtree. /// data in root node, data must be present in left subtree.
return getNode(root->left, data); return getNode(root->left, data);
} }
} }
@@ -155,9 +160,10 @@ namespace operations_on_datastructures {
} }
/** /**
* @brief Inorder successor of a node is the next node in inorder traversal of the Binary Tree. * @brief Inorder successor of a node is the next node in inorder traversal of
* This function takes the root node and the data of the node for which we have to find the inorder successor, and * the Binary Tree. This function takes the root node and the data of the node
* returns the inorder successor node. * for which we have to find the inorder successor, and returns the inorder
* successor node.
* @details Search from the root node as we need to walk the tree starting from * @details Search from the root node as we need to walk the tree starting from
* the root node to the given node, by doing so, we are visiting every ancestor * the root node to the given node, by doing so, we are visiting every ancestor
* of the given node. In order successor would be the deepest node in this path * of the given node. In order successor would be the deepest node in this path
@@ -196,13 +202,14 @@ namespace operations_on_datastructures {
} }
/** /**
* @brief This function clears the memory allocated to entire tree recursively. Its just for clean up the * @brief This function clears the memory allocated to entire tree recursively.
* memory and not relevant to the actual topic. * Its just for clean up the memory and not relevant to the actual topic.
* @param root Root node of the tree. * @param root Root node of the tree.
* @returns void * @returns void
* */ * */
void deallocate(Node *rootNode) { void deallocate(Node *rootNode) {
if (rootNode == nullptr) return; if (rootNode == nullptr)
return;
deallocate(rootNode->left); deallocate(rootNode->left);
deallocate(rootNode->right); deallocate(rootNode->right);
delete (rootNode); delete (rootNode);
@@ -211,8 +218,6 @@ namespace operations_on_datastructures {
} // namespace inorder_traversal_of_bst } // namespace inorder_traversal_of_bst
} // namespace operations_on_datastructures } // namespace operations_on_datastructures
/** /**
* @brief class encapsulating the necessary test cases * @brief class encapsulating the necessary test cases
*/ */
@@ -283,7 +288,8 @@ public:
assert(inorderSuccessor == expectedOutput); assert(inorderSuccessor == expectedOutput);
log("Assertion check passed!"); log("Assertion check passed!");
operations_on_datastructures::inorder_traversal_of_bst::deallocate(root); /// memory cleanup! operations_on_datastructures::inorder_traversal_of_bst::deallocate(
root); /// memory cleanup!
log("[PASS] : TEST CASE 1 PASS!"); log("[PASS] : TEST CASE 1 PASS!");
log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
@@ -323,7 +329,8 @@ public:
assert(inorderSuccessor->data == expectedOutput); assert(inorderSuccessor->data == expectedOutput);
log("Assertion check passed!"); log("Assertion check passed!");
operations_on_datastructures::inorder_traversal_of_bst::deallocate(root); /// memory cleanup! operations_on_datastructures::inorder_traversal_of_bst::deallocate(
root); /// memory cleanup!
log("[PASS] : TEST CASE 2 PASS!"); log("[PASS] : TEST CASE 2 PASS!");
log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
@@ -364,7 +371,8 @@ public:
assert(inorderSuccessor->data == expectedOutput); assert(inorderSuccessor->data == expectedOutput);
log("Assertion check passed!"); log("Assertion check passed!");
operations_on_datastructures::inorder_traversal_of_bst::deallocate(root); /// memory cleanup! operations_on_datastructures::inorder_traversal_of_bst::deallocate(
root); /// memory cleanup!
log("[PASS] : TEST CASE 3 PASS!"); log("[PASS] : TEST CASE 3 PASS!");
log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
@@ -411,7 +419,7 @@ int main(int argc, char *argv[]) {
} else { } else {
std::cout << "Target element is : " << targetElement << std::endl; std::cout << "Target element is : " << targetElement << std::endl;
std::cout << "Inorder successor for target element is : " std::cout << "Inorder successor for target element is : "
<< inorderSuccessor->data; << inorderSuccessor->data << std::endl;
} }
deallocate(root); /// memory cleanup! deallocate(root); /// memory cleanup!