Build an n-ary tree from a forest - c++

i asked my professor to give me an old homework from another semester. And its about building a family tree and then finding the kinship between two nodes given. The family tree is about namekians (Dragon ball z) so every namekian has a single father.
The thing is that the input its something like this:
First name is the parent Second name is the child
Iolin Lyre
Iolin Piyano
Batu Iolin
Batu Okiat
Ollusc Xylo
Organa Murd
Piccoro Ollusc
Piccoro Rombone
Rombone Organa
So i must have two trees, one with Piccoro as the leader (he is always the leader of one tree) and another with unknown leader.
The thing is that i have trouble when i try to create the trees, i know i have two roots, but as you can see the input is not in order so ill have nodes without parent until i read and create its parent. For example, i create Ollusc and its child Xylo, and then Organa and Murd, but i only have one root to represent that tree (Also i dont know if they are in the same tree or not) so i dont know how to "save" those nodes to connect them later, same happens with Organa and Rombone, Organa will be somewhere until i create Rombone and then connect him with Organa.
Batu------>NULL
/ \
Iolin--->Okiat->NULL
/ \
Lyre-->Piyano->NULL
Piccoro-----> NULL
/ \
Ollusc--->Rombone->NULL
/ /
Xylo->NULL Organa->NULL
/
Murd->NULL
I thought about saving nodes into a Queue or maybe a Stack because i dont know how much nodes will be floating somewhere until i connect them, but save them into a queue and then what?, because when i think about my next step i don't know what to do.
Maybe store a node into the queue until a node Parent appears, and then take that node from queue, but queue its FIFO and doesnt help too much i think, because what if i need to take the second node or maybe the third instead of the front one.
So maybe store them into a aux list?
I should add a node to a list,Queue,stack if they have no parent and they are not the root right? or should i add the root to the list,Queue,Stack?
Because i'm using root to build the tree
In the first Tree my root its Iolin until batu appears and i change it to batu
In the second tree Root will be always Piccoro, but its a little difficult to build a tree starting with piccoro because i dont know his childs
What do you think? what should i do? Do you have better or other ideas?
int main(int argc, char const *argv[])
{
FILE *fpInput,*fpOutput;
fpInput = fopen("input.in","r");
fpOutput = fopen("output.out","w");
if ((fpInput == NULL)){ printf("Open File Error\n"); exit(1); }
// To read a line of the file
char *fpInputString;
char *parentInput, *childInput;
// Because i dont know the number of lines that comes next, read until a number is found
// That number is the number of consult of kinship about namekians
fpInputString = inputString(fpInput,5);
while ((strlen(fpInputString) != 1) && (strlen(fpInputString) != 2) && (strlen(fpInputString) != 3))
{
parentInput = strtok(fpInputString," ");
childInput = strtok(NULL,"\0");
fpInputString = inputString(fpInput,5);
}
fclose(fpInput);
fclose(fpOutput);
return 0;
}
InputString Function reads a whole line from a file
tree.h
// Struct of a node
struct treeNode
{
// Name
char *name;
// Pointers
struct treeNode *parent;
struct treeNode *firstChild;
struct treeNode *nextSibling;
struct treeNode *prevSibling;
};
I'll be very thankful if you help me, i know it can be hard to understand me or my code
But i really want to learn new things about coding, i don't know if this homework will be better if i do it in c++ because c doesn't have STL

Save input information with map.
Find the ancestor node.
Add child nodes to the ancestor node.
Don't build trees for a node if it is not a ancestral node.

Related

BST setting height at each pointing node

I am trying to implement recursive method to set recursively the height at each node. Partially solution is achieved, however I am not entirely sure where I could decrement height and check if particular node in-Order traversal is complete. My program is based on this implementation: http://visualgo.net/bst.html
Thank you
If you mean for height here to represent the level of the tree that a node is on, using a global variable is going to give you pretty weird results. I also admit to not being entirely sure what you are doing with the variable u.
That said, I think you should be okay with something like this:
public void setHeight(struct node *r, int h = -1) {
// pointer pointing to null, return
if(r == NULL) {
return;
}
h++; // increment height
r.height = h; // set update height to a current node
setHeight(r ->u.lc, h); // traverse the list pointing to the left child
visit(r) // visit pointing node
setHeight(r ->u.rc, h); // visit right child of the node
}
Edit: I don't have the reputation to comment yet, so I'm limited to responding with edits. #ProgLearner, you don't need a separate variable u because your node pointer is a function argument, and so you'll have a fresh one with every call to the function. Similarly, as Jonathan Mee said, the h variable needs no external initialization because it's also local to the function. In cases where you don't supply any initial value (like when you call it on the root), it will default to -1.

Is there a way to keep data from previous recursion in C++ (specific example)?

I'm working on an AVL Tree Project (almost finished after lots of hours of programming) and I wonder if it's possible to keep data from the calling recursion. This is the code:
node* previous;
//Visits the nodes by level recursively (post-order traversal), so that it can calculate the balance of each node (updates heights when deleting a node with two children)
void AVLTree::updateTreeHeights(node *ptr)
{
if(ptr==root)
previous=root;
if(ptr==NULL)
return;
updateTreeHeights(ptr->leftChild);
updateTreeHeights(ptr->rightChild);
if(ptr->leftChild==NULL && ptr->rightChild==NULL)
{
ptr->heightL=ptr->heightR=0;
}
else if(ptr->leftChild==NULL)
{
ptr->heightR=max(ptr->rightChild->heightL,ptr->rightChild->heightR)+1;
ptr->heightL=0;
}
else if(ptr->rightChild==NULL)
{
ptr->heightL=max(ptr->leftChild->heightL,ptr->leftChild->heightR)+1;
ptr->heightR=0;
}
else
{
ptr->heightL=max(ptr->leftChild->heightL,ptr->leftChild->heightR)+1;
ptr->heightR=max(ptr->rightChild->heightL,ptr->rightChild->heightR)+1;
}
ptr->balance=ptr->heightR-ptr->heightL;
if(ptr->balance>1)
balanceTree(ptr,previous,ptr->rightChild);
else if(ptr->balance<-1)
balanceTree(ptr,previous,ptr->leftChild);
}
Here's what I want! I want to keep the ptr value from the calling recursion and save it to the gloabal variable named previous (it's not necessery to be global, but I figured that it must be the only way). For example if ptr points at number 20 and then we call the recursive function for ptr's leftChild (e.g. updateTreeHeights(ptr->leftChild);) I want to keep number 20 (previous=ptr;). Is it possible somehow? I'm not really good with recursion! (Don't tell! :P )
I don't see why not. You can make a global variable and then just copy it over from updateTreeHeights. Just keep a look out for making sure the copy happens only once, and also by doing previous=ptr previous will be pointing to the entire node. So you might have to dive a little deeper in the node to get the date you want.

What is wrong with my operator += of the binary search tree?

I have some lines of code about a binary search tree (BSTreeBag) which I can not quite figure out.
The "operator +=(const BSTreeBag& addend)" requires to insert what's in the addend into the current tree we have. If the current tree we have is the same with "addend" we need to double our tree(to make duplicates of all items in the tree)
Here is my code
template <class ItemType>
void BSTreeBag<ItemType>::operator +=(const BSTreeBag& addend)
{
if(this==&addend)//This works
{
binary_tree_node<ItemType>* addroot_ptr=root_ptr;//create a pointer
//that points to the current tree
insert_all(addroot_ptr);//This is a helper function that insert
//every item of the addend into the current tree. It works fine.
}
else
{
insert_all(addend.root_ptr);
}
}
The lines of code works perfectly whenever it is not doing self-assignment. It always stops at the line
insert_all(addroot_ptr);
without giving any information about segmentation fault or other problem. Could someone explain what is going on?
A very likely problem is that you have an infinite loop when you add one tree to itself. Like in, you add nodes while iterating over the tree, but since there are new nodes being added you continue iterating and adding them, ad infinitum.
Lets give an example with a simple list. Lets say you have the following list:
root -> A
Now if you try to add the list to itself, you iterate over the list from the root pointer, finding the node A, so you add that. Now your list looks like
root -> A -> A
You continue the iteration and find... node A (again), and so you add it:
root -> A -> A -> A
And so on and so on.
You should probably create a completely new tree from root_ptr and then add that.
This is what mine looks like (I think both the instructions AND the test file are a little wack):
template <class ItemType>
void BSTreeBag<ItemType>::operator+=(const BSTreeBag& addend)
{
if (this != &addend)
insert_all(addend.root_ptr);
else
{
BSTreeBag<ItemType> new_bst = addend;
insert_all(new_bst.root_ptr);
tree_clear(new_bst.root_ptr);
}
}

Nested loop to delete linked list members that are equal to another member is breaking. Isolated the issue to one line

I've been working on my linked list lab with the help of a tutor, but lost contact with them unfortunately a while ago and haven't been able to figure this out on my own.
My first while loop steps through the linked list one node at a time, and then proceeds to the second while loop which steps through the second one and compares it to the first.
This seems to be working fine. The problem however, is that when it deletes a member, it actually goes ahead and deletes two. It deletes the one before it, and the node it's supposed to.
I've isolated the problem to line 80 of list.cpp (below). I think that cursorOne's link_field pointing to cursor 2's link field is deleting all of the nodes in between the two cursors, and this isn't what I want.
So I guess I should have cursor 1's link field point to cursor 1 next's link field? I feel so close.. and the hard part of this lab is already done but I have yet to have the one last Eureka moment req'd but I've been looking at it a lot.
Here is the program: It should be pretty self explanatory. It uses the node class and then mutates it with the list class.
Well on second thought, I guess I can't link to code on ideone.com.
So I will try and make this as brief as possible and just post the loop.
Here is the node and list.cpp
while(currentItem != NULL)
{
cout << "Enter Second Loop" << endl;
cout << currentItem->data_field << " Curse 2" << endl;
//compare it
if (nodeToFindDuplicatesOf->data_field == currentItem->data_field)
{
//prev->next = current->next to delete
// in order to delete only one, I must find a way to set the link_field of the previous node to cursor 1 to
// the link field of the node that's to be deleted
cout << nodeToFindDuplicatesOf->data_field << "being removed" << endl;
predecessor = currentItem->link_field;
delete currentItem;
currentItem = nodeToFindDuplicatesOf; //set cursor2 to cursor1
}
currentItem = currentItem->link_field;
}
nodeToFindDuplicatesOf = nodeToFindDuplicatesOf->link_field;
if (nodeToFindDuplicatesOf)
currentItem = nodeToFindDuplicatesOf->link_field;
}
}
Do I need a previous node pointer in my node class?
Your analysis in locating the error is correct. To delete an item from a list you need a pointer to both the currentItem you want to delete (a.k.a cursorTwo), as well as its predecessor. Your cursorOne pointer however is not the predecessor of cursorTwo, but instead the pointer to some node you want to find the duplicates of.
To fix the error, first of all use meaningful names for your variables. cursorOne and cursorTwo are not meaningful at all and their names are most likely the origin of your error. Why not call them nodeToFindDuplicatesOf and currentItem? (or maybe you can come up with something even better.)
Then you need to introduce a new pointer to keep track of the predecessor of currentItem.
When currentItem needs to be removed set the link_field of its predecessor, then delete currentItem (without setting it to NULL beforehand).

C++ libxml xmlNode->children

Ok I have been working on a class to iterate through all nodes in an html doc and return the data that I need. This is very simple and I have achieved this in Bash but now I am trying to port the same to C++.
I started with the example on the libxml site but I have stepped through this function node by node and I can't understand how it is working.
Here is the function:
static void
print_element_names(xmlNode * a_node)
{
xmlNode *cur_node = NULL;
for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
if (cur_node->type == XML_ELEMENT_NODE) {
printf("node type: Element, name: %s\n", cur_node->name);
}
print_element_names(cur_node->children);
}
}
So basically, this function takes a node assigns it to a pointer, and starts to loop through all sibling nodes, but if the current node has children, it calls the function and start over on that child node. This is all very understandable.
So it drives down the doc structure, but how does it navigate back up the structure?
Does xmlNode->children return the next parent node when it is found NULL? As far as I can tell, this is not true, but I just can't figure out how this is working.
I successfully created a class to do what I want, but it is so much more complex than this and about 10 lines longer. I actually had to check if the next node was null and either navigate down if it has children or navigate back up and to the next node if it didn't.
This example is much simpler and I would like to understand how to make my code better.
So it drives down the doc structure, but how does it navigate back up the structure?
What you have posted is a recursive function. From the nature of your question, I'm assuming you don't quite understand what recursion is/how it works. A quick google search should give you some good information/examples.
Does xmlNode->children return the next parent node when it is found NULL?
I am assuming that xmlNode->children returns a pointer to a linked list containing all children of the current node. If the current node has no children, it would probably return NULL.
This example is much simpler and I would like to understand how to make my code better.
I am assuming the class you wrote was purely iterative. Recursive functions can greatly simplify code, but performance wise they can cause issues on larger data sets. I would definitely recommend reading up on them; they can be quite fun.
Solving the problem iteratively is essentially a tree traversal. You will need a stack to accomplish this. The stack can probably be most easily implemented as a singly-linked-list.
// interface to be implemented
typedef void* Stack;
Stack stack_new(); // creates a new stack
void stack_add(Stack stack, xmlNode *element); // adds an element to the stack
int stack_size(); // returns the number of elements currently in the stack
xmlNode* stack_remove(Stack stack); // pops an element from the stack
void stack_free(Stack stack); // frees up resources used by the stack
// printing code
static void print_element_names(xmlNode *a_node)
{
Stack stack = stack_new();
stack_add(stack, a_node);
while(stack_size(stack))
{
xmlNode *cur_node = stack_remove(stack);
if(cur_node->children) stack_add(cur_node->children);
xmlNode *iter_node = NULL;
for (iter_node = cur_node; iter_node; iter_node = iter_node->next)
{
if (iter_node->type == XML_ELEMENT_NODE)
printf("node type: Element, name: %s\n", iter_node->name);
}
}
stack_free(stack);
}