I was going through a 'generictree' class designed by my instructor, and couldn't understand a concept.
There was a function in it which returned to the user, the node containing the highest value, below is its code.
const Node<T> * getLargestNode() const {
return getLargestNodeHelper(root);
}
I understand that we require a helper function, because we need to do it recursively, and hence require an argument. Therefore, a helper function is required to pass the root as argument, because root cannot be passed as argument from main function, as access to internal data members is not required.
Below is the code for helper-function
private:
static const Node<T> * getLargestNodeHelper(const Node<T> * node) {
if (node == NULL) {
return NULL;
}
const Node<T> * largest = node;
for (int i = 0; i < node->children.size();i++) {
const Node<T> * childlargest = getLargestNodeHelper(node->children[i]);
if (childlargest->data > largest->data) {
largest = childlargest;
}
}
return largest;
}
Now, when I was trying to create same class on my own, I created the helper function as shown below,
private:
const Node<T> * getLargestNodeHelper(const Node<T> * node) const {
if (node == NULL) {
return NULL;
}
const Node<T> * largest = node;
for (int i = 0; i < node->children.size();i++) {
const Node<T> * childlargest = getLargestNodeHelper(node->children[i]);
if (childlargest->data > largest->data) {
largest = childlargest;
}
}
return largest;
}
Now, the doubt I am having is, is there any disadvantage on using my version of the helper-function. What is the difference between the two, as both cannot change the data members and both cannot be called from the object?
If your method is not static, you need an object of that class to be able to call it (even if it doesn't care about the object you call it on). This comes - depending on situation - with the overhead of creating a dummy object and destroying it, just to use it once to call.
Static methods can be called without an object.
In your simple example there is no useful difference because getLargestNode() always requires an object. But in more complex class there could be other public but static member funcion that needs such helper function. In that case your function could not be called (code is not reused). One more thing is speed and memory (for very limited systems). Argument with pointer to object could take a place in the stack (in some systems). getLargestNodeHelper() is called recursively so more memory and more time.
It's all about reusing of code. And don't give to a recursive function more than it requires.
Related
I have a simple question. I have a LinkList class and root is initiated inside the class.
class LinkList {
struct node {
int data;
shared_ptr<node> next;
};
shared_ptr<node> root;
public:
void insert(int data);
void remove(int data);
void print();
int length();
bool search_recursive(int data);
bool search_recursiveUtil(shared_ptr<node> p, int data);
}
Ideally I wanted to implement a recursive function to search for a node. Now I implemented in the following way:
bool LinkList::search_recursiveUtil(shared_ptr<node> p, int data){
if(p == nullptr){
return false;
}
if(p->data == data){
return true;
}
return search_recursiveUtil(p->next, data);
}
bool LinkList::search_recursive(int data){
shared_ptr<node> p = root;
return search_recursiveUtil(p, data);
}
Now clearly you can see that since I do not want root to reach at the end of the linked list as other functions might use this head pointer to do something, I am taking a shared pointer P and traversing it. Now I want to have p to be pass to the "search_recursive" function but since it doesn't take shared_ptr argument so I had to take support of a "search_recursiveUtil" function.
My question is it is right way to approach? How can i implement this without having util function support?
Beside the consideration on why using a recursive search (the will soon result in a stack overflow as soon as the list becomes big enough) instead of a iterating one, since pointers are passed by value, there is no need of p: just call return search_recursiveUtil(root, data). Your reasoning abut root to reach the end of the list is a misconception.
The use of an xUtil function taking a positional parameter not required when calling the search from outside can be a good idea, just make it private to the class, so that -from outside- your interface will be just the search_recursive function.
Also, declare both the functions const, since they are not supposed to modify the data.
An alternative can be place the "Util" function as a node member, so that you can do
bool LinkList::node::search_recursiveUtil(int src_data){
if(data == src_data)
return true;
if(pnext == nullptr)
return false;
return pnext->search_recursiveUtil(src_data);
}
called as
bool LinkList::search_recursive(int data){
root->search_recursiveUtil(data);
}
In principle, that's exactly the way to go:
You have your interface function with the necessary parameters that calls an internal function with the required parameters. This way you keep your root member variable hidden. You could/should even declare your util member function private.
I'm making a rather simple version of a linked list which is accessed through a Link class. The goal here is to make an advance() method that will be used to traverse the list. However, the most lightweight solution I have involves using a const_cast which is undesirable. Is there solution to this that I have not considered?
Link* Link::advance(int n) const
{
if(!this) return nullptr;
Link* it = const_cast<Link*>(this);
if(n > 0) {
while(n--) {
it = it->next(); //the next link in the list
}
}
else if(n < 0) {
while(n++) {
it = it->previous(); //the previous link in the list
}
}
return it;
}
This is more of a semantical problem than it seems.
By having the signature: Link* Link::advance(int n) const
What this means is that given a node instance of your linked list you want it to provide access to one of its brother node wether in front or behind it.
The interesting part is the following: A node does not own its brothers.
They all kind of exist at the same level. This is even more obvious given that the same node is pointed to by a next and a previous pointer at the same time from different other node instances.
The reason why your node can provide access to other nodes it doesn't own, is because he has a link to a non const instance of them (a next and a previous pointer). And that is the only reason. This has nothing to do with the current node instance itself and thus justify the const of the advance member function.
Now the only real problem comes from the fact that a node has no link to itself, and thus cannot provide access to itself the same way it can provide access to one of its brother.
There are two ways to take actions based on that:
1) Either you change the base facts of this situation, which means changing Link* Link::advance(int n) const, and there are multiple ways to do this like removing the const, adding an iterator concept and other methods, returning const instances etc. each takes a different approach angle.
2) Or you keep on this path which means you need to have a link on yourself too to totally respect the semantic you have given to your function:
class Link
{
public:
Link()
:
previous_(nullptr),
current_(this),
next_(nullptr)
{}
// ...
Link* advance(int n) const;
// ...
Link* previous() const { return previous_; }
Link* next() const { return next_; }
// ...
private:
Link *previous_;
Link * const current_;
Link *next_;
};
Link* Link::advance(int n) const
{
//if(!this) return nullptr;
Link* it = current_;
if(n > 0) {
while(n--) {
it = it->next(); //the next link in the list
}
}
else if(n < 0) {
while(n++) {
it = it->previous(); //the previous link in the list
}
}
return it;
}
I have been using C# for around a year and have recently been testing my patience with the harsh world of C++.
I am trying to create an object orientated binary tree. I have stepped through the code and read up on reference parameter passing and use of const in C++ but cannot work out what I am doing to cause an Access Violation Error. I have ensured that the structure is created properly and the code completes the first line of main as expected, however calling toString seems to result in an error and I cannot work out why.
Here is the code so far:
// ExpressionCL.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
using namespace std;
template<class TData> class TreeNode
{
private:
TData Data;
const TreeNode<TData>* Left = nullptr;
const TreeNode<TData>* Right = nullptr;
void setData(TData data)
{
Data = data;
}
public:
TreeNode<TData>(TData data)
{
setData(data);
}
TreeNode<TData>(TData data, const TreeNode<TData>& leftNode, const TreeNode<TData>& rightNode)
{
setData(data);
setLeft(leftNode);
setRight(rightNode);
}
void setLeft(const TreeNode<TData>& leftNode)
{
Left = &leftNode;
}
void setRight(const TreeNode<TData>& rightNode)
{
Right = &rightNode;
}
TreeNode<TData> getLeft() const
{
if (hasLeft())
{
return Left;
}
}
TreeNode<TData> getRight() const
{
if (hasRight())
{
return Right;
}
}
TData getData() const
{
return Data;
}
bool hasLeft() const
{
if (Left != nullptr)
{
return true;
}
else
{
return false;
}
}
bool hasRight() const
{
if (Right != nullptr)
{
return true;
}
else
{
return false;
}
}
string toString() const
{
string treeString = "";
if (hasLeft())
{
treeString += Left->toString();
}
treeString += to_string(Data);
if (hasRight())
{
treeString += Right->toString();
}
return treeString;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
TreeNode<int> IntTree(1, TreeNode<int>(1), TreeNode<int>(2));
cout << IntTree.toString() << endl;
return 0;
}
Some guidance or further recommended resources would be great.
Your setLeft and setRight functions set off alarm bells. Storing the address of an object that was passed by reference is seriously asking for trouble, as the caller may destroy the object and then you are left with dangling pointers for Left and Right.
In fact that is exactly what you do. You pass temporary objects to your constructor, storing their address in Left and Right. Then you call IntTree.toString() which tries to use pointers to objects that no longer exist.
To fix this you need to need to use manual lifetime management for your nodes. That means the node must be created via new. You have the option of either using raw pointers (in which case you would document your interface carefully to note that the caller should call new, pass in the pointer, and not call delete after).
The other option is to use smart pointers which will track ownership of the objects, however you have a few other problems to solve before doing that.
Specifically, treeNode does not currently follow the Rule of Three. Fixing this is extremely important. At a minimum, disable copying so that you do not accidentally make copies of a treeNode (which will not behave properly until you start following the Rule of Three)).
Using smart pointer classes means you can follow Rule of Zero instead of Rule of Three which makes for much cleaner code (although it may be difficult to do straight off the bat if you're new to C++, there aren't any good online teaching resources that I know of besides SO).
You are calling the Treenode constructor with temporary values and storing in the treenode pointer to these temps.
After the constructor has finished, these temps are gone and in calling a function which uses pointers to those temps (toString), a crash is occurring.
Your design needs the values of the treeitems as long as the tree is used, because you store only pointers to those values in the tree.
You could change the design to store copies of the treenodes within the tree.
First of all I am sorry for this silly question, but I am new to the world of C++ and I am used to Java and Python.
I would like to ask how are constructors supposed to work in C++. I would expect that if I assign some value or sub-object to my instance then it will not be deleted by another constructor?
Particularly my problem is following:
I have class Tree that looks like this:
class Tree {
Node * const first;
Node * last;
std::vector<Node *> nodesVector;
unsigned int nodes;
public:
Tree(Node * const root) : first(root){
nodes = 1;
nodesVector.push_back(root);
}
}
And then I have class RRTStar that looks like this:
class RRTStar {
Tree * tree;
Node * root;
const double RADIUS;
public:
RRTStar(const Point & point, double radius) : RADIUS(radius){
Node n;
n.point = point;
unsigned int zero = 0;
n.id = zero;
n.cost = 0;
n.parent = NULL;
this->root = &n;
Tree t = Tree(this->root);
this->tree = &t;
}
}
As you can see there is always appended one value to the vector from the Tree's constructor which is called from RRTStar constructor. When I go through debug I can see that there is really added the Node n to the vector, but unfortunately it is then somehow deleted after the RRTStar constructor finishes.
So my question is what am I doing wrong that vector or it's content of the tree instance is deleted?
These two lines look most suspect:
this->root = &n;
this->tree = &t;
They are taking the address of a local variable, which will be destroyed when the constructor completes. Any use of those pointers outside of the constructor will be UB.
You need to dynamically allocate them using new, and make sure your destructor, copy constructor, and assignment operator handle them appropriately.
I don't consider myself all that knowledgeable in C++ but I'm having a hard time with this concept. So I have a class the holds some template datatype and a double. I want the m_data variable to be generic, but right now I'm only testing with an unsigned int. When I call the function SetData() with say a pointer to an unsigned int I lose the info the pointer is pointing to. This happens when I go out of scope, so I felt I need to do a deep copy of it...
I tried many different constructors and assignment operators but I still lose the info... I feel I'm missing something obvious about templates here.If anyone could point me in the right direction as to why the data is being lost I would be very grateful.
Small bit of code:
template<typename T>
class PointNode {
public:
PointNode(double p){ m_point = p;}
~PointNode();
void SetData(T * data);
T * GetData() const;
private:
double m_point;
T *m_data;
};
template<typename T>
void PointNode::SetData(T * data)
{
m_data = data;
}
template<typename T>
T * PointNode::GetData()
{
return m_Data;
}
OK some more info. This class is being stored in a map that is a member of another class. Heres a bit of it.
template<typename T>
class AuMathPointTreeT
{
public:
//Member Variables
double m_dTolerance;
unsigned int m_cPoint;
map<VectorKey, PointNode<T> > m_tree; /*map posing as a tree */
typename map<VectorKey, PointNode<T> >::iterator iter; /* iterator */
pair< typename map<VectorKey, PointNode<T> >::iterator, bool > return_val;
/* Tree methods */
//constructor
AuMathPointTreeT(double tol);
...
};
In another program I'm using this class, creating node and setting the template data like so
if (node = pnttree.AddPoint(point) )
{
unsigned int * data = new unsigned int();
*data = pntCount;
node->SetData(data);
++pntCount;
}
UPDATE: Ok discovered the culprit of what's wrong, and would like suggestions on how to approach it. When I insert a node into the map class a few functions are called in the process and im losing the original pointer to the newly allocated node class object. Here is what I'm doing.
template<typename T>
PointNode<T> * AuMathPointTreeT<T>::
AddPoint(double point)
{
PointNode<T> * prNode = MakeNode(point);
m_cPoint++;
return prNode;
}
template<typename T>
PointNode<T> * AuMathPointTreeT<T>::
MakeNode(double point)
{
PointNode<T> * prNode = new PointNode<T>;
//set the contents for the node just performs a few calcs on the values
prNode->SetNode(point, m_dTolerance);
//Create the key class using the
VectorKey key(point, m_dTolerance);
//Store the key,node as a pair for easy access
return_val = m_tree.insert( pair<VectorKey, PointNode<T> >(key, *prNode) );
if (return_val.second == false)
prNode = NULL;
unsigned int * test = new unsigned int;
*test = 55;
prNode->SetData(test); //if call this here its no longer the right pointer
return prNode;
}
So after looking at this... I really still want to return a pointer and use it. But maybe the iterator being held by return_val? Im open on suggestions for all aspects too.. Sorry this question has been a mess :\
I don't think this has anything to do with the use of templates. Once a local variable goes out of scope, its location on the stack could be over-written by other data.
If you expect the template class instance to out-live the local variable whose address is passed to SetData, you should consider allocating the data on the heap not the stack. Either way, I'd suggest replacing the raw m_data pointer with an appropriate smart pointer. For example, the use of shared_ptr<> in the template class and its client code should reduce the amount of data copying while at the same time ensuring the data remains valid regardless of whether or not the original data variable is in scope.
If you want a deep copy, you must use T and not T*, or you must do dynamic memory allocation with T* (but it's overkill) and will bring a similar result.
If you really want Nodes of pointers, it will be when you use your Node.
Exemple:
int number = 5;
Node<int*> oneNode(&number); // number will die at end of scope
Node<int> anotherNode(number); //anotherNode can be used without risk
your code will not compile because of your constructor
PointNode(double p){ m_point = p;}
m_point is const, you have to write it to the initializer list:
PointNode(double p) : m_point(p) {}