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);
}
}
Related
I managed to figure out the answer to this question as I was writing it. Keeping it posted to hopefully aide future devs that run into similar issue.
Here's a quick rundown:
I have a directed, weighted map class.
I keep track of all my nodes in: vector<Node> nodes;
I keep track of all the nodes' adjacent nodes in map<Node, <map<Node, int>> connections
When I try doing a traversal through the Graph and I reach a node that does not have any adjacent nodes it will crash the program because my map throws out_of_range exception.
After looking online I see someone has the solution of using this line of code when they are adding nodes: (void) connections[node];. If I remove this line of code, I get the out_of_range exception from the map class's .at() function, but with this line of code, it somehow avoids that exception.
My Question: What is the line of code doing that avoids the exception from being thrown?
My best guess right now is that the line of code is somehow creating an empty adjacency list and my for-each loop doesn't get the exception
set<Node> nodes; // {n1, n2...nn}
map<Node, map<Node, int>> connections; //Connections between the nodes and their weights
//Add node to graph
void add(Node node) {
nodes.insert(node); //add to node list
(void) connections[node]; //This is the magic line!!
}
bool DFS(N start, N target) {
for (Node node : nodes) {
//This for-each loop crashes when the node in the .at() doesn't exist in the connections map
for (pair<N, int> connectedNode : connections.at(node)) {
if (target == connectedNode.first) {
return true;
}
}
}
return false;
}
As I was writing the question I was able to answer my own question. Love a good Rubber Ducky moment. Hopefully, this question can aide future devs who also miss the very basic answer to this question.
In stl::map the [ ] operator will get a reference to the value of the key inside the [ ] if it exists, if it doesn't exist it creates one.
So in the add(Node node) function the (void)connections[node] was actually creating the node in the adjacency map.
The (void) before the line is telling the compiler to ignore any warnings about this because it's technically an incomplete line of code (according to the compiler). Read more about the meaning of (void) here
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.
I have a simple digital tree defined as below:
class DTN {
public:
DTN () :
is_word(false), word_to_here(""), children()
{}
DTN (bool iw, std::string wth) :
is_word(iw), word_to_here(wth), children()
{}
bool is_word;
std::string word_to_here;
Map<char,DTN> children;
};
I am having problem to define a function called longest_word (const DTN& dtn) which is suppose to return the longest word in the digital tree with iterator and recursion, shown as follow:
std::string longest_word (const DTN& dtn) {
std::string lw = dtn.word_to_here;
for(auto s:dtn.children){
if(s.second.is_word && lw.length()<s.second.word_to_here.length()){
lw = longest_word(s.second);
}
longest_word(s.second);
}
return lw;
}
Assume we have three words in a digital tree DTN: (ante, anteater, anthebellum), and calling the longest_word(DTN) will give me an empty string "" instead of "anthebellum". Can someone please point out what I did wrong in the longest_word function? With actual code will be appreciated because my English is not good, codes are easier for me to understand. Thanks in advance.
The algorithm for longest_word is completely wrong. You should inspect all children longest_words and return the one which is longer. You cannot return before the loop on children is complete. Notice that your algorithm will always return on first children. I don't even understand why you check for a complete word there...
I could try to write the correct code but I feel it is not useful to you. My suggestion is to get back to simplest algorithms like finding the maximum number in a list of integers.
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.
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);
}