Why my Preoder, Inorder and Postorder functions are not working - binary-tree

#include <stdio.h>
#include <stdlib.h>
Node Creation
This structure creates the struct node data type
struct node
{
int data;
struct node *left, *right;
} * newnode;
Create Function
create() - It first allocates the memory required for the node. When user enters the data, it recursively calls itself to create its child node, and this process goes on. When the user enters -1, it terminates the recursion and goes back from where it is called.
struct node *create()
{
int x;
newnode = (struct node *)malloc(sizeof(struct node));
newnode->left = 0;
newnode->right = 0;
printf("Enter data(-1 for no node)\n");
scanf("%d", &x);
if (x == -1)
return 0;
newnode->data = x;
printf("Enter left child of %d\n", x);
newnode->left = create();
printf("Enter right child of %d\n", x);
newnode->right = create();
return newnode;
}
Preorder
preorder(struct node *root) - This function displays the data of the tree in preorder manner
void preorder(struct node *root)
{
if (root == 0)
return;
printf("%d\n", root->data);
preorder(root->left);
preorder(root->right);
}
Inorder
inorder(struct node *root) - This function displays the data of the tree in inorder manner
void inorder(struct node *root)
{
if (root == 0)
return;
inorder(root->left);
printf("%d\n", root->data);
inorder(root->right);
}
Postorder
Postorder(struct node *root) - This function displays the data of the tree in postorder manner
void postorder(struct node *root)
{
if (root == 0)
return;
postorder(root->left);
postorder(root->right);
printf("%d\n", root->data);
}
Main Function
Main function asks the user to create a tree and then traverse it according to the choice entered by the user. The problem is that preorder, inorder and postorder are not giving the required output, and result in an infinite loop after execution.
void main()
{
struct node *root;
root = 0;
int choice = 3, opt = 1;
while (opt)
{
printf("Select\n 1-for creation\n 2-for preorder\n 3-for inorder\n 4-for postorder\n");
scanf("%d", &choice);
switch (choice)
{
case 1:
root = create();
break;
case 2:
printf("Preorder is: ");
preorder(root);
break;
case 3:
printf("Inorder is: ");
inorder(root);
break;
case 4:
printf("Postorder is: ");
postorder(root);
break;
default:
printf("Invalid choice");
break;
}
printf("Wanna continue \n1-for yes\n0-for no\n");
scanf("%d", &opt);
}
}

There is no bug with any of the traversal functions you've provided.
No design or implementation problem with create () function either.
The trouble lies in the global struct node pointer newnode declared with the structure's definition.
Because each recursive call to create () is basically using the "same" newnode pointer, the tree is never really built in the way we want it to.
Let's try to dry run the create () function.
Let's say we want a tree like this:
1
/ \
2 3
create () is first called from main.
The memory is allocated using malloc () function and the address of the memory is stored in newnode.
Set it's attributes, left and right.
Ask for data and put it into data attribute, if data == -1 is true, return 0.
Up until this point, this is the state:
newnode -> 1
/ \
Null Null
create () is recursively called to build the left subtree.
The memory is allocated for newnode using malloc () and the address of the memory is stored in newnode. Note that this operation has basically "over-wrote" the address previously stored in newnode (because newnode is a global variable)
Then again, the user will be prompted for the data and its attributes will be set.
Therefore, the tree has now become:
newnode -> 2
/ \
Null Null
The struct node to which newnode was previously pointing is now lost (because of loss of its address)
Similarly, when the recursive call for the right subtree is made, then, the following will be observed:
newnode -> 3
/ \
Null Null
Considering the same scenario for the rest of the recursive calls made, it is clear that in the end, the tree we were expecting wasn't built and the reason is the global variable newnode, the constant allocation of memory and over-writing the address in newnode led to memory leakage only.
The reason infinite recursion was found is that, during multiple recursive calls, the left or right pointer of newnode was made to point to newnode itself, leading to a cycle. This node can be found by closely tracking the data of newnode during the recursive calls.
Hence, remove the declaration of newnode pointer from the structure declaration and modify the following statement in create () function:
newnode = (struct node *)malloc(sizeof(struct node));
to this:
struct node * newnode = (struct node *)malloc(sizeof(struct node));
And
struct node
{
int data;
struct node *left, *right;
};
is all what's needed.
In this way, each recursive call to create () function will have its own local pointer variable newnode and there will be no overwriting, no leakage, no cycle, no infinite recursion.

Related

Tree and graphs problems in Julia using struct data types, pointers and this

I want to write solve some graph/trees problems using Julia language.
Here is some good example. In C it was done this way:
Recursive C program for level order traversal of Binary Tree
#include <stdio.h>
#include <stdlib.h>
/* A binary tree node has data, pointer to left child
and a pointer to right child */
struct node
{
int data;
struct node *left, *right;
};
/* Function prototypes */
void printGivenLevel(struct node* root, int level);
int height(struct node* node);
struct node* newNode(int data);
/* 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++)
printGivenLevel(root, i);
}
/* Print nodes at a given level */
void printGivenLevel(struct node* root, int level)
{
if (root == NULL)
return;
if (level == 1)
printf("%d ", root->data);
else if (level > 1)
{
printGivenLevel(root->left, level-1);
printGivenLevel(root->right, level-1);
}
}
/* Compute the "height" of a tree -- the number of
nodes along the longest path from the root node
down to the farthest leaf node.*/
int height(struct node* node)
{
if (node==NULL)
return 0;
else
{
/* compute the height of each subtree */
int lheight = height(node->left);
int rheight = height(node->right);
/* use the larger one */
if (lheight > rheight)
return(lheight+1);
else return(rheight+1);
}
}
/* Helper function that allocates a new node with the
given data and NULL left and right pointers. */
struct node* newNode(int data)
{
struct node* node = (struct node*)
malloc(sizeof(struct node));
node->data = data;
node->left = NULL;
node->right = NULL;
return(node);
}
/* Driver program to test above functions*/
int main()
{
struct node *root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(4);
root->left->right = newNode(5);
printf("Level Order traversal of binary tree is \n");
printLevelOrder(root);
return 0;
}
I have tried to do it in Julia in similar way, but there are some problems, especially with accessing to struct elements.(like node->right and node->left).
Or some way to create Self-referential struct and function to allocate nodes.
struct node
data::Int
left::Ptr{node}
right::Ptr{node}
end
# Compute the "height" of a tree -- the number of
# nodes along the longest path from the root node
# down to the farthest leaf node.
function height = (node::Ptr{node})
if node === nothing
return 0
else
# compute the height of each subtree
lheight = height(node->left)
rheight = height(node->right)
# use the larger one
if lheight > rheight
return lheight+1
else return rheight+1
end
end
end
From what I've seen trying to recreate a problem solution in C way isn't the way, however this struct type should be useful. I just have to know how to create self-referent struct, how to allocate elements in this node and how to get them.
First of all, I would strongly suggest reading through https://docs.julialang.org/en/v1/, since Julia is different from C in quite a few ways. There are multiple things to point out here:
Per default structs in Julia are immutable, which means you cannot modify fields after it is created. It is also always passed by copy instead of by reference, since it doesn't have a specific memory address and usually gets allocated on the stack. This actually has multiple benefits for the compiler and is part of the reason why Julia can be so fast. In your example you probably want a mutable struct, which is more similar a struct in C.
In Julia, you should never have to use pointers (Ptr) directly, unless you are calling C code. Since Julia uses a garbage collector, raw pointers have a lot of gotchas when it comes to memory management and should generally just be avoided. You usually just work with objects directly or, if you want to pass immutable objects by reference, you can wrap them in Ref.
In Julia, fields are always accessed either just with a dot x.field (equivalent to getproperty(x, :field)), or in some cases getfield(x, :field). (The latter can't be overloaded by the user, which is sometimes useful). -> actually creates an anonymous function.
For your example the following should work instead:
mutable struct Node
data::Int
left::Node
right::Node
Node(data::Int) = new(data)
end
function height(node::Node, field::Symbol)
isdefined(node, field) || return 0
return height(getproperty(node, field))
end
function height(node::Node)
lheight = height(node, :left)
rheight = height(node, :right)
# use the larger one
if lheight > rheight
return lheight+1
else
return rheight+1
end
end
What the first part is doing is creating a mutable struct Node, with self-referential fields like your C example. The line Node(data::Int) = new(data) is actually an inner constructor taking just the data and if you call new directly in a mutable struct, you can leave trailing fields undefined. You can define these fields afterwards with x.field = y. If these fields are themselves mutable, you can also check if they are undefined with isdefined(x, :field). Here, I am adding another method to height, which also takes a field name, which returns the height of the field if it's defined and 0 otherwise.
You would then construct nodes and calculate their height like this:
julia> n = Node(1)
Node(1, #undef, #undef)
julia> n.left=Node(2)
Node(2, #undef, #undef)
julia> n
Node(1, Node(2, #undef, #undef), #undef)
julia> height(n)
2
Hope that helps! If you want to learn more, the documentation I linked above is usually quite good.

Problem with Stack based Euler-Tree-traversal

I want a function that traverses a binary tree with the Euler traversal (this is how it works). Of course this is easily achievable with recursion - I know how that works. But now I want to implement an iterative version of this algorithm using a stack instead of recursion. My idea was to store the direction we are traversing on the stack as well. My code is not working and I can somehow not wrap my mind around this problem. Can you give me any hints on how to tackle this issue? Here is my code so far:
#define LEFT (struct Node*) 0xBADF00D
#define RIGHT (struct Node*) 0xDEADBEEF
struct Node {
int data;
struct Node* parent;
struct Node* left;
struct Node* right;
};
void eulerTree(struct Node* root)
{
stack<struct Node*> s;
s.push(root);
s.push(RIGHT);
s.push(root);
s.push(LEFT);
while(!s.empty()) {
struct Node* direction = s.top(); s.pop();
struct Node* node = s.top(); s.pop();
visit(node);
if(direction == LEFT) {
if(node->left) {
s.push(node->left);
s.push(RIGHT);
s.push(node->left);
s.push(LEFT);
}
}
if(direction == RIGHT) {
if(node->right) {
s.push(node->right);
s.push(RIGHT);
s.push(node->right);
s.push(LEFT);
}
}
}
}
Think of a simple binary tree to start with :
1
2 3
Euler traversal for this is : 1 2 1 3 1
You see the pattern here:
root, root->left, root, root->right, root
So your stack order should be:
root
root->left
root
root->right
root
But what if your root is a leaf? then don't push anything just print the value.
Also once you push the nodes on left, right make sure you set them as 0 for the root so that you don't keep pushing them forever.
With that said, the code in cpp would be:
Edit:
The previous code I posted has a bug. The correct code is below:
void eulerTree(struct Node* root)
{
stack<struct Node*> s;
s.push(root);
while(!s.empty()) {
struct Node* node = s.pop();
visit(node);
if(node->right) {
s.push(node);
s.push(node->right);
}
if(node->left) {
s.push(node);
s.push(node->left);
}
node->left = 0;
node->right = 0;
}
}
Without destroying the tree:
But yes, even though the code is simple this destroys the tree which is not desired. To tackle this problem I am going to use two properties for leaves of the tree in a euler tree traversal.
If the leaf is left child of the parent and the right child of that parent is null
( or )
if the leaf is right child
-after this leaf is printed then print the parent nodes all the way up the root.
If the leaf is left child and the right child is not null
-after this leaf is printed then print only its immediate parent.
To illustrate look at the below tree.
1
2 3
4 5 6 7
If the leaf is 5 then after it is printed, then print all the parents upto 1.
If the leaf is 4 then after it is printed, then print just its immediate parent 2.
To simplify implementation I am going to use a parent stack in addition to the current stack.
void eulerTree(struct Node* root) {
stack<struct Node*> s;
s.push(root);
struct Node* original = root;
stack<struct Node*> p;
while(!s.empty()) {
struct Node* node = s.top();
s.pop();
visit(node);
if ( !node->right && !node->left && !p.empty() ) {
struct Node* pNode = p.top();
if ( pNode->left == node && !pNode->right || pNode->right == node ) {
while ( !p.empty() ) {
visit(p.top());
p.pop();
}
p.push(original);
} else {
visit(pNode);
}
}
if(node->left || node->right) {
p.push(node);
}
if(node->right) {
s.push(node->right);
}
if(node->left) {
s.push(node->left);
}
}
}
A recursive implementation might look like this:
void euler(Node *n) {
visit(n);
if (n->left) {
euler(n->left);
visit(n);
}
if (n->right) {
euler(n->right);
visit(n);
}
}
Now whenever this makes a recursive call, the call stack is used to remember where we are in the code and what we're doing. Then we start again at the top and when we're done, that information is popped of the stack and we continue where we left off.
If you're going to do it iteratively with your own stack, you have to do the same job yourself. You have to remember enough to continue where you left off.
We have to remember which node we were working on of course, but also there are two recursive calls so, so there are 2 possible places we might have to return to. When we return from a recursive call, then either:
We have just done the n->left call and should continue on to check n->right; OR
We have just done the n->right call and should continue with the final visit of n
We could store some extra information on the stack to distinguish these two cases, but that is not necessary for this particular algorithm. From the descriptions above, you can see that we can distinguish these cases based on the node we're returning from -- it's either n->left or n->right.
So, just storing the waiting node in the stack, we can write an iterative version like this:
int state=0; // 0 => initial visit, 1 => just did left, 2 => just did right
Node *n = root;
while (n) {
visit(n);
if (n->left && state<1) {
stack.push(n);
n=n->left;
state=0;
continue;
}
if (n->right && state<2) {
stack.push(n);
n=n->right;
state=0;
continue;
}
if (stack.empty())
break; // done
Node *child=n;
n = stack.pop();
state = (child == n->left ? 1 : 2);
}

Singly linked list Tail

if you want create a singly linked list like this:
struct Node {
int data;
Node *next;
};
struct List{
Node *head;
// Node *tail; --> necessary?
Node *last;
};
And this list has the methods "append", "remove", "printList" and "findElement".
Is it necessary to have a tail? Because with "last" you can address the last node.
So when it is necessary to have all three Nodes "head", "tail" and "last"? When you want to insert the node sorted into the list for example?
No, it's not necessary. The tail is equal to head->next and thus it would be redundant and add bookkeeping overhead to keep this field updated.
Also note that the field last is kind of unusual. In most use cases, you add elements to the head of a singly linked list and use a different data structure when you really need to add to the end.
Actually, you can implement enqueue (append at tail), push (prepend at head), dequeue (remove from head), and of course find and print with with a one-pointer header. The trick is to make the list circular and have the header point to the tail. Then tail->next is the head.
#include <stdio.h>
#include <stdlib.h>
typedef struct node_s {
struct node_s *next;
int data;
} Node;
typedef struct list_s {
Node *tail;
} List;
Node *new_node(int data) {
Node *node = malloc(sizeof *node);
node->data = data;
node->next = node;
return node;
}
void init_list(List *list) {
list->tail = NULL;
}
int is_empty(List *list) {
return list->tail == NULL;
}
void enqueue(List *list, Node *node) {
if (list->tail) {
Node *head = list->tail->next;
node->next = head;
list->tail->next = node;
list->tail = node;
} else list->tail = node->next = node;
}
void push(List *list, Node *node) {
if (list->tail) {
Node *head = list->tail->next;
node->next = head;
list->tail->next = node;
} else list->tail = node->next = node;
}
Node *dequeue(List *list) {
Node *head = list->tail->next;
if (head == list->tail)
list->tail = NULL;
else
list->tail->next = head->next;
return head;
}
void print_list(List *list) {
printf("The list:\n");
if (list->tail) {
Node *head = list->tail->next;
Node *p = head;
do {
printf("%d\n", p->data);
p = p->next;
} while (p != head);
}
}
int main(int argc, char *argv[]) {
List list[1];
init_list(list);
// Build the list in order and print it.
for (int i = 0; i < 4; i++) enqueue(list, new_node(i));
print_list(list);
// Remove elements from head until empty.
printf("Dequeueing:\n");
while (!is_empty(list)) {
Node *node = dequeue(list);
printf("%d\n", node->data);
free(node);
}
// Build the list in reverse order and print it.
for (int i = 0; i < 4; i++) push(list, new_node(i));
print_list(list);
return 0;
}
I think it depends on what operations you want to use.
Assuming you want to insert and delete nodes at the tail of a list, it is certainly a wise choice to keep a last node in your list.
Otherwise, if you want to do operations at the beginning of the list, a last node is unnecessary.
It's not necessary but a tail can be useful if you're working with the linked list in a queue-like FIFO fashion rather than a stack-like LIFO fashion or want to be able to transfer entire lists of elements from one head to another's tail without disrupting the relative order of the elements.
Note that I'm referring to 'tail' as a reference to the last node in the list which I believe is safe to assume that the question is about.
A lot of very micro-optimized SLL implementations often are tail-less and work like a stack while backed by an efficient fixed allocator for locality of reference (cache-friendliness) and faster node allocations/deallocations. There the primary benefit of the SLL over a variable-sized array-based sequence is the ability to start moving things around by just changing the value of the next pointer/reference and the lack of invalidation on inserting/removing elements if you're working in native, lower-level languages that involve pointers. The lack of a tail can boost performance quite a bit by reducing the amount of branching instructions required in operations to push and pop from the stack.
For the needs you listed, whether the tail is going to help or just add unnecessary complexity and overhead is if your append and remove operations can work strictly from the front in a LIFO stack fashion or if you want to be able to append to the back but remove from the front in a FIFO fashion without any iteration involved, e.g. If you don't have a tail in the latter case, one of these operations are going to go from constant-time complexity to linear-time complexity, and you might improve your use cases by exchanging that linear-time algorithmic complexity for the relatively smaller micro-level overhead of maintaining a tail.

Reading binary tree floor by floor. What would be the fastest way to do that?

Let's say theres a binary tree like that.
I'd like to read it floor by floor (from left to the right) so the output would look like:
2 4 5 3 1 3 9
Thanks.
Its Printing in BFS, You should use auxiliary data-structure Queue: Learn here
listed below is pseudocode for a simple queue based level order traversal,
levelorder(root)
q = empty queue
q.enqueue(root)
while not q.empty do
node := q.dequeue()
visit(node)
if node.left ≠ null
q.enqueue(node.left)
if node.right ≠ null
q.enqueue(node.right)
This is one way of doing it.
void tree::BFS()
{
queue<node *>p;
node *leaf=root;
node *newline=new node; //this node helps to print a tree level by level
newline->val=0;
newline->left=NULL;
newline->right=NULL;
newline->parent=NULL;
p.push(leaf);
p.push(newline);
while(!p.empty())
{
leaf=p.front();
if(leaf==newline)
{
printf("\n");
p.pop();
if(!p.empty())
p.push(newline);
}
else
{
cout<<leaf->val<<" ";
if(leaf->left!=NULL)
{
p.push(leaf->left);
}
if(leaf->right!=NULL)
{
p.push(leaf->right);
}
p.pop();
}
}
delete newline;
}
This implementation is using queue.There are other implementations also in which you
do not need queue.
The below mwntioned code do not need any queue.
1) Using the parent pointer, get the level of the given node. Also, get the root of the
tree.
int level = 1;
struct node *temp = node;
/* Find the level of the given node and root of the tree */
while(temp->parent != NULL)
{
temp = temp->parent;
level++;
}
/* temp is now root of the tree and level is level of the node */
2) Once we have level of the given node and root of the tree, traverse the tree from
root to the calculated level + 1. We are traversing one extra level for the case
when given node is the rightmost node of its level. While traversing if you visit
the given node, mark visited flag as 1. Print the node just after the visited flag.
#include <stdio.h>
#include <stdlib.h>
/* Note the structure of root. It has data and pointers to left childe, right child and
parent node */
struct node
{
int data;
struct node *left;
struct node *right;
struct node *parent;
};
/* Prints the level order successor of node
root --> root of the tree
level --> level of node */
void _print(struct node* root, struct node *node, int level)
{
static int visited = 0;
if(root == NULL)
return;
if(level == 1)
{
/* If the given node is visited then print the current root */
if(visited == 1)
{
printf("Level Order Successor is %d ", root->data);
visited = 0;
return;
}
/* If the current root is same as given node then change the visited flag
so that current node is printed */
if(root == node)
visited = 1;
}
else if (level > 1)
{
_print(root->left, node, level-1);
_print(root->right, node, level-1);
}
}
void printLevelOrderSuccessor(struct node *node)
{
int level = 1;
struct node *temp = node;
/* Find the level of the given node and root of the tree */
while(temp->parent != NULL)
{
temp = temp->parent;
level++;
}
_print(temp, node, level);
}
/* Helper function that allocates a new node with the
given data and NULL left and right pointers. */
struct node* newNode(int data)
{
struct node* node = (struct node*)malloc(sizeof(struct node));
node->data = data;
node->left = NULL;
node->right = NULL;
node->parent = NULL;
return(node);
}
/* Driver program to test above functions*/
int main()
{
struct node *root = newNode(1);
root->parent = NULL;
root->left = newNode(2);
root->right = newNode(3);
root->left->parent = root;
root->right->parent = root;
root->left->left = newNode(4);
root->right->right = newNode(5);
root->left->left->parent = root->left;
root->right->right->parent = root->right;
// printf("\n Level order successor of %d is: ", root->right->data);
printLevelOrderSuccessor(root->left->left);
return 0;
}
Time Complexity: O(n) for both the algos.
Space Complexity: O(n) if we consider the size of recursion stack, otherwise O(1).

How To Find the Mirror Node of a Given Node (or item) in a Binary Tree Efficiently

I've been thinking of this problem, and I have not found a good, efficient solution.
How to find the mirror node of a given node (or item) in a binary tree?
// Node definition
struct _Node {
char data;
struct _Node* left;
struct _Node* right;
} Node;
// Assumption:
// "given" is guaranteed in the binary tree ("root" which is not NULL)
Node* FindMirrorNode(Node* root, Node* given)
{
// Implementation here
}
// OR:
// Assumption:
// in the binary tree ("root"), there is no repeated items, which mean in each node the char data is unique;
// The char "given" is guaranteed in the binary tree.
char FindMirrorNodeData(Node* root, char given)
{
// Implementation here
}
NOTE: I'm NOT asking on how to find a mirror tree of a given tree :-)
For example, considering the tree below
A
/ \
B C
/ / \
D E F
\ / \
G H I
The mirror node of 'D' is node 'F'; while the mirror node of 'G' is NULL.
Thanks.
I've written a solution for the function with the char. Is FindMirrorNode(r, n) == FindMirrorNodeData(r, n->data)?
You have to go through the entire tree searching for the given data while keeping the mirror nodes on the stack. That's a quite simple solution, still quite efficient.
If you want you may transform tail-calls into while.
static Node* FindMirrorNodeRec(char given, Node* left, Node* right)
{
// if either node is NULL then there is no mirror node
if (left == NULL || right == NULL)
return NULL;
// check the current candidates
if (given == left->data)
return right;
if (given == right->data)
return left;
// try recursively
// (first external then internal nodes)
Node* res = FindMirrorNodeRec(given, left->left, right->right);
if (res != NULL)
return res;
return FindMirrorNodeRec(given, left->right, right->left);
}
Node* FindMirrorNodeData(Node* root, char given)
{
if (root == NULL)
return NULL;
if (given == root->data)
return root;
// call the search function
return FindMirrorNodeRec(given, root->left, root->right);
}
Thanks for Chris's beautiful solution. It worked.
Node* FindMirrorNodeRec(Node* given, Node* left, Node* right)
{
// There is no mirror node if either node is NULL
if (!left || !right)
return NULL;
// Check the left and right
if (given == left)
return right;
if (given == right)
return left;
// Try recursively (first external and then internal)
Node* mir = FindMirrorNodeRec(given, left->left, right->right);
if (mir)
return mir;
// Internally
return FindMirrorNodeRec(given, left->right, right->left);
}
// Find the mirror node of the given node
// Assumption: root is not NULL, and the given node is guaranteed
// in the tree (of course, not NULL :-)
Node* FindMirrorNode(Node* const root, Node* const given)
{
if (!root || root == given)
return root;
return FindMirrorNodeRec(given, root->left, root->right);
}

Resources