Converting a Binary Tree to Double Threaded Binary Tree? - c++

I could not find anything on search to satisfy my question, if it exists, I'm sorry!
I am working on a college assignment about threaded binary trees. I.e. various kinds of traversals - inorder, postorder and preorder on double TBT.
This is the TBTNode struct:
struct TBTNode {
TBTNode *left, *right, *parent;
char data;
bool left_normal, right_normal;
TBTNode(char d) {
data = d;
left = NULL;
right = NULL;
parent = NULL;
left_normal = true;
right_normal = true;
}
};
As you can see, there is not much distinction between a Binary Tree node and a TBT node, except that the node's properties, viz. {left,right}_normal are set to true when required.
To create the tree, I have this:
class TBT {
TBTNode *root;
public:
TBT() {
root = new TBTNode(0);
root->right = root;
root->right_normal = true;
cout << "Root:" ;
root->left = create();
if(root->left)
root->left_normal = true;
}
TBTNode* create();
};
TBTNode* TBT::create() {
char data;
TBTNode *node = NULL;
cout << endl << "Enter data (0 to quit): ";
cin >> data;
if(data == '0')
return NULL;
node = new TBTNode(data);
cout << endl << "Enter left child of " << data;
node->left = create();
if(node->left)
node->left->parent = node;
else {
node->left = root;
node->right = node->parent;
node->left_normal = node->right_normal = false;
}
cout << endl << "Enter right child of " << data;
node->right = create();
if(node->right)
node->right->parent = node;
else {
node->left = node;
node->right = node->parent->parent;
node->left_normal = node->right_normal = false;
}
return node;
}
After the tree gets recursively created using the above code, I want to convert it into a double threaded binary tree. I know the concept that left child is linked to the child's inorder predecessor and right to inorder successor, but I am unable to create an algorithm. Can someone help me?

I found the solution myself. First traverse the tree in inorder and add nodes to an array as you go on. Then process the array to link threads, because for a given element x in the array, the one previous to x will be inorder predecessor and one after x will be inorder successor. For the first and last element, special checks are made to link them to the head node (not root).
Parent link isn't needed, and it's removed.
Code is as follows:
class TBT {
TBTNode *root;
void createInorderArray(TBTNode *T);
TBTNode **array;
unsigned array_size;
public:
TBT();
TBTNode* create();
void inorder();
void preorder();
};
TBT::TBT() {
root = new TBTNode(0);
root->right = root;
root->right_normal = true;
cout << "Root:" ;
root->left = create();
if(!root->left) {
root->left_normal = false;
root->left = root;
}
array = NULL;
array_size = 0;
createInorderArray(root->left);
for(unsigned i = 0; i < array_size; i++) {
if(!array[i]->left) {
array[i]->left = i == 0 ? root : array[i-1];
array[i]->left_normal = false;
}
if(!array[i]->right) {
array[i]->right_normal = false;
array[i]->right = i == (array_size - 1) ? root : array[i+1];
}
}
free(array);
array_size = 0;
}
void TBT::createInorderArray(TBTNode *T) {
if(!T)
return;
createInorderArray(T->left);
array = (TBTNode**) realloc(array, sizeof(TBTNode**) * ++array_size);
array[array_size-1] = T;
createInorderArray(T->right);
}

Related

To print the entire sub tree of a given tree recursively

I know how to print the left and right view of a binary tree, but I want to print the entire left subtree of a given tree recursively. So, below is the code I use, and though I am getting the desired output, I feel this is not the proper approach. Is there any other way to achieve the same result without setting the root node's right child to nullptr?
#include<iostream>
using namespace std;
class node
{
public:
int data;
node *lchild;
node *rchild;
};
node *CreateNode(int data)
{
node *NewNode = new node();
NewNode->data = data;
NewNode->lchild = nullptr;
NewNode->rchild = nullptr;
return NewNode;
}
void printEntireTree(node *root)
{
if (root == nullptr)
return;
else
{
cout << root->data<<endl;
printEntireTree(root->lchild);
printEntireTree(root->rchild);
}
}
int main()
{
node *root = CreateNode(3);
root->lchild = CreateNode(1);
root->rchild = CreateNode(4);
root->lchild->rchild = CreateNode(2);
root->lchild->lchild = CreateNode(7);
root->lchild->lchild->lchild = CreateNode(8);
root->lchild->lchild->rchild = CreateNode(9);
root->rchild->lchild = CreateNode(5);
cout << "to print entire left sub tree" << endl;
node *temp = root->rchild;
root->rchild = nullptr;
printEntireTree(root);
root->rchild = temp;
temp = root->lchild;
cout << "entire right sub tree is" << endl;
root->lchild = nullptr;
printEntireTree(root);
root->lchild = temp;
}
#include<iostream>
using namespace std;
class node
{
public:
int data;
node *lchild;
node *rchild;
};
node *CreateNode(int data)
{
node *NewNode = new node();
NewNode->data = data;
NewNode->lchild = nullptr;
NewNode->rchild = nullptr;
return NewNode;
}
void printEntireTree(node *root, node *ro2)
{
if(root== ro2->lchild || root== ro2->rchild)
{
cout << ro2->data<<endl;
}
if (root == nullptr)
return;
else
{
cout << root->data<<endl;
printEntireTree(root->lchild, ro2);
printEntireTree(root->rchild, ro2);
}
}
int main()
{
node *root = CreateNode(3);
root->lchild = CreateNode(1);
root->rchild = CreateNode(4);
root->lchild->rchild = CreateNode(2);
root->lchild->lchild = CreateNode(7);
root->lchild->lchild->lchild = CreateNode(8);
root->lchild->lchild->rchild = CreateNode(9);
root->rchild->lchild = CreateNode(5);
cout << "to print entire left sub tree" << endl;
printEntireTree(root->lchild, root);
cout << "entire right sub tree is" << endl;
printEntireTree(root->rchild, root);
}

How to keep track of layers when traversing a binary tree?

If I need to print out each elements of a binary tree constructed with the struct below. How could I keep track of which layer of elements I am printing?
struct for a binary tree node
For example:
any binary tree
Expected output:
layer 0: 12
layer -1: 28 19
layer -2: 94 32
layer -3: 65 18 72
Solution using queue based on GeeksForGeeks
#include <iostream>
#include <queue>
using namespace std;
// A Binary Tree Node
struct node
{
struct node *left;
int data;
struct node *right;
};
// Iterative method to do level order traversal
// line by line
void printLevelOrder(node *root)
{
// Base Case
if (root == NULL)
return;
// Create an empty queue for level order tarversal
queue<node *> q;
// Enqueue Root and initialize height
q.push(root);
int i = 0;
while (q.empty() == false)
{
cout << "layer " << i << ": ";
// nodeCount (queue size) indicates number
// of nodes at current lelvel.
int nodeCount = q.size();
// Dequeue all nodes of current level and
// Enqueue all nodes of next level
while (nodeCount > 0)
{
node *node = q.front();
cout << node->data << " ";
q.pop();
if (node->left != NULL)
q.push(node->left);
if (node->right != NULL)
q.push(node->right);
nodeCount--;
}
cout << endl;
--i;
}
}
// Utility function to create a new tree node
node *newNode(int data)
{
node *temp = new node;
temp->data = data;
temp->left = NULL;
temp->right = NULL;
return temp;
}
// Driver program to test above functions
int main()
{
// Create binary tree
node *root = newNode(12);
root->left = newNode(28);
root->right = newNode(19);
root->left->left = newNode(94);
root->left->left->left = newNode(65);
root->left->left->right = newNode(18);
root->right->left = newNode(32);
root->right->left->right = newNode(72);
printLevelOrder(root);
return 0;
}
Solution using recursive function and helper function based on CrazyForCode:
#include <iostream>
using namespace std;
struct node
{
int data;
struct node *left;
struct node *right;
};
void printLevel(node *, int);
int height(struct node *node);
/* Function to print level order traversal a tree*/
void printLevelOrder(struct node *root)
{
int h = height(root);
int i;
for (i = 1; i <= h; i++){
printf("layer %d: ",i*-1+1);
printLevel(root, i);
cout << endl;
}
}
/* Print nodes at a given level */
void printLevel(struct node *root, int level)
{
if (root == NULL)
return;
if (level == 1)
{
printf("%d ", root->data);
}
else if (level > 1)
{
printLevel(root->left, level - 1);
printLevel(root->right, level - 1);
}
}
/* Compute the "height" of a tree */
int height(struct node *node)
{
if (node == NULL)
return 0;
else
{
int lheight = height(node->left);
int rheight = height(node->right);
if (lheight > rheight)
return (lheight + 1);
else
return (rheight + 1);
}
}
node *newNode(int data)
{
node *temp = new node;
temp->data = data;
temp->left = NULL;
temp->right = NULL;
return temp;
}
int main()
{
// Create binary tree
node *root = newNode(12);
root->left = newNode(28);
root->right = newNode(19);
root->left->left = newNode(94);
root->left->left->left = newNode(65);
root->left->left->right = newNode(18);
root->right->left = newNode(32);
root->right->left->right = newNode(72);
printLevelOrder(root);
return 0;
}

Binary tree class implematation

I have the following code. It creates a binary tree class. The functions are insert(), pre_order(), post_order(), in_order(). But when I debug it I get zeros values. Also I insert 9 values but only have 7 zeros. Why I did wrong?
#include <iostream>
using namespace std;
//Begin the construction of the BINARY TREE
struct tree_node {
tree_node *left;
tree_node *right;
int data;
};
//Declaring the class
class bst {
tree_node *root; //creating the root of the binary tree
public:
bst() {
root = NULL; //intialize the default construction, set the root to NULL
}
int is_empty() { //check for empty graph
return (root == NULL);
}
//Manipulating the Binary Tree
void insert(int item);
void remove_it(int value); //difficult implementation
//Graph Traversal of Binary Tree
void in_order_trav();
void in_order(tree_node *);
void pre_order_trav();
void pre_order(tree_node *);
void post_order_trav();
void post_order(tree_node *);
};
void bst::insert(int item) {
tree_node *p = new tree_node;
tree_node *parent;
p->left = NULL;
p->right = NULL;
parent = NULL;
if (is_empty()) {
root = p;
}
else {
tree_node *ptr;
ptr = root;
while (ptr != NULL) {
parent = ptr;
if (item > ptr->data)
ptr = ptr->right;
else
ptr = ptr->left;
}
if (item < parent->data)
parent->left = p;
else
parent->right = p;
}
}
/*************In Order Traversal*****************************/
// Begin
void bst::in_order_trav() {
in_order(root);
}
void bst::in_order(tree_node *ptr) {
if (ptr!=NULL) {
in_order(ptr->left);
cout << " " << ptr->data << " ";
in_order(ptr->right);
}
}
// End
/***********************************************************/
/*************Pre Order Traversal*****************************/
// Begin
void bst::pre_order_trav() {
pre_order(root);
}
void bst::pre_order(tree_node *ptr) {
if (ptr!=NULL) {
cout << " " << ptr->data << " ";
pre_order(ptr->left);
pre_order(ptr->right);
}
}
// End
/***********************************************************/
/*************Post Order Traversal*****************************/
// Begin
void bst::post_order_trav() {
post_order(root);
}
void bst::post_order(tree_node *ptr) {
if(ptr!=NULL) {
post_order(ptr->left);
post_order(ptr->right);
cout << " " << ptr->data << " ";
}
}
// End
/***********************************************************/
int main() {
bst bin_tree; //create the Binary Tree
bin_tree.insert(20);
bin_tree.insert(30);
bin_tree.insert(52);
bin_tree.insert(254);
bin_tree.insert(2);
bin_tree.insert(24);
bin_tree.insert(25);
bin_tree.insert(42);
bin_tree.insert(59);
bin_tree.in_order_trav(); //in order traversal
bin_tree.pre_order_trav(); //pre order traversal
bin_tree.post_order_trav(); //post order traversal
}
The node value should be initialized(p->data = item) at function insert() as below
void bst::insert(int item) {
tree_node *p = new tree_node;
tree_node *parent;
p->left = NULL;
p->right = NULL;
p->data = item;
parent = NULL;
... ...
}
Ok the solution is silly! -.-
I forgot to add that line in insert routine!
p->data = item;

Insert values in Binary Search Trees

I was trying to write a method which set values in a binary search tree. I have implemented a simple technique of recursion to add nodes in the tree. But when I input the values and ran the code I got segmentation fault:
struct Node
{
int data;
Node* leftN;
Node* rightN;
};
typedef Node* Node_ptr;
Node_ptr head;
//INSERT_VALUE FUNCTION
Node* new_node(int key)
{
Node* leaf = new Node;
leaf->data = key;
leaf->leftN = NULL;
leaf->rightN = NULL;
}
Node* insert_value(Node_ptr leaf, int key)
{
if(leaf == NULL)
return(new_node(key));
else
{
if(key <= leaf->data)
leaf->leftN = insert_value(leaf->leftN, key);
else
leaf->rightN = insert_value(leaf->rightN, key);
return(leaf);
}
}
//PRINT FUNCTION
void printTree(Node_ptr leaf)
{
if(leaf == NULL)
return;
printTree(leaf->leftN);
cout << "Data element: " << leaf->data << endl;
printTree(leaf->rightN);
}
//MAIN
int main()
{
Node_ptr root = NULL;
Node_ptr tail;
int i;
int x;
//initialize values
for(i = 0; i < 20; i++)
{
x = rand() % 1000 + 1;
tail = insert_value(root, x);
root = head;
}
root = head;
printTree(root);
root = head;
cout << "Head Node: " << root->data << endl;
return 0;
}
You are getting a segmentation fault because you never set the head, there for when you get to the line
cout << "Head Node: " << root->data << endl;
Your root value will be NULL, (since it was set to by head, which is NULL).
A "root" (or "head") node is typically a special case scenario, you should check to see if that node has been constructed at the top of insert_value, and if not, then you assign the node node to it.
Also, your code has in error in it as new_node does not return a value.

Binary Search Trees C++

I was trying to implement a simple Binary Search Tree for practice. I tried to just add values and print the values in the nodes. However, I am not getting the proper ascending order of values in the nodes. Here is what I have:
struct Node
{
int data;
Node* leftN;
Node* rightN;
};
typedef Node* Node_ptr;
Node_ptr head;
//INSERT_VALUE FUNCTION
Node* insert_value(Node_ptr leaf, int key)
{
//Root case when there is no set value yet
if(leaf == NULL)
{
leaf = new Node;
head = leaf;
cout << "Make the first node" << endl;
leaf->data = key;
leaf->leftN = NULL;
leaf->rightN = NULL;
return leaf;
}
//Left child Node
if(key < leaf->data)
{
//Search for a spot in the tree to add a Node (left value < root value < right value)
//This is only true for the left child Node
if(leaf->leftN != NULL)
insert_value(leaf, key);
//We have found a spot in the tree to add a new Node and add the value of key
else
{
cout << "Insert-left" << endl;
leaf->leftN = new Node;
leaf = leaf->leftN;
leaf->data = key;
leaf->leftN = NULL;
leaf->rightN = NULL;
return leaf;
}
}
//Right child Node
else if(key >= leaf->data)
{
//Search for a spot to add a new Node in the tree (only amongst the right child Nodes)
if(leaf->rightN != NULL)
insert_value(leaf, key);
//Once we have found a spot to add a new Node, append the new Node
else
{
cout << "Insert-right" << endl;
leaf->rightN = new Node;
leaf = leaf->rightN;
leaf->data = key;
leaf->leftN = NULL;
leaf->rightN = NULL;
return leaf;
}
}
}
//PRINT FUNCTION
void printTree(Node_ptr leaf)
{
if(leaf == NULL)
return;
printTree(leaf->leftN);
cout << "Data element: " << leaf->data << endl;
printTree(leaf->rightN);
}
//MAIN
int main()
{
Node_ptr root = NULL;
int i;
//initialize values
for(i = 1; i < 12; i+=2)
root = insert_value(root, i);
root = head;
for(i = 0; i < 11; i+=2)
root = insert_value(root, i);
root = head;
printTree(root);
root = head;
cout << "Head Node: " << root->data << endl;
return 0;
}
When I printed the results, this is what I got:
0, 2, 4, 6, 8, 10, 1, 3, 5, 7, 9, 11 and the value of the head node is 1
Because you are calling the insertion as:
root = insert_value(root, i);
the location at which you insert is always using a subtree starting at the last insertion. Except the time that you re-start to add the odd numbers, when you start inserting at the head.
If you create a class BinarySearchTree that contains a head pointer, and an insert method taking an int value that calls Node::insert( head, value ), then you can just call insert on that class, without passing it a node, and it can always see to it that the insertions use the root of the tree for the start of the recursion.
Just me, but I would have a constructor for Node that takes an int and initializes the pointers to NULL. That way you don't have to do that in the insert method.
In the leaf->node? != NULL case, I think instead of calling
insert_value(leaf, key);
you want to say
leaf->node? = insert_value(leaf->node?, key)
where ? is either L or R, of course.
Something you might consider is adding a comment to the method like so:
// Adds the given key to the (sub-)tree rooted at node* then returns the new root
// of that (sub-)tree.
node *insert_value_and_return_root(node *root, int value) { ... }