#include <iostream>
#include <string>
#include <fstream>
using namespace std;
template <class T>
struct TreeNode{
string value;
T key;
TreeNode<T> *LeftChild;
TreeNode<T> *RightChild;
TreeNode (T k,string Val)
{
this->value=Val;
this->key=k;
this->LeftChild=NULL;
this->RightChild=NULL;
}
};
template <class T>
class BinaryTree{
private:
TreeNode<T> *Root;
public:
BinaryTree();
void insertNode();
};
template <class T>
BinaryTree<T>::BinaryTree()
{
Root=NULL;
ifstream fin;
fin.open("names.txt");
string buffer;
T buff;
while (!fin.eof())
{
getline(fin,buffer,'~');
fin>>buff;
cout<<buff<<buffer<<endl;
cout<<"down the tree"<<endl;
TreeNode<T> *temp=Root;
while (temp!=NULL)
{
TreeNode<T> *Right=temp->RightChild;
TreeNode<T> *Left=temp->LeftChild;
if (temp->key>buff)
{
temp=temp->LeftChild;
}
else if (temp->key<buff)
temp=temp->RightChild;
}
cout<<"further down"<<endl;
}
temp->value=buffer;
temp->key=buff;
cout<<"and done!"<<endl;
cout<<"hey"<<endl;
}
fin.close();
}
I am making a binary tree. There are pointers to left and right child in my tree and a key and a string value for each node. In my destructor I am reading from a file and storing the key and value in a node. Every line of the file has the following format:
"M. Ubiquity~ 14100148"
- the Value is the name followed by the key.
Whenever I run this code, I get segmentation fault error but I can't seem to find the fault.
Any hint/help will be appreciated.
You have Root=NULL; and then few lines later TreeNode<T> *temp = Root; so you have temp=NULL.
Obviously the while (temp!=NULL) never executes and after while loop you have temp->value=buffer; which cause segementation fault!
Pointers can only associated with memory addresses, not values. Mainly there are two ways: If you have an automatic variable, you can assign its address to a pointer like this:
int i = 6; //automatic variable
int *pi = &i;
std::cout << pi; // you get the address of pi (hexadecimal number)
std::cout << *pi; // 6
Or you can allocate memory manually. The main thing is if you allocated memory to a variable, you also have to deallocate it or your program will have "memory leak".
int *pi = new int(6);
delete pi;
So if you place new elements in the tree, you have to allocate memory for them, and if you delete an element, you have to destruct with delete. You have to care about not to broke the list.
Related
In tree, while taking input (inside takeInput function), tree node was made using dynamic allocation, but I tried doing it statically, but as tree node were declared inside a function locally it should have not worked because its a local variable (I was expecting a error). But Why am I able print it even after that:
NOTE: this code takes input recursively (and may not be the best way)
#include<bits/stdc++.h>
using namespace std;
template <typename T>
class treeNode{
public:
T data;
vector <treeNode<T>> children;
treeNode(T data){
this->data=data;
}
};
treeNode<int> takeInput(){
int rootdata;
cout<<"Enter Node"<<endl;
cin>>rootdata;
// treeNode<int>* root= new treeNode<int>(rootdata);
treeNode<int> root(rootdata); //Static Allocation
cout<< "Enter Number of children of "<<rootdata<<endl;
int n;
cin>>n;
for(int i=0;i<n;i++){
treeNode<int> child = takeInput();
root.children.push_back(child);
}
return root;
}
void printTree(treeNode<int> root){
cout<<root.data<<": ";
for(int i=0;i<root.children.size();i++){
cout<<root.children[i].data<<",";
}
cout<<endl;
for(int i=0; i<root.children.size();i++){
printTree(root.children[i]);
}
}
int main(){
treeNode<int> root= takeInput();
printTree(root);
return 0;
}
Following code is using dynamic allocation:
#include<bits/stdc++.h>
using namespace std;
template <typename T>
class TreeNode{
public:
T data;
vector <TreeNode<T>*> children;
TreeNode(T data){
this->data=data;
}
};
TreeNode<int>* takeInput(){
int rootdata;
cout<<"Enter node"<<endl;
cin>>rootdata;
TreeNode<int>* root=new TreeNode<int>(rootdata);
cout<<"Enter number of children of "<<rootdata<<endl;
int n;
cin>>n;
for(int i=0;i<n;i++){
TreeNode<int>* child=takeInput();
root->children.push_back(child);
}
return root;
}
void printTree(TreeNode<int>* root){
if (root == NULL){
return;
}
cout<< root->data<<" :";
for(int i=0;i<root->children.size(); i++){
cout<<root->children[i]->data<<",";
}
cout<<endl;
for(int i=0;i<(*root).children.size();i++){
printTree(root->children[i]);
}
}
int main(){
TreeNode<int>* root = takeInput();
printTree(root);
return 0;
}
Your code is equivalent to
A foo() {
A a;
a = bar();
return a;
}
a is just copied into the return value (That copy might be avoided too). Replace A with treeNode<int> and the semantics remain the same.
Why then the dynamic code?
I'm guessing the code version using dynamic allocation was probably coded up thinking that something like
struct A {
std::vector<A> vecA;
};
is a recursive definition for A since when vecA is declared A is an incomplete type. But that's not the case anymore and this is officially into C++17 (though it worked for some compilers in earlier versions too) where some STL containers can do with incomplete type. Hence it used the form
vector <TreeNode<T>*> children;
storing pointers to the children and hence that code, which is similar to the familiar LinkedList Node data structure definition
struct Node {
int data;
Node* next; // The TreeNode stores a vector of pointers instead.
};
Conclusion
Stack allocation is usually preferred when possible since it's faster than the heap route. Also, that code with dynamic allocation brings in the headache of memory management unless smart pointers are being used. It's just not needed for your code. Go with the stack allocation route for your example and let std::vector take care of maintaining the dynamic array.
I am trying to figure out how the newNode addresses change each iteration of appendNode. When I convert the addresses from hexadecimal to decimal I get the values 14683824, 14683848, 14685096. While the first two addresses seem to increase by 24 the third address increases by 1248. I can't figure out why this is occurring.
//Main Program
#include <iostream>
#include "numberList.h"
using namespace std;
int main()
{
numberList list;
list.appendNode(2.5);
list.appendNode(3.4);
list.appendNode(5.6);
// list.displayList();
return 0;
}
//append.cpp
#include <iostream>
#include "numberList.h"
using namespace std;
void numberList ::appendNode(double num)
{
listNode *newNode;
listNode *nodePtr;
newNode = new listNode;
newNode->value = num;
newNode->next = nullptr;
cout << newNode << endl; //The addresses of the newNode dont have even
intervals
if(!head)
{
head = newNode;
}
else
{
nodePtr = head;
while(nodePtr->next)
{
nodePtr = nodePtr->next;
}
}
}
//numberList.h
#ifndef APPENDNODE_NUMBERLIST_H
#define APPENDNODE_NUMBERLIST_H
class numberList
{
private:
struct listNode
{
double value;
struct listNode *next;
};
listNode *head;
public:
numberList()
{
head = nullptr;
}
//~numberList();
void appendNode(double);
void displayList() const;
void insertNode(double);
void deleteNode(double);
};
#endif //APPENDNODE_NUMBERLIST_H
Output:
0xe00eb0
0xe00ec8
0xe013a8
The standard doesn't give you any guarantees about the location of memory you allocate. new could give you locations that are right next to each other, but it'd also be allowed to give you locations on a completely random basis. What specifically you end up with depends on
The algorithm used for allocation by new
The pattern of previous allocations
So why did it happen this time? In general, it makes sense for successive allocations to end up close together because that decreases the chance of a cache miss, but new has no obligation to do that. In fact, because new occasionally has to request memory from the operating system, and because new has to use a bit of memory to keep track of what's been allocated, it's not possible to guarantee that all allocations happen at regular intervals.
I have made a superclass named "tree". I have constructed the tree in this class. Now, I want to pass the root of the constructed tree to another class which is a subclass of tree. But when I try to pass it, the subclass calls the supercalss constructor and sets it to NULL;
struct node
{
struct node *left;
struct node *right;
int val;
};
struct node *create(int val)
{
struct node *temp = (struct node *)malloc(sizeof(struct node));
temp->val = val;
temp->left = temp->right = NULL;
return temp;
};
class tree
{
public:
struct node *root;
tree()
{
root = NULL;
}
void createtree()
{
root = create(5);
}
void preorder()
{
preorderp(root);
}
void preorderp(struct node *p)
{
if(!p) {
return;
}
cout<<p->val<<' ';
preorderp(p->left);
preorderp(p->right);
}
};
This is the definition of my tree class. It just creates a tree with one node having value 5. Now I want to pass the new root created to a subclass of tree.
class treeiterator:public tree
{
struct node *p;
stack<struct node *> s;
public:
treeiterator()
{
p = root;
push(root);
}
bool hasnext();
int next();
private:
void push(struct node *root);
};
I create an object for tree first and then do createtree. Now, when I create an object for treeiterator, it's member p gets sets to NULL since supercalss constructor is also called. How can I just access the tree created in the superclass in subclass?
Full code:
#include <bits/stdc++.h>
using namespace std;
struct node
{
struct node *left;
struct node *right;
int val;
};
struct node *create(int val)
{
struct node *temp = (struct node *)malloc(sizeof(struct node));
temp->val = val;
temp->left = temp->right = NULL;
return temp;
};
class tree
{
public:
struct node *root;
tree()
{
root = NULL;
}
void createtree()
{
root = create(5);
}
void preorder()
{
preorderp(root);
}
void preorderp(struct node *p)
{
if(!p) {
return;
}
cout<<p->val<<' ';
preorderp(p->left);
preorderp(p->right);
}
};
class treeiterator:public tree
{
struct node *p;
stack<struct node *> s;
public:
treeiterator()
{
p = root;
push(root);
}
bool hasnext();
int next();
private:
void push(struct node *root);
};
void treeiterator::push(struct node *t)
{
while(t) {
s.push(t);
t = t->left;
}
}
bool treeiterator::hasnext()
{
return s.empty()?1:0;
}
int treeiterator::next()
{
struct node *t = s.top();
int val = t->val;
s.pop();
if(t->right) {
push(t->right);
}
return val;
}
int main()
{
tree t;
t.createtree();
t.preorder();
treeiterator it;
while(it.hasnext()) {
cout<<it.next()<<' ';
}
}
Because of inheritance every treeiterator is also a tree. This means
treeiterator treeIt;
treeIt.createtree();
will do what OP wants. There is no need to make a separate tree and moving the root around.
However this is a bit odd in the world of C++ because OP is under-using the constructor. For example, node could be:
struct node
{
node *left;
node *right;
int val;
node(int inval):
val(inval),
left(nullptr),
right(nullptr)
// the above is a Member Initializer List. It makes sure all of your
// members are initialized before the body of the constructor runs.
{
}
};
That bit after the : in the constructor is the Member Initializer List.
Now when you allocate a node it's initialized and ready to be linked. For tree
class tree
{
public:
struct node *root; // almost certainly should not be public.
// also should be a std::unique_ptr<node>
tree(int inval)
{
root = new node(5); // note new in place of malloc. new allocates
// storage and calls constructors. malloc should
// only be used in C++ in rare edge-cases.
}
/* obsolete
void createtree()
{
root = create(5);
}
*/
...
};
tree is assigned a root on allocation. treeiterator is a wee bit trickier because it must call tree's constructor to set up root.
class treeiterator:public tree
{
struct node *p; // Don't see the point off this
stack<struct node *> s; // or this, but that's another question
public:
treeiterator(int inval):
tree(inval) // call's tree's constructor
{
}
bool hasnext();
int next();
private:
void push(struct node *root);
};
Allocating a treeiterator now guarantees that it is all ready to go with no further work.
treeiterator treeIt(5); // all done.
All of the above is covered within the first few chapters of any good C++ programming text. I recommend getting one and reading it, because right now it looks like you are trying to write bad C.
Off topic 1:
You are going to quickly find that this code is in violation of the Rule Of Three. What is The Rule of Three? If you don't know, read the link. It will save you much time and hair-pulling
Off Topic 2:
#include <bits/stdc++.h>
using namespace std;
Is a ticking time bomb. The first line includes the entire standard library, but only in GCC. Your code is now doing far, far more work than it need to to compile, is no longer standard C++, and is not portable to other compilers and may well break with the next revision of GCC. Don't use anything in bits. It internal compiler-specific stuff with no guarantees what-so-ever.
More here: Why should I not #include <bits/stdc++.h>?
The second line takes everything in the std namespace and places it in the global namespace. This leads to fun games like is reverse or std::reverse being called? Often this leads to insane and arcane compiler messages because the poor compiler is confused as hell, but sometimes it's not confused and picks the best choice among the many and silently breaks something else. Great fun debugging.
More here: Why is "using namespace std" considered bad practice?
Together you have the entire standard library pulled into your file AND stripped of it's proper namespace. This results in a vast minefield of potential hidden pain that is not worth any perceived time savings. One of the resulting bugs could cost more clean up than years of typing a few extra lines per file and characters.
No one want to clean up code with this stupid a mistake, so doing this in a professional setting can be costly.
First, you should not have root has public. This is a gross OO error. If you want it to be available to subclasses you should make it protected.
This is my first time working with any kind of tree. I created a tnode class for my tree and now I'm trying to create the class for the tree itself. However I've gotten a couple errors I can't figure out.
#ifndef Tree_Ntree_h
#define Tree_Ntree_h
// SIZE reprsents the max number of children a node can have
#define SIZE 10
// SEPERATE will allow the program to distinguish when a subtree no longer has children
#define SEPERATOR '#'
#include <iostream>
#include <fstream>
template <typename T>
class tnode{
public:
T value;
tnode *child[SIZE];
tnode() {};
tnode<T> *addChild(T data){
tnode*temp = new tnode;
temp -> value = data;
for (int i=0; i<SIZE; i++)
temp -> child[i] = NULL;
return temp;
}
};
template <typename T>
class Ntree{
private:
tnode<T> *root;
T data;
std::string filename;
public:
Ntree(){ root= NULL;}
Ntree( T data){ *root = data;}
inline T getRoot(){return root;}
My errors are in the last three lines.
In the last line of my code (getRoot), this is the error:
No viable conversion from 'tnode > *' to
'std::__1::basic_string'
In the second to last line and the third to last line (*root = data) (root = NULL) this is the error:
No viable overloaded '='
I don't understand why it is necessary to overload the = operator in this situation.
root is a tnode<T> * and getRoot is returning a T object. The compiler doesn't know how to convert one to the other. You probably just want to return root->value
However, you haven't allocated any space for root and it might be NULL, so you need to determine what to do when it is NULL.
In this line:
Ntree( T data){ *root = data;}
This time you are assigning a T to a tnode<T>, which the compiler doesn't know how to do. You also haven't allocated any memory for root. Instead you probably want todo something like:
Ntree( T data){ root = new T; root->value = data;}
Or better still have a tnode constructor that takes a value.
I have a one-dimensional template list that contains nodes, each node has a link to next node.
It works rather well on it's own, but not when it contains another linked list.
LinkedList and Node looks something like that:
template <class T>
class LinkedList
{
private:
Node<T>* pPreHead;
public:
LinkedList(void);
~LinkedList(void);
Node<T>* getHead(void);
int size();
void addElementToEnd(T& value);
void deleteNextNode(Node<T>* pNodeBefore);
}
template <class T>
class Node
{
private:
T value;
Node* next;
public:
Node();
Node* getNext();
Node* getValue();
void setNext(Node* nextElem);
void setValue(T elem);
};
Now for the task I need to use LinkedList>, which is filled via a loop.
It looks something like this:
ifstream fl;
fl.open("test1.in", std::ifstream::in);
while (fl.good())
{
string currentLine;
getline(fl, currentLine);
LinkedList<string> newDNA;
//newDNA being filled here so I skipped code
DNAStorage.addElementToEnd(newDNA);
//Place 1
}
//Place 2
Now if I insert some test output code in "Place 1" everything is fine, but when the loop enters new iteration newDNA variable gets freed and so is the pointer inside DNAStorage (which is LinkedList<LinkedList<string>> in question), and when I try to print anything in "Place 2" I get segmentation fault.
Unfortunately I can't use any other data structures since this is the kind of task I need to do.
My question is - how can this be fixed, so that it actually is not freed prematurely?
Edit:
Here's my code for AddElementToEnd(T& value):
template <class T>
void LinkedList<T>::addElementToEnd(T &value)
{
Node<T> *newtail = new Node<T>;
newtail.setNext(NULL);
newtail.setValue(value);
if(pPreHead == NULL)
{
pPreHead = newtail;
return;
}
Node<T> *tail = pPreHead;
while(tail.getNext() != NULL)
{
tail = tail.getNext();
}
tail.setNext(newtail);
}
The problem is that you are storing references to objects that are going out of scope, causing undefined behavior when you try and access them. Your LinkedList<string> newDNA gets created and destroyed with each iteration of the while loop, yet you pass a reference to be stored in DNAStorage list.
One solution would be to store a copy of each object (not reference) in the list when addElementToEnd() gets called.