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..ebe4bff --- /dev/null +++ b/Data Structures/Trees/Threaded Binary Tree/Binary_to_threaded.cpp @@ -0,0 +1,127 @@ + +/* 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 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; +} 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..30e7d28 --- /dev/null +++ b/Data Structures/Trees/Threaded Binary Tree/E_Binary_to_threaded.cpp @@ -0,0 +1,124 @@ +/* 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; +}; + +// 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 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..7d4b081 --- /dev/null +++ b/Data Structures/Trees/Threaded Binary Tree/README.md @@ -0,0 +1,98 @@ +**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:** + +- 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{
+ 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** + +**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 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..4de81c0 --- /dev/null +++ b/Data Structures/Trees/Threaded Binary Tree/Threaded_Binary_Tree_all.cpp @@ -0,0 +1,207 @@ +#include +#include +#define MAX_VALUE 65536 +using namespace std; +class N { //node declaration + public: + int k; + N *l, *r; + bool leftTh, rightTh; +}; +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; + } + void makeEmpty() { //clear tree + root= new N(); + root->r = root->l = root; + root->leftTh = true; + root->k = MAX_VALUE; + } + 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; + } + } + 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; + } + } +} +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; + } + } + 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 + } + 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; + } + } +} +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<<" "; + } + cout<>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 "<