From 27b0f2b2c03bf0113c4c8854949584f37bc11c32 Mon Sep 17 00:00:00 2001 From: Shubham Tribedi Date: Sun, 10 Oct 2021 13:04:20 +0530 Subject: [PATCH 1/6] Added Threaded Binary Tree --- .../Trees/Threaded Binary Tree/README.md | 83 +++++ .../Threaded_Binary_Tree_all.cpp | 338 ++++++++++++++++++ 2 files changed, 421 insertions(+) create mode 100644 Data Structures/Trees/Threaded Binary Tree/README.md create mode 100644 Data Structures/Trees/Threaded Binary Tree/Threaded_Binary_Tree_all.cpp diff --git a/Data Structures/Trees/Threaded Binary Tree/README.md b/Data Structures/Trees/Threaded Binary Tree/README.md new file mode 100644 index 0000000..8477ebb --- /dev/null +++ b/Data Structures/Trees/Threaded Binary Tree/README.md @@ -0,0 +1,83 @@ +The idea of threaded binary trees is to make inorder traversal faster and do it without stack and without recursion. A binary tree is made threaded by making all right child pointers that would normally be NULL point to the inorder successor of the node (if it exists). + +There are two types of threaded binary trees. + +- Single Threaded: Where a NULL right pointers is made to point to the inorder successor (if successor exists) +- Double Threaded: Where both left and right NULL pointers are made to point to inorder predecessor and inorder successor respectively. The predecessor threads are useful for reverse inorder traversal and postorder traversal. + +The threads are also useful for fast accessing ancestors of a node. + +Single Threaded Binary Tree: Here only the right NULL pointer are made to point to inorder successor. + +Double Threaded Binary Tree: Here both the right as well as the left NULL pointers are made to point inorder successor and inorder predecessor respectively. (here the left threads are helpful in reverse inorder traveral of the tree ) + +Structure of node in threaded binary tree: + +A node in threaded binary tree has two additional attributes: + +- rightThread +- leftThread + +Both new attributes are of type bolean. + +Following is the node structure in a Single threaded binary tree and Double threaded binary tree: + +// single threaded + +struct Node{ + int data ; + Node *left ; + Node *right ; + bool rightThread ; +} + +// double threaded + +struct Node{ + int data ; + Node *left ; + Node *right ; + bool leftThread ; + bool rightThread ; +} + +Significance of bool variable (leftThread and rightThread) in structure: + +If we have some address stored in some node to diffrentiate whether that address is of parent node or of child node we use leftThread and rightThread bool variables. + +leftThread and rightThread bool variables stores whether left and right pointers point to child node or some ancestor node , if the bool variable is set to true that means pointer is pointing to child node and if it is set to 1 that means that pointer is pointing to parent node. + +for example: + +let's us say for some node right pointer is pointing to some node and righThread is set to true, this means that it is pointing to it's children, but if in the same case if rightThread is set to false this means that it is pointing to it's parent node (and not child ). + +What happens with righmost and leftmost null nodes ? + +When we create a threaded binary tree the left most and rightmost pointers do not have inorder predecessor or inorder successor so they are made to point to a dummy node as you can see in the image and leftThread of leftmost node and rightThread of rightmost node is set to false. + +Operations in Threaded Binary Tree +We can also perform various operations in a threaded binary tree like - + +1.Insert +2.search +3.Delete + +After performing the following operations we need to make sure that our new binary tree still follows all the conditions of a threaded binary tree and also these operations should be performed with least amount of space and time complexity possible. + +Applications of Threaded Binary Tree: + +The idea of threaded binary trees is to make inorder traversal of the binary tree faster and do it without using any extra space, so sometimes in small systems where hardware is very limited we use threaded binary tree for better efficiency of the software in a limited hardware space. + +Time and space complexity for operations + +Time complexity for: + +- For insertion : log(n) +- For deletion : log(n) +- For seaching : log(n) + +Space complexity for insertion is O(1) , for deletion and searching we donot require any extra space. + +The time required for finding inorder predecessor or successor for a given node is O(1) provided we are on that node. + +The Code for Threaded Binary Tree and all other Operations are given in Threaded_Binary_Tree_all.cpp \ No newline at end of file diff --git a/Data Structures/Trees/Threaded Binary Tree/Threaded_Binary_Tree_all.cpp b/Data Structures/Trees/Threaded Binary Tree/Threaded_Binary_Tree_all.cpp new file mode 100644 index 0000000..c160481 --- /dev/null +++ b/Data Structures/Trees/Threaded Binary Tree/Threaded_Binary_Tree_all.cpp @@ -0,0 +1,338 @@ +#include +using namespace std; + +struct Node { + struct Node *left, *right; + int info; + + // True if left pointer points to predecessor + // in Inorder Traversal + bool lthread; + + // True if right pointer points to predecessor + // in Inorder Traversal + bool rthread; +}; + +struct Node *search( struct Node *root , int key ){ + + Node *ptr = root ; + + + + while( ptr != nullptr ){ + + if( ptr->info == key ){ + // indicating that the element is found then + return ptr ; + }else if( ptr->info < key ){ + // moving to inorder predecessor of the current node + ptr = ptr->right ; + }else{ + // moving to inorder successor of the current node + ptr = ptr->left ; + } + + } + + // if element is not found then we can return nullptr indicating element not + // found in the given binary search tree + return nullptr ; + +} + +// Insert a Node in Binary Threaded Tree +struct Node* insert(struct Node* root, int ikey) +{ + // Searching for a Node with given value + Node* ptr = root; + Node* par = NULL; // Parent of key to be inserted + while (ptr != NULL) { + // If key already exists, return + if (ikey == (ptr->info)) { + printf("Duplicate Key !\n"); + return root; + } + + par = ptr; // Update parent pointer + + // Moving on left subtree. + if (ikey < ptr->info) { + if (ptr->lthread == false) + ptr = ptr->left; + else + break; + } + + // Moving on right subtree. + else { + if (ptr->rthread == false) + ptr = ptr->right; + else + break; + } + } + + // Create a new Node + Node* tmp = new Node; + tmp->info = ikey; + tmp->lthread = true; + tmp->rthread = true; + + if (par == NULL) { + root = tmp; + tmp->left = NULL; + tmp->right = NULL; + } + else if (ikey < (par->info)) { + tmp->left = par->left; + tmp->right = par; + par->lthread = false; + par->left = tmp; + } + else { + tmp->left = par; + tmp->right = par->right; + par->rthread = false; + par->right = tmp; + } + + return root; +} + +// Returns inorder successor using left +// and right children (Used in deletion) +struct Node* inSucc(struct Node* ptr) +{ + if (ptr->rthread == true) + return ptr->right; + + ptr = ptr->right; + while (ptr->lthread == false) + ptr = ptr->left; + + return ptr; +} + +// Returns inorder successor using rthread +// (Used in inorder) +struct Node* inorderSuccessor(struct Node* ptr) +{ + // If rthread is set, we can quickly find + if (ptr->rthread == true) + return ptr->right; + + // Else return leftmost child of right subtree + ptr = ptr->right; + while (ptr->lthread == false) + ptr = ptr->left; + return ptr; +} + +// Printing the threaded tree +void inorder(struct Node* root) +{ + if (root == NULL) + printf("Tree is empty"); + + // Reach leftmost Node + struct Node* ptr = root; + while (ptr->lthread == false) + ptr = ptr->left; + + // One by one print successors + while (ptr != NULL) { + printf("%d ", ptr->info); + ptr = inorderSuccessor(ptr); + } +} + +struct Node* inPred(struct Node* ptr) +{ + if (ptr->lthread == true) + return ptr->left; + + ptr = ptr->left; + while (ptr->rthread == false) + ptr = ptr->right; + return ptr; +} + +// Here 'par' is pointer to parent Node and 'ptr' is +// pointer to current Node. +struct Node* case1(struct Node* root, struct Node* par, + struct Node* ptr) +{ + // If Node to be deleted is root + if (par == NULL) + root = NULL; + + // If Node to be deleted is left + // of its parent + else if (ptr == par->left) { + par->lthread = true; + par->left = ptr->left; + } + else { + par->rthread = true; + par->right = ptr->right; + } + + // Free memory and return new root + free(ptr); + return root; +} + +// Here 'par' is pointer to parent Node and 'ptr' is +// pointer to current Node. +struct Node* case2(struct Node* root, struct Node* par, + struct Node* ptr) +{ + struct Node* child; + + // Initialize child Node to be deleted has + // left child. + if (ptr->lthread == false) + child = ptr->left; + + // Node to be deleted has right child. + else + child = ptr->right; + + // Node to be deleted is root Node. + if (par == NULL) + root = child; + + // Node is left child of its parent. + else if (ptr == par->left) + par->left = child; + else + par->right = child; + + // Find successor and predecessor + Node* s = inSucc(ptr); + Node* p = inPred(ptr); + + // If ptr has left subtree. + if (ptr->lthread == false) + p->right = s; + + // If ptr has right subtree. + else { + if (ptr->rthread == false) + s->left = p; + } + + free(ptr); + return root; +} + +// Here 'par' is pointer to parent Node and 'ptr' is +// pointer to current Node. +struct Node* case3(struct Node* root, struct Node* par, + struct Node* ptr) +{ + // Find inorder successor and its parent. + struct Node* parsucc = ptr; + struct Node* succ = ptr->right; + + // Find leftmost child of successor + while (succ->lthread==false) { + parsucc = succ; + succ = succ->left; + } + + ptr->info = succ->info; + + if (succ->lthread == true && succ->rthread == true) + root = case1(root, parsucc, succ); + else + root = case2(root, parsucc, succ); + + return root; +} + +// Deletes a key from threaded BST with given root and +// returns new root of BST. +struct Node* deleteFromThreadedBst(struct Node* root, int target) +{ + // Initialize parent as NULL and + // Node as root. + struct Node *par = NULL, *ptr = root; + + // Set true if key is found + int found = 0; + + // Search key in BST : find Node and its + // parent. + while (ptr != NULL) { + if (target == ptr->info) { + found = 1; + break; + } + par = ptr; + if (target < ptr->info) { + if (ptr->lthread == false) + ptr = ptr->left; + else + break; + } + else { + if (ptr->rthread == false) + ptr = ptr->right; + else + break; + } + } + + if (found == 0) + printf("target not present in tree\n"); + + // Two Children + else if (ptr->lthread == false && ptr->rthread == false) + root = case3(root, par, ptr); + + // Only Left Child + else if (ptr->lthread == false) + root = case2(root, par, ptr); + + // Only Right Child + else if (ptr->rthread == false) + root = case2(root, par, ptr); + + // No child + else + root = case1(root, par, ptr); + + return root; +} + +// Driver Program +int main() +{ + struct Node* root = NULL , *temp = NULL; + + root = insert(root, 1); + root = insert(root, 3); + root = insert(root, 5); + root = insert(root, 7); + root = insert(root, 12); + root = insert(root, 2); + root = insert(root, 10); + root = insert(root, 6); + + temp = search(root , 5) ; + + if( temp ) cout<<"Element with value 5 found\n" ; + else cout<<"element doesn't exist in the given binary threaded tree\n" ; + + root = deleteFromThreadedBst(root, 6); + inorder(root); + + return 0; +} + +// Output for the above entry + +// Element with value 5 found +// 1 2 3 5 7 10 12 From 3233edea92bd3ddf3ae6573c466a216266885459 Mon Sep 17 00:00:00 2001 From: Shubham Tribedi Date: Sun, 10 Oct 2021 13:10:51 +0530 Subject: [PATCH 2/6] Update README.md --- .../Trees/Threaded Binary Tree/README.md | 74 ++++++++++--------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/Data Structures/Trees/Threaded Binary Tree/README.md b/Data Structures/Trees/Threaded Binary Tree/README.md index 8477ebb..64a1504 100644 --- a/Data Structures/Trees/Threaded Binary Tree/README.md +++ b/Data Structures/Trees/Threaded Binary Tree/README.md @@ -1,17 +1,19 @@ +**Threaded Binary Tree:** + The idea of threaded binary trees is to make inorder traversal faster and do it without stack and without recursion. A binary tree is made threaded by making all right child pointers that would normally be NULL point to the inorder successor of the node (if it exists). -There are two types of threaded binary trees. +**There are two types of threaded binary trees:** - Single Threaded: Where a NULL right pointers is made to point to the inorder successor (if successor exists) - Double Threaded: Where both left and right NULL pointers are made to point to inorder predecessor and inorder successor respectively. The predecessor threads are useful for reverse inorder traversal and postorder traversal. The threads are also useful for fast accessing ancestors of a node. -Single Threaded Binary Tree: Here only the right NULL pointer are made to point to inorder successor. +**Single Threaded Binary Tree:** Here only the right NULL pointer are made to point to inorder successor. -Double Threaded Binary Tree: Here both the right as well as the left NULL pointers are made to point inorder successor and inorder predecessor respectively. (here the left threads are helpful in reverse inorder traveral of the tree ) +**Double Threaded Binary Tree:** Here both the right as well as the left NULL pointers are made to point inorder successor and inorder predecessor respectively. (here the left threads are helpful in reverse inorder traveral of the tree ) -Structure of node in threaded binary tree: +**Structure of node in threaded binary tree:** A node in threaded binary tree has two additional attributes: @@ -20,64 +22,64 @@ A node in threaded binary tree has two additional attributes: Both new attributes are of type bolean. -Following is the node structure in a Single threaded binary tree and Double threaded binary tree: +**Following is the node structure in a Single threaded binary tree and Double threaded binary tree:** -// single threaded +// **single** threaded
-struct Node{ - int data ; - Node *left ; - Node *right ; - bool rightThread ; -} +struct Node{
+ Node *left ;
+ Node *right ;
+ bool rightThread ;
+}
-// double threaded +// **double** threaded
-struct Node{ - int data ; - Node *left ; - Node *right ; - bool leftThread ; - bool rightThread ; -} +struct Node{
+ int data ;
+ Node *left ;
+ Node *right ;
+ bool leftThread ;
+ bool rightThread ;
+}
-Significance of bool variable (leftThread and rightThread) in structure: +**Significance of bool variable (leftThread and rightThread) in structure:** If we have some address stored in some node to diffrentiate whether that address is of parent node or of child node we use leftThread and rightThread bool variables. -leftThread and rightThread bool variables stores whether left and right pointers point to child node or some ancestor node , if the bool variable is set to true that means pointer is pointing to child node and if it is set to 1 that means that pointer is pointing to parent node. +LeftThread and rightThread bool variables stores whether left and right pointers point to child node or some ancestor node , if the bool variable is set to true that means pointer is pointing to child node and if it is set to 1 that means that pointer is pointing to parent node. -for example: +**For example:** -let's us say for some node right pointer is pointing to some node and righThread is set to true, this means that it is pointing to it's children, but if in the same case if rightThread is set to false this means that it is pointing to it's parent node (and not child ). +Let's us say for some node right pointer is pointing to some node and righThread is set to true, this means that it is pointing to it's children, but if in the same case if rightThread is set to false this means that it is pointing to it's parent node (and not child ). -What happens with righmost and leftmost null nodes ? +**What happens with righmost and leftmost null nodes ?** When we create a threaded binary tree the left most and rightmost pointers do not have inorder predecessor or inorder successor so they are made to point to a dummy node as you can see in the image and leftThread of leftmost node and rightThread of rightmost node is set to false. -Operations in Threaded Binary Tree +**Operations in Threaded Binary Tree** + We can also perform various operations in a threaded binary tree like - -1.Insert -2.search -3.Delete +1.**Insert**
+2.**search**
+3.**Delete**
After performing the following operations we need to make sure that our new binary tree still follows all the conditions of a threaded binary tree and also these operations should be performed with least amount of space and time complexity possible. -Applications of Threaded Binary Tree: +**Applications of Threaded Binary Tree:** The idea of threaded binary trees is to make inorder traversal of the binary tree faster and do it without using any extra space, so sometimes in small systems where hardware is very limited we use threaded binary tree for better efficiency of the software in a limited hardware space. -Time and space complexity for operations +**Time and space complexity for operations** Time complexity for: -- For insertion : log(n) -- For deletion : log(n) -- For seaching : log(n) +- For insertion : log(n)
+- For deletion : log(n)
+- For seaching : log(n)
-Space complexity for insertion is O(1) , for deletion and searching we donot require any extra space. +**Space complexity** for insertion is O(1) , for deletion and searching we donot require any extra space. The time required for finding inorder predecessor or successor for a given node is O(1) provided we are on that node. -The Code for Threaded Binary Tree and all other Operations are given in Threaded_Binary_Tree_all.cpp \ No newline at end of file +**The Code for Threaded Binary Tree and all other Operations are given in Threaded_Binary_Tree_all.cpp** From f296d5acb1bd0811b2a6f3b1b7a072f4a55f1c32 Mon Sep 17 00:00:00 2001 From: Shubham Tribedi Date: Sun, 10 Oct 2021 13:19:50 +0530 Subject: [PATCH 3/6] Binary to Threaded Binary Tree Added --- .../Binary_to_threaded.cpp | 129 ++++++++++++++++++ .../E_Binary_to_threaded.cpp | 122 +++++++++++++++++ .../Trees/Threaded Binary Tree/README.md | 13 ++ 3 files changed, 264 insertions(+) create mode 100644 Data Structures/Trees/Threaded Binary Tree/Binary_to_threaded.cpp create mode 100644 Data Structures/Trees/Threaded Binary Tree/E_Binary_to_threaded.cpp diff --git a/Data Structures/Trees/Threaded Binary Tree/Binary_to_threaded.cpp b/Data Structures/Trees/Threaded Binary Tree/Binary_to_threaded.cpp new file mode 100644 index 0000000..a9620d8 --- /dev/null +++ b/Data Structures/Trees/Threaded Binary Tree/Binary_to_threaded.cpp @@ -0,0 +1,129 @@ +/* C++ program to convert a Binary Tree to Threaded Tree */ +#include +using namespace std; + +/* Structure of a node in threaded binary tree */ +struct Node { + int key; + Node *left, *right; + + // Used to indicate whether the right pointer is a normal + // right pointer or a pointer to inorder successor. + bool isThreaded; +}; + +// Helper function to put the Nodes in inorder into queue +void populateQueue(Node* root, std::queue* q) +{ + if (root == NULL) + return; + if (root->left) + populateQueue(root->left, q); + q->push(root); + if (root->right) + populateQueue(root->right, q); +} + +// Function to traverse queue, and make tree threaded +void createThreadedUtil(Node* root, std::queue* q) +{ + if (root == NULL) + return; + + if (root->left) + createThreadedUtil(root->left, q); + q->pop(); + + if (root->right) + createThreadedUtil(root->right, q); + + // If right pointer is NULL, link it to the + // inorder successor and set 'isThreaded' bit. + else { + root->right = q->front(); + root->isThreaded = true; + } +} + +// This function uses populateQueue() and +// createThreadedUtil() to convert a given binary tree +// to threaded tree. +void createThreaded(Node* root) +{ + // Create a queue to store inorder traversal + std::queue q; + + // Store inorder traversal in queue + populateQueue(root, &q); + + // Link NULL right pointers to inorder successor + createThreadedUtil(root, &q); +} + +// A utility function to find leftmost node in a binary +// tree rooted with 'root'. This function is used in inOrder() +Node* leftMost(Node* root) +{ + while (root != NULL && root->left != NULL) + root = root->left; + return root; +} + +// Function to do inorder traversal of a threaded binary tree +void inOrder(Node* root) +{ + if (root == NULL) + return; + + // Find the leftmost node in Binary Tree + Node* cur = leftMost(root); + + while (cur != NULL) { + cout << cur->key << " "; + + // If this Node is a thread Node, then go to + // inorder successor + if (cur->isThreaded) + cur = cur->right; + + else // Else go to the leftmost child in right subtree + cur = leftMost(cur->right); + } +} + +// A utility function to create a new node +Node* newNode(int key) +{ + Node* temp = new Node; + temp->left = temp->right = NULL; + temp->key = key; + return temp; +} + +// Driver program to test above functions +int main() +{ + /* 1 + / \ + 2 3 + / \ / \ + 4 5 6 7 */ + Node* root = newNode(1); + root->left = newNode(2); + root->right = newNode(3); + root->left->left = newNode(4); + root->left->right = newNode(5); + root->right->left = newNode(6); + root->right->right = newNode(7); + + createThreaded(root); + + cout << "Inorder traversal of created threaded tree is\n"; + inOrder(root); + return 0; +} + +// Output: + +// Inorder traversal of created threaded tree is +// 4 2 5 1 6 3 7 \ No newline at end of file diff --git a/Data Structures/Trees/Threaded Binary Tree/E_Binary_to_threaded.cpp b/Data Structures/Trees/Threaded Binary Tree/E_Binary_to_threaded.cpp new file mode 100644 index 0000000..1865683 --- /dev/null +++ b/Data Structures/Trees/Threaded Binary Tree/E_Binary_to_threaded.cpp @@ -0,0 +1,122 @@ +/* C++ program to convert a Binary Tree to + Threaded Tree */ +#include +using namespace std; + +/* Structure of a node in threaded binary tree */ +struct Node +{ + int key; + Node *left, *right; + + // Used to indicate whether the right pointer + // is a normal right pointer or a pointer + // to inorder successor. + bool isThreaded; +}; + +// Converts tree with given root to threaded +// binary tree. +// This function returns rightmost child of +// root. +Node *createThreaded(Node *root) +{ + // Base cases : Tree is empty or has single + // node + if (root == NULL) + return NULL; + if (root->left == NULL && + root->right == NULL) + return root; + + // Find predecessor if it exists + if (root->left != NULL) + { + // Find predecessor of root (Rightmost + // child in left subtree) + Node* l = createThreaded(root->left); + + // Link a thread from predecessor to + // root. + l->right = root; + l->isThreaded = true; + } + + // If current node is rightmost child + if (root->right == NULL) + return root; + + // Recur for right subtree. + return createThreaded(root->right); +} + +// A utility function to find leftmost node +// in a binary tree rooted with 'root'. +// This function is used in inOrder() +Node *leftMost(Node *root) +{ + while (root != NULL && root->left != NULL) + root = root->left; + return root; +} + +// Function to do inorder traversal of a threadded +// binary tree +void inOrder(Node *root) +{ + if (root == NULL) return; + + // Find the leftmost node in Binary Tree + Node *cur = leftMost(root); + + while (cur != NULL) + { + cout << cur->key << " "; + + // If this Node is a thread Node, then go to + // inorder successor + if (cur->isThreaded) + cur = cur->right; + + else // Else go to the leftmost child in right subtree + cur = leftMost(cur->right); + } +} + +// A utility function to create a new node +Node *newNode(int key) +{ + Node *temp = new Node; + temp->left = temp->right = NULL; + temp->key = key; + return temp; +} + +// Driver program to test above functions +int main() +{ + /* 1 + / \ + 2 3 + / \ / \ + 4 5 6 7 */ + Node *root = newNode(1); + root->left = newNode(2); + root->right = newNode(3); + root->left->left = newNode(4); + root->left->right = newNode(5); + root->right->left = newNode(6); + root->right->right = newNode(7); + + createThreaded(root); + + cout << "Inorder traversal of created " + "threaded tree is\n"; + inOrder(root); + return 0; +} + +// Output + +// Inorder traversal of created threaded tree is +// 4 2 5 1 6 3 7 \ No newline at end of file diff --git a/Data Structures/Trees/Threaded Binary Tree/README.md b/Data Structures/Trees/Threaded Binary Tree/README.md index 64a1504..7d4b081 100644 --- a/Data Structures/Trees/Threaded Binary Tree/README.md +++ b/Data Structures/Trees/Threaded Binary Tree/README.md @@ -83,3 +83,16 @@ Time complexity for: The time required for finding inorder predecessor or successor for a given node is O(1) provided we are on that node. **The Code for Threaded Binary Tree and all other Operations are given in Threaded_Binary_Tree_all.cpp** + +**Convert a Binary Tree to Threaded Binary Tree (Using Queue)** + +We basically need to set NULL right pointers to inorder successor. We first do an inorder traversal of the tree and store it in a queue (we can use a simple array also) so that the inorder successor becomes the next node. We again do an inorder traversal and whenever we find a node whose right is NULL, we take the front item from queue and make it the right of current node. We also set isThreaded to true to indicate that the right pointer is a threaded link. + +**The Code for conversion of a Binary Tree to Threaded Binary Tree (Using Queue) is given in Binary_to_threaded.cpp** + +**Convert a Binary Tree to Threaded Binary Tree (Efficient Method)** + +In this efficient case, a space-efficient solution is discussed that doesn’t require a queue. +The idea is based on the fact that we link from inorder predecessor to a node. We link those inorder predecessor which lie in subtree of node. So we find inorder predecessor of a node if its left is not NULL. Inorder predecessor of a node (whose left is NULL) is a rightmost node in the left child. Once we find the predecessor, we link a thread from it to the current node. This algorithm works in O(n) time complexity and O(1) space other than function call stack. + +**The Code for conversion of a Binary Tree to Threaded Binary Tree (Efficient Method) is given in E_Binary_to_threaded.cpp** \ No newline at end of file From e1dad4394a26561293ea933256cd2f724f869536 Mon Sep 17 00:00:00 2001 From: Shubham Tribedi Date: Mon, 18 Oct 2021 14:47:50 +0530 Subject: [PATCH 4/6] Update Binary_to_threaded.cpp Updated with only Required Imports --- .../Binary_to_threaded.cpp | 252 +++++++++--------- 1 file changed, 125 insertions(+), 127 deletions(-) diff --git a/Data Structures/Trees/Threaded Binary Tree/Binary_to_threaded.cpp b/Data Structures/Trees/Threaded Binary Tree/Binary_to_threaded.cpp index a9620d8..ebe4bff 100644 --- a/Data Structures/Trees/Threaded Binary Tree/Binary_to_threaded.cpp +++ b/Data Structures/Trees/Threaded Binary Tree/Binary_to_threaded.cpp @@ -1,129 +1,127 @@ -/* C++ program to convert a Binary Tree to Threaded Tree */ -#include -using namespace std; +/* C++ program to convert a Binary Tree to Threaded Tree */ +#include +#include +using namespace std; + /* Structure of a node in threaded binary tree */ -struct Node { - int key; - Node *left, *right; - - // Used to indicate whether the right pointer is a normal - // right pointer or a pointer to inorder successor. - bool isThreaded; -}; - -// Helper function to put the Nodes in inorder into queue -void populateQueue(Node* root, std::queue* q) -{ - if (root == NULL) - return; - if (root->left) - populateQueue(root->left, q); - q->push(root); - if (root->right) - populateQueue(root->right, q); -} - -// Function to traverse queue, and make tree threaded -void createThreadedUtil(Node* root, std::queue* q) -{ - if (root == NULL) - return; - - if (root->left) - createThreadedUtil(root->left, q); - q->pop(); - - if (root->right) - createThreadedUtil(root->right, q); - - // If right pointer is NULL, link it to the - // inorder successor and set 'isThreaded' bit. - else { - root->right = q->front(); - root->isThreaded = true; - } -} - -// This function uses populateQueue() and -// createThreadedUtil() to convert a given binary tree -// to threaded tree. -void createThreaded(Node* root) -{ - // Create a queue to store inorder traversal - std::queue q; - - // Store inorder traversal in queue - populateQueue(root, &q); - - // Link NULL right pointers to inorder successor - createThreadedUtil(root, &q); -} - -// A utility function to find leftmost node in a binary -// tree rooted with 'root'. This function is used in inOrder() -Node* leftMost(Node* root) -{ - while (root != NULL && root->left != NULL) - root = root->left; - return root; -} - -// Function to do inorder traversal of a threaded binary tree -void inOrder(Node* root) -{ - if (root == NULL) - return; - - // Find the leftmost node in Binary Tree - Node* cur = leftMost(root); - - while (cur != NULL) { - cout << cur->key << " "; - - // If this Node is a thread Node, then go to - // inorder successor - if (cur->isThreaded) - cur = cur->right; - - else // Else go to the leftmost child in right subtree - cur = leftMost(cur->right); - } -} - -// A utility function to create a new node -Node* newNode(int key) -{ - Node* temp = new Node; - temp->left = temp->right = NULL; - temp->key = key; - return temp; -} - -// Driver program to test above functions -int main() -{ - /* 1 - / \ - 2 3 - / \ / \ - 4 5 6 7 */ - Node* root = newNode(1); - root->left = newNode(2); - root->right = newNode(3); - root->left->left = newNode(4); - root->left->right = newNode(5); - root->right->left = newNode(6); - root->right->right = newNode(7); - - createThreaded(root); - - cout << "Inorder traversal of created threaded tree is\n"; - inOrder(root); - return 0; -} - -// Output: - -// Inorder traversal of created threaded tree is -// 4 2 5 1 6 3 7 \ No newline at end of file +struct Node +{ + int key; + Node *left, *right; + + // Used to indicate whether the right pointer is a normal + // right pointer or a pointer to inorder successor. + bool isThreaded; +}; + +// Helper function to put the Nodes in inorder into queue +void populateQueue(Node *root, std::queue *q) +{ + if (root == NULL) return; + if (root->left) + populateQueue(root->left, q); + q->push(root); + if (root->right) + populateQueue(root->right, q); +} + +// Function to traverse queue, and make tree threaded +void createThreadedUtil(Node *root, std::queue *q) +{ + if (root == NULL) return; + + if (root->left) + createThreadedUtil(root->left, q); + q->pop(); + + if (root->right) + createThreadedUtil(root->right, q); + + // If right pointer is NULL, link it to the + // inorder successor and set 'isThreaded' bit. + else + { + root->right = q->front(); + root->isThreaded = true; + } +} + +// This function uses populateQueue() and +// createThreadedUtil() to convert a given binary tree +// to threaded tree. +void createThreaded(Node *root) +{ + // Create a queue to store inorder traversal + std::queue q; + + // Store inorder traversal in queue + populateQueue(root, &q); + + // Link NULL right pointers to inorder successor + createThreadedUtil(root, &q); +} + +// A utility function to find leftmost node in a binary +// tree rooted with 'root'. This function is used in inOrder() +Node *leftMost(Node *root) +{ + while (root != NULL && root->left != NULL) + root = root->left; + return root; +} + +// Function to do inorder traversal of a threadded binary tree +void inOrder(Node *root) +{ + if (root == NULL) return; + + // Find the leftmost node in Binary Tree + Node *cur = leftMost(root); + + while (cur != NULL) + { + cout << cur->key << " "; + + // If this Node is a thread Node, then go to + // inorder successor + if (cur->isThreaded) + cur = cur->right; + + else // Else go to the leftmost child in right subtree + cur = leftMost(cur->right); + } +} + +// A utility function to create a new node +Node *newNode(int key) +{ + Node *temp = new Node; + temp->left = temp->right = NULL; + temp->key = key; + return temp; +} + +// Driver program to test above functions +int main() +{ + /* 1 + / \ + 2 3 + / \ / \ + 4 5 6 7 */ + Node *root = newNode(1); + root->left = newNode(2); + root->right = newNode(3); + root->left->left = newNode(4); + root->left->right = newNode(5); + root->right->left = newNode(6); + root->right->right = newNode(7); + + createThreaded(root); + + cout << "Inorder traversal of creeated threaded tree is +"; + inOrder(root); + return 0; +} From 0b161465f9e0b064b586cfabbd99ead7442d4e00 Mon Sep 17 00:00:00 2001 From: Shubham Tribedi Date: Mon, 18 Oct 2021 14:48:27 +0530 Subject: [PATCH 5/6] Update E_Binary_to_threaded.cpp --- .../Trees/Threaded Binary Tree/E_Binary_to_threaded.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Data Structures/Trees/Threaded Binary Tree/E_Binary_to_threaded.cpp b/Data Structures/Trees/Threaded Binary Tree/E_Binary_to_threaded.cpp index 1865683..30e7d28 100644 --- a/Data Structures/Trees/Threaded Binary Tree/E_Binary_to_threaded.cpp +++ b/Data Structures/Trees/Threaded Binary Tree/E_Binary_to_threaded.cpp @@ -1,6 +1,8 @@ /* C++ program to convert a Binary Tree to Threaded Tree */ -#include +#include +#include + using namespace std; /* Structure of a node in threaded binary tree */ @@ -119,4 +121,4 @@ int main() // Output // Inorder traversal of created threaded tree is -// 4 2 5 1 6 3 7 \ No newline at end of file +// 4 2 5 1 6 3 7 From 2129b8747654a948f508dba566aa01a661ae0410 Mon Sep 17 00:00:00 2001 From: Shubham Tribedi Date: Mon, 18 Oct 2021 14:50:13 +0530 Subject: [PATCH 6/6] Update Threaded_Binary_Tree_all.cpp Changed the imports to specific --- .../Threaded_Binary_Tree_all.cpp | 513 +++++++----------- 1 file changed, 191 insertions(+), 322 deletions(-) diff --git a/Data Structures/Trees/Threaded Binary Tree/Threaded_Binary_Tree_all.cpp b/Data Structures/Trees/Threaded Binary Tree/Threaded_Binary_Tree_all.cpp index c160481..4de81c0 100644 --- a/Data Structures/Trees/Threaded Binary Tree/Threaded_Binary_Tree_all.cpp +++ b/Data Structures/Trees/Threaded Binary Tree/Threaded_Binary_Tree_all.cpp @@ -1,338 +1,207 @@ -#include +#include +#include +#define MAX_VALUE 65536 using namespace std; - -struct Node { - struct Node *left, *right; - int info; - - // True if left pointer points to predecessor - // in Inorder Traversal - bool lthread; - - // True if right pointer points to predecessor - // in Inorder Traversal - bool rthread; +class N { //node declaration + public: + int k; + N *l, *r; + bool leftTh, rightTh; }; - -struct Node *search( struct Node *root , int key ){ - - Node *ptr = root ; - - - - while( ptr != nullptr ){ - - if( ptr->info == key ){ - // indicating that the element is found then - return ptr ; - }else if( ptr->info < key ){ - // moving to inorder predecessor of the current node - ptr = ptr->right ; - }else{ - // moving to inorder successor of the current node - ptr = ptr->left ; - } - - } - - // if element is not found then we can return nullptr indicating element not - // found in the given binary search tree - return nullptr ; - -} - -// Insert a Node in Binary Threaded Tree -struct Node* insert(struct Node* root, int ikey) -{ - // Searching for a Node with given value - Node* ptr = root; - Node* par = NULL; // Parent of key to be inserted - while (ptr != NULL) { - // If key already exists, return - if (ikey == (ptr->info)) { - printf("Duplicate Key !\n"); - return root; - } - - par = ptr; // Update parent pointer - - // Moving on left subtree. - if (ikey < ptr->info) { - if (ptr->lthread == false) - ptr = ptr->left; - else - break; - } - - // Moving on right subtree. - else { - if (ptr->rthread == false) - ptr = ptr->right; - else - break; - } +class ThreadedBinaryTree { + private: + N *root; + public: + ThreadedBinaryTree() { //constructor to initialize the variables + root= new N(); + root->r= root->l= root; + root->leftTh = true; + root->k = MAX_VALUE; } - - // Create a new Node - Node* tmp = new Node; - tmp->info = ikey; - tmp->lthread = true; - tmp->rthread = true; - - if (par == NULL) { - root = tmp; - tmp->left = NULL; - tmp->right = NULL; + void makeEmpty() { //clear tree + root= new N(); + root->r = root->l = root; + root->leftTh = true; + root->k = MAX_VALUE; } - else if (ikey < (par->info)) { - tmp->left = par->left; - tmp->right = par; - par->lthread = false; - par->left = tmp; - } - else { - tmp->left = par; - tmp->right = par->right; - par->rthread = false; - par->right = tmp; + void insert(int key) { + N *p = root; + for (;;) { + if (p->k< key) { / /move to right thread + if (p->rightTh) + break; + p = p->r; + } else if (p->k > key) { // move to left thread + if (p->leftTh) + break; + p = p->l; + } else { + return; + } + } + N *temp = new N(); + temp->k = key; + temp->rightTh= temp->leftTh= true; + if (p->k < key) { + temp->r = p->r; + temp->l= p; + p->r = temp; + p->rightTh= false; + } else { + temp->r = p; + temp->l = p->l; + p->l = temp; + p->leftTh = false; + } } - - return root; -} - -// Returns inorder successor using left -// and right children (Used in deletion) -struct Node* inSucc(struct Node* ptr) -{ - if (ptr->rthread == true) - return ptr->right; - - ptr = ptr->right; - while (ptr->lthread == false) - ptr = ptr->left; - - return ptr; -} - -// Returns inorder successor using rthread -// (Used in inorder) -struct Node* inorderSuccessor(struct Node* ptr) -{ - // If rthread is set, we can quickly find - if (ptr->rthread == true) - return ptr->right; - - // Else return leftmost child of right subtree - ptr = ptr->right; - while (ptr->lthread == false) - ptr = ptr->left; - return ptr; -} - -// Printing the threaded tree -void inorder(struct Node* root) -{ - if (root == NULL) - printf("Tree is empty"); - - // Reach leftmost Node - struct Node* ptr = root; - while (ptr->lthread == false) - ptr = ptr->left; - - // One by one print successors - while (ptr != NULL) { - printf("%d ", ptr->info); - ptr = inorderSuccessor(ptr); + bool search(int key) { + N *temp = root->l; + for (;;) { + if (temp->k < key) { //search in left thread + if (temp->rightTh) + return false; + temp = temp->r; + } else if (temp->k > key) { //search in right thread + if (temp->leftTh) + return false; + temp = temp->l; + } else { + return true; + } } } - -struct Node* inPred(struct Node* ptr) -{ - if (ptr->lthread == true) - return ptr->left; - - ptr = ptr->left; - while (ptr->rthread == false) - ptr = ptr->right; - return ptr; -} - -// Here 'par' is pointer to parent Node and 'ptr' is -// pointer to current Node. -struct Node* case1(struct Node* root, struct Node* par, - struct Node* ptr) -{ - // If Node to be deleted is root - if (par == NULL) - root = NULL; - - // If Node to be deleted is left - // of its parent - else if (ptr == par->left) { - par->lthread = true; - par->left = ptr->left; +void Delete(int key) { + N *dest = root->l, *p = root; + for (;;) { //find Node and its parent. + if (dest->k < key) { + if (dest->rightTh) + return; + p = dest; + dest = dest->r; + } else if (dest->k > key) { + if (dest->leftTh) + return; + p = dest; + dest = dest->l; + } else { + break; + } } - else { - par->rthread = true; - par->right = ptr->right; + N *target = dest; + if (!dest->rightTh && !dest->leftTh) { + p = dest; //has two children + target = dest->l; //largest node at left child + while (!target->rightTh) { + p = target; + target = target->r; + } + dest->k= target->k; //replace mode } - - // Free memory and return new root - free(ptr); - return root; -} - -// Here 'par' is pointer to parent Node and 'ptr' is -// pointer to current Node. -struct Node* case2(struct Node* root, struct Node* par, - struct Node* ptr) -{ - struct Node* child; - - // Initialize child Node to be deleted has - // left child. - if (ptr->lthread == false) - child = ptr->left; - - // Node to be deleted has right child. - else - child = ptr->right; - - // Node to be deleted is root Node. - if (par == NULL) - root = child; - - // Node is left child of its parent. - else if (ptr == par->left) - par->left = child; - else - par->right = child; - - // Find successor and predecessor - Node* s = inSucc(ptr); - Node* p = inPred(ptr); - - // If ptr has left subtree. - if (ptr->lthread == false) - p->right = s; - - // If ptr has right subtree. - else { - if (ptr->rthread == false) - s->left = p; + if (p->k >= target->k) { //only left child + if (target->rightTh && target->leftTh) { + p->l = target->l; + p->leftTh = true; + } else if (target->rightTh) { + N*largest = target->l; + while (!largest->rightTh) { + largest = largest->r; + } + largest->r = p; + p->l= target->l; + } else { + N *smallest = target->r; + while (!smallest->leftTh) { + smallest = smallest->l; + } + smallest->l = target->l; + p->l = target->r; + } + } else {//only right child + if (target->rightTh && target->leftTh) { + p->r= target->r; + p->rightTh = true; + } else if (target->rightTh) { + N *largest = target->l; + while (!largest->rightTh) { + largest = largest->r; + } + largest->r= target->r; + p->r = target->l; + } else { + N *smallest = target->r; + while (!smallest->leftTh) { + smallest = smallest->l; + } + smallest->l= p; + p->r= target->r; + } } - - free(ptr); - return root; } - -// Here 'par' is pointer to parent Node and 'ptr' is -// pointer to current Node. -struct Node* case3(struct Node* root, struct Node* par, - struct Node* ptr) -{ - // Find inorder successor and its parent. - struct Node* parsucc = ptr; - struct Node* succ = ptr->right; - - // Find leftmost child of successor - while (succ->lthread==false) { - parsucc = succ; - succ = succ->left; +void displayTree() { //print the tree + N *temp = root, *p; + for (;;) { + p = temp; + temp = temp->r; + if (!p->rightTh) { + while (!temp->leftTh) { + temp = temp->l; + } + } + if (temp == root) + break; + cout<k<<" "; } - - ptr->info = succ->info; - - if (succ->lthread == true && succ->rthread == true) - root = case1(root, parsucc, succ); - else - root = case2(root, parsucc, succ); - - return root; + cout<info) { - found = 1; - break; - } - par = ptr; - if (target < ptr->info) { - if (ptr->lthread == false) - ptr = ptr->left; - else - break; - } - else { - if (ptr->rthread == false) - ptr = ptr->right; - else - break; - } +}; +int main() { + ThreadedBinaryTree tbt; + cout<<"ThreadedBinaryTree\n"; + char ch; + int c, v; + while(1) { + cout<<"1. Insert "<>c; + //perform switch operation + switch (c) { + case 1 : + cout<<"Enter integer element to insert: "; + cin>>v; + tbt.insert(v); + break; + case 2 : + cout<<"Enter integer element to delete: "; + cin>>v; + tbt.Delete(v); + break; + case 3 : + cout<<"Enter integer element to search: "; + cin>>v; + if (tbt.search(v) == true) + cout<<"Element "<lthread == false && ptr->rthread == false) - root = case3(root, par, ptr); - - // Only Left Child - else if (ptr->lthread == false) - root = case2(root, par, ptr); - - // Only Right Child - else if (ptr->rthread == false) - root = case2(root, par, ptr); - - // No child - else - root = case1(root, par, ptr); - - return root; -} - -// Driver Program -int main() -{ - struct Node* root = NULL , *temp = NULL; - - root = insert(root, 1); - root = insert(root, 3); - root = insert(root, 5); - root = insert(root, 7); - root = insert(root, 12); - root = insert(root, 2); - root = insert(root, 10); - root = insert(root, 6); - - temp = search(root , 5) ; - - if( temp ) cout<<"Element with value 5 found\n" ; - else cout<<"element doesn't exist in the given binary threaded tree\n" ; - - root = deleteFromThreadedBst(root, 6); - inorder(root); - + cout<<"\n"; return 0; } - -// Output for the above entry - -// Element with value 5 found -// 1 2 3 5 7 10 12