I'd just like to note I already saw this post before asking my question: C How to "draw" a Binary Tree to the console
Let's say I have the following tree. If my print function were to print only the numbers (in order traversal), I would have the following printed out: 1,3,4,6,7,8,10,13,14.
What would be the best approach to draw the tree like something below considering the tree gets printed in that order?
I feel that if 8 got printed first followed by 3,10 etc.. it would be easier but since it is in-order traversal 1 is getting printed first which would be the first print statement at the top.
I did this about 2 years ago for some coursework...
I created a node struct that contained its own data and 2 nodes, one left and one right, it looked like this (I couldn't find the final code, that might have used shared pointers):
struct node
{
int data;
node *left;
node *right;
};
I then created my tree by adding more nodes to it using recursion like so:
void insert(node **tree, int value)
{
if (*tree == nullptr)
{
*tree = new node;
(*tree)->data = value;
(*tree)->left = nullptr;
(*tree)->right = nullptr;
}
else if (value < (*tree)->data)
{
insert(&((*tree)->left), value);//memory location of the pointer to the node of the node
}
else if (value > (*tree)->data)
{
insert(&((*tree)->right), value);
}
else
return;
}
Side note: Looking back, I never accounted for adding a node with the same value as an existing node if that's even possible.
I assume you will be doing something similar. Now for the bit that answers your question, printing it out, also using recursion.
void inorder(node *tree)
{
if (!(tree == nullptr))
{
inorder((tree)->left);
cout << (tree->data) << endl;//Prints on new lines, you could comma separate them if you really wanted.
inorder((tree)->right);
}
}
Lastly, you'll want to clean up your tree after you've used it so you'll need to delete it... recursively.
To be honest it's been a while and this recursion thing is still a little confusing to me so I have probably forgotten something, but the theory's there!
Edit, headers used: <iostream> and <memory>, also this was c++ not c but they're very similar.
Related
i have a program with various recursive functions.
I now need to optimize the code to run the program faster: i checked with profiler and, a part from the biggest function with lots of checks, i have two functions that require a lot of time every run.
One (Unmarked_Nodes) is like this:
typedef struct node* tree;
struct node{
char* data;
tree left;
tree right;
int marker;
};
static int remaining = 0;
int main(){
...
}
int Unmarked_Nodes(tree root) {
if (root != NULL) {
Unmarked_Nodes(root->left);
if (root->marker == 0)
remaining++;
Unmarked_Nodes(root->right);
}
return remaining;
}
The other is similar but instead of the if cycle it has a printf of data.
The other, however, is faster than this... why? Or instead: how can i improve the code to make it run faster?
Thanks in advance
Candidate improvements: might help a little although answer remains O(n).
Recurse less often
Loop inside the function for one of the children.
Avoid global
Simply not needed.
Use const
No so much a speed improvement, yet allows for use with constant data.
Avoid hiding pointers
int Unmarked_Nodes(const struct node *root) {
int remaining = 0;
while (root != NULL) {
remaining += Unmarked_Nodes(root->left);
if (root->marker == 0) {
remaining++;
}
root = root->right;
}
return remaining;
}
Perhaps only recurse when both children are non-NULL. Test null-ness at the end of the loop since it is initially false for all recursive entry.
static int Unmarked_Nodes2r(const struct node *root) {
int remaining = 0;
do {
if (root->marker == 0) {
remaining++;
}
if (root->left) {
if (root->right) {
remaining += Unmarked_Nodesr(root->right);
}
root = root->left;
// continue; // Could skip loop test.
} else {
root = root->right;
}
} while (root);
return remaining;
}
int Unmarked_Nodes2(const struct node *root) {
return root ? Unmarked_Nodes2r(root) : 0;
}
In the absence of more information, it would seem that you likely "visit" the tree three times: once for 'marking' nodes (for whatever purpose), once to 'print' marked (or unmarked) nodes, and once more to reset those marks.
Presuming that 'marked nodes' are the interesting ones, consider using a dynamic array of pointers (malloc/realloc in suitable increments) to build a list of only those nodes, print from that list (no 2nd tree traversal), then free() the list (no 3rd tree traversal).
You wouldn't need to 'mark/unmark' anything. Interesting nodes added to the suggested list mean that those nodes are 'marked', and 'unmarked' when the list is erased.
You may need to consider if 'marking' may encounter unwanted duplicates.
Another suggestion is to consider transforming the tree into a list once it is filled. Then, use conventional binary search of that list to mark 'nodes', and a sweep through to erase marks (presuming the same list is to be reused multiple times.
Another suggestion relates to whether you are marking to include or to exclude from the print traversal. If marked nodes are included, then simply 'unmark' them as you print them. If marked nodes are excluded, then mark all those other unmarked nodes being printed that haven't previously been 'excluded' and remember whether '0' means 'marked' or if '1' means marked for the next time it comes to searching/marking.
Hi this is probably a stupid question to ask with a simple solution but I just can't find an answer in the internet.
So I was exercising for an exam and worked on an assignment. The program has the job to find out what the value in the center of a linked list is (if the length of the list is an odd number)
The structdef is:
typedef struct IntList IntList;
struct IntList {
int value;
IntList* next;
};
and my exact problem right now is that I get a segmentation fault when I try using:
list = list->next;
I want to go step by step in a loop to go to the wished list at the nth position (the center) of the linked list.
Someone knows how I have to rewrite this? If you need more Information to help just say so and I will explain more.
With that function I check the length of the list and in my other function I have a loop which only goes to the mid of the length.
int length_list(IntList* list) {
int n = 0;
for(IntList* node = list; node != NULL; node = node->next) n++;
return n;
}
After this loop ends for(IntList* node = list; node != NULL; node = node->next) n++; you surely have node==NULL.
That is not immediatly a problem.
But depending on what you do with the value of n which you return you might have an off-by-one problem. E.g. in a list with exactly one entry (1 is odd after all), the attempt to use a value which is 1 too high could result in an attempt to access a non-existing node.
Because of this I suspect that your problem might be solved by changing the loop to
for(IntList* node = list; node->next != NULL; node = node->next) n++;, so that it ends on the last existing node, instead of behind. The return value will be lower, whatever you do with it will be "more-careful".
That or try something similar with the small code fragment you show and ask about, list = list->next; only do that if the next is not NULL, not if only list is not NULL.
I have a function that creates a binary tree, and for each node in the tree, I need to add a node to a separate linked list that points to the node in the binary tree.
My function to create the binary tree:
typedef struct myTree _node;
void INSERT(_node *(*tree), _node *item) {
if (!(*tree)) {
*tree = item;
return;
}
if (item->val < (*tree)->val) {
INSERT(&(*tree)->left, item);
}
else if (item->val > (*tree)->val) {
INSERT(&(*tree)->right);
}
}
My main function:
int main(void) {
int i;
int *balanced;
_node *current, *root;
root = NULL;
for (i = 0; i < size; i++) {
current = (_node *)malloc(sizeof(_node));
current->left = current->right = NULL;
current->val = balanced[i];
INSERT(&root, current);
}
return 0;
}
I've left out parts of my main function for simplicity.
The idea is that I want to print out the contents of the tree in pre, in, and post order, as well as traverse the linked list and print the value of the node in the tree that each linked list node points to.
I'm only a few months into learning C, so I am not terribly advanced.
Much like your insert function is recursive on the tree, walking the tree is recursive as well. There are two ways to do this: the specific way and the generic way. Let's see both.
The specific way just prints values as it encounters them. It solves this specific problem: printing the values. If you have to do tree walks to do more than one thing, you'd have to copy the code, which is generally a bad thing.
On the other hand, the code is much simpler and easier to follow. Let's look at the in-order case (you can do the other two by yourself; they are very similar):
void print_in_order (const struct myTree * tree) {
// if we're in a null node, do nothing
if (!tree) return;
// otherwise, do the left subtree, then the current node, then the right subtree
// non-existent subtrees will be handled by the above check, so don't check twice
print_in_order(tree -> left);
printf("%d\n", tree -> val);
print_in_order(tree -> right);
}
The generic way, on the other hand, is a better approach if your program is doing tree walks for all sorts of purposes. The idea is that you encapsulate the actual task to be done at each node (in this case, printing it) in a separate function:
void print_node (const struct myTree * node) {
printf("%d\n", node -> val);
}
And then you write a function that takes this function as an argument and calls it on each node, in the corresponding order. Let's do it for in-order:
void apply_in_order (const struct myTree * tree,
void (* callback)(const struct myTree *)) {
// this is the same as before...
if (!tree) return;
apply_in_order(tree -> left, callback);
// ...except that, instead of doing a specific thing, we call the callback on each node
callback(tree);
apply_in_order(tree -> right, callback);
}
Now, you just call this function as apply_in_order(tree, print_node); and you get the same behavior as above. But the next time you need to write a function that walks a tree, you only need the per-node thing; the rest is already done.
struct cnode
{
int info;
struct cnode *next;
struct cnode *previous;
};
typedef struct cnode cnode;
pre-made DOUBLY LINKED LIST: 1<->2<->3<->4<->5<->6<->7
So I'm trying to make a recursive function that grabs the mid of the doubly linked list (root = 4) and convert it into a the remaining into a binary tree. I'm still new to recursion so an explanation along with code would be GREATLY appreciated!
EX. 4
/ \
2 6
/ \ / \
1 3 5 7
This is the code I have thus far (which isn't much due to difficulties with recursion)
void *convert(cnode *head){
if(head == NULL)
return;
int count = 0;
cnode *tempHead = head;
while(tempHead != NULL){
count++;
tempHead = tempHead->next;
}
int move = (count/2) + (count%2);
int i;
for(i=1; i<move; i++){
head = head->next;
}
}
Pretty much just sets the head pointer to the mid info (4)
I think I understand; you're making a balanced binary tree from cnodes with the previous and next pointers being reused for the left and right sub-trees.
... so that's your algorithm.
Find the middle node of the binary tree (which you've already done).
Turn the left half into a binary tree. The left half is the original head, with the last element (middle->previous) now having a next pointer of NULL.
Link this left half to middle->previous (hijacked as the left sub-tree).
Turn the right half into a binary tree; this is headed by middle->next. Make it the new value of middle->next.
You have to keep the original head as the pointer to the left sub-tree.
You'll want your routine to return the binary tree's root, so the previous call can link it into the level above.
You still have to pick a termination condition, such as the head pointer being NULL.
Does that get you moving to a solution?
I hope this code will help you. call the DLL2BT method with head of the doubly linked list which return the root node of the tree created.
class box
{
int data;
box left=null,right=null;
box(int a)
{
data=a;
}
}
public static box DLL2BT(box head)// head = linked list head
{
if(head!=null)
{
box node=null;
try
{
node = findMid(head);
node.left.right=null;
node.left=DLL2BT(head);
node.right.left=null;
node.right=DLL2BT(node.right);
}
catch( Exception e){ }
return node;
}
return null;
}
public static box findMid(box head)
{
box slow=head,fast=head.right;
try
{
while(fast!=null)
{
slow=slow.right;
fast=fast.right.right;
}
}
catch(Exception e){ }
return slow;
}
Firstly, You are trying to convert DLL to binary tree assuming the DLL is given as in-order of the binary tree you have to make. Note that there isn't a unique tree you can make from only inorder traversal.Even if you have to make BST, you can't make it with only inorder traversal. What I actually think you are trying to do is to convert it into a balanced BST. Even though, it will also not be unique.
Here's the algorithm..
1) Get the Middle of the linked list and make it root.
2) Recursively do same for left half and right half.
a) Get the middle of left half and make it left child of the root
created in step 1.
b) Get the middle of right half and make it right child of the
root created in step 1.
Time complexity: O(nLogn) where n is the number of nodes in Linked List.
Although,it can be solved in O(n) if you insert nodes in BST in the same order as the appear in Doubly Linked List.
I was asked to write the iterative version, but I wrote the recursive version i.e.
void inorderTraverse(BinaryTree root)
{
if(root==NULL)
printf("%d",root->id);
else
{
inorderTraverse(root->left);
printf("%d",root->id);
inorderTraverse(root->right);
}
}
I'm not looking for the code, I want to understand how this can be done. Had it been just the last recursive call, I would have done
void inorderTraverse(BinaryTree root)
{
while(root!=NULL)
{
printf("%d",root->id);
root=root->right;
}
}
But how do I convert to an iterative program when there are two recursive calls?
Here are the type definitions.
struct element{
struct element* parent;
int id;
char* name;
struct element* left;
struct element* right;
};
typedef element* BinaryTree;
This is what I thought of, am I on the right track?
temp=root;
while(1)
{
while(temp!=NULL)
{
push(s,temp);
temp=temp->left;
continue;
}
temp=pop(s);
if(temp==NULL)
return;
printf("%d\t",temp->data);
temp=temp->right;
}
The problem you're seeing is that you need to "remember" the last place you were iterating at.
When doing recursion, the program internally uses "the stack" to remember where to go back to.
But when doing iteration, it doesn't.
Although... does that give you an idea?
I can't think of a really elegant way to do this iteratively off-hand.
One possibility might be using a 'mark algorithm', where you start out with all nodes 'unmarked' and 'mark' nodes as they're handled. The markers can be added to the object model or kept in a seperate entity.
Pseudocode:
for (BinaryTree currentNode = leftmostNode(root); currentNode != null; currentNode = nextNode(currentNode)):
print currentNode;
currentNode.seen = true;
sub nextNode(BinaryTree node):
if (!node.left.seen):
return leftmostNode(node.left)
else if (!node.seen)
return node
else if (!node.right.seen)
return leftmostNode(node.right)
else
return nextUnseenParent(node)
sub leftmostNode(BinaryTree node):
while (node.left != null)
node = node.left
return node;
sub nextUnseenParent(BinaryTree node):
while (node.parent.seen)
node = node.parent
return node.parent
I take it for granted, that iterating down from the parent nodes to the left nodes is not a problem. The problem is to know what to do when going up from one node to the parent: should you take the right child node or should you go up one more parent?
The following trick will help you:
Before going upwards remember the current node. Then go upwards. Now you can compare: Have you been in the left node: Then take the right node. Otherwise go up one more parent node.
You need only one reference/pointer for this.
There is a general way of converting recursive traversal to iterator by using a lazy iterator which concatenates multiple iterator suppliers (lambda expression which returns an iterator). See my Converting Recursive Traversal to Iterator.