I am trying to use a recursive function to insert nodes into a binary search tree. However, when I try to call my function, I get the error message
no known conversion for argument 1 from ‘Node*’ to ‘Node*&’
This is the code for the recursive function and the function that calls it:
bool BST::add(int data)
{
if (root == NULL)
{
Node* gnu = new Node(data);
root = gnu;
return true;
}
return recursiveAdd(root, data);
}
bool BST::recursiveAdd(Node*& start, int data)
{
if (start == NULL)
{
Node* gnu = new Node(data);
start = gnu;
return true;
}
if (data < start->getData())
{
return recursiveAdd(start->getLeft(), data);
}
if (data > start->getData())
{
return recursiveAdd(start->getRight(), data);
}
if (data == start->getData())
{
return false;
}
return false;
}
The following are the functions for getLeft(), getRight(), and getData() from my Node class:
int Node::getData()
{
return data;
}
Node* Node::getLeft()
{
return leftChild;
}
Node* Node::getRight()
{
return rightChild;
}
I would really appreciate it if someone could show me what I need to fix for it to work properly.
Thanks!
You can't bind a temporary variable (the copies returned by getLeft and getRight) with a non-const lvalue reference, hence the error.
You shouldn't need to modify the pointer itself anyway. I'd suggest you rewrite your algorithm to work without this rather strange and error-prone requirement.
Your accessors return copies of the internal pointers
Node* Node::getLeft()
{
return leftChild;
}
Node* Node::getRight()
{
return rightChild;
}
But recursiveAdd needs to be able to modify the structure
start = gnu;
These approaches aren't compatible, and you were lucky the compiler caught you. You can either change getLeft() and getRight() to return references, or capture the structure change made by recursiveAdd() and propagate it using a mutator.
Node* theLeft = start->getLeft();
bool did_insert = recursiveAdd(theLeft, data);
start->setLeft(theLeft);
return did_insert;
Or, as Matt says, you can make recursiveAdd a friend and just do
return recursiveAdd(start->leftChild, data);
...
if (root == NULL)
{
Node* gnu = new Node(data);
root = gnu;
return true;
}
return recursiveAdd(root, data);
}
Block scope. If root is NULL, you're going to end up with no declaration for root outside of the block. This means that recursiveAdd() will be called with an invalid parameter; this cannot compile or else it would always have the opportunity to yield undefined behavior.
Regardless, since root will expire, so will the reference, as the reference will point to a temporary object. This is incorrect, as references cannot be bound to temporary objects--they, by definition, will point to "containers of values," often called lvalues in C++11 parlance.
There are also rvalues, but that is outside the scope of the question.
Related
I'm a beginner in c++. and I was writing a link list in which I can call my function for inserting nodes like this:
(assuming a and b and c are data which I want to insert in link list.
list.insert(a)->insert(b)->insert(c);
and I did it like this:
#include <iostream>
using namespace std;
class Node {
public:
char letter;
Node* next;
};
class link_list {
private:
Node* head;
public:
link_list() {
head = NULL;
}
link_list* insertNewNode(char item);
};
link_list* link_list::insertNewNode(char item) {
Node* temp;
temp = new Node;
temp->letter = item;
temp->next = head;
head = temp;
return this;
}
int main() {
link_list list;
list.insertNewNode('a')->insertNewNode('b')->insertNewNode('c');
return 0;
}
in my insertNewNode function I'm returning a pointer to my current object.and it's working fine ,however I'm not sure if my method is right?
But I should also explain what happen , if instead of returning a pointer or reference to my current object ,I return my current object.
so I tried this:
class Node {
public:
char letter;
Node* next;
};
class link_list {
private:
Node* head;
public:
link_list() {
head = NULL;
}
link_list insertNewNode(char item);
};
link_list link_list::insertNewNode(char item) {
Node* temp;
temp = new Node;
temp->letter = item;
temp->next = head;
head = temp;
return *this;
}
int main() {
link_list list;
list.insertNewNode('a')->insertNewNode('b')->insertNewNode('c');
return 0;
}
and then I received an error which said list should be a pointer ,so I changed my main to:
int main() {
link_list *list;
list = new link_list;
list->insertNewNode('a')->insertNewNode('b')->insertNewNode('c');
return 0;
}
but I'm still receiving this error which said here list->insertNewNode('a')->insertNewNode('b')->insertNewNode('c'); expression must have a pointer type and these two errors:
1.type 'link_list' does not have an overloaded member 'operator ->'
2.'->link_list::insertNewNode': left operand has 'class' type, use '.'
so here is my questions for purpose of calling insert function like this list.insert(p1)->insert(p2)->insert(p3);, is my way in first program right ? and also is it even possible to return my current object for this purpose? and what would happen if I return current object?
PS:sorry for long question and also thanks in advance for your help.
Well, there's nothing criminal in your current method returning a pointer. Not something done very often, still quite compilable.
More idiomatic would be to return current object by-reference:
link_list &insert(char elem) {
return *this;
}
Your initial problem was that you changed method's return type, but retained -> in main(). If you change insert's return type to reference from pointer, then chained calls should be done via ., as you're working with objects and references to them, not with pointers.
Returning a copy of current object from a setter is not something that should be done, especially if you manage private resources on your own and haven't defined a proper copy constructor yet. Rather return a reference.
Your method seems fine. You are doing
link_list* insertNewNode(char) {
// ...
return this;
}
so that you can chain the insertions like this
list.insertNewNode('a')->insertNewNode('b')->insertNewNode('c');
You could also return a reference to the link_list, like this
link_list& insertNewNode(char) {
// ...
return *this;
}
and now chaining the insertions looks like this
list.insertNewNode('a').insertNewNode('b').insertNewNode('c');
Note that you shouldn't do something like
link_list insertNewNode(char) {
// ...
return *this;
}
because this will compile, but you would be returning a copy of the linked list, and the chaining would simply not work.
If your nodes would be added to the tail, the default copy constructor would make it appear as if chaining works, because the original link_list would see all Nodes added to the copy.
In your implementation, you are adding Nodes at the head, so the original link_list doesn't see Nodes added to the copy, and so the chaining doesn't appear to work. This is good, because the copies would leak the memory they allocate, even if you write a proper destructor.
I have a function like this..
unique_ptr<Node> test(unique_ptr<Node> &&node, string key)
{
if(!node)
{
return make_unique<Node>(key);
}
else
return node;
}
I want to create a node if the node is null, or to return the node. but it errors out saying "use of deleted function 'std::unique_ptr' ". What have I done wrong?
The problem is the way you are calling the function. But first of all you should accept your std::unique_ptr by value, not r-reference.
Then you need to std::move() your pointer when calling the function:
// accept by value
std::unique_ptr<Node> test(std::unique_ptr<Node> node)
{
if(!node)
return std::make_unique<Node>();
return node;
}
int main()
{
auto n = std::make_unique<Node>();
n = test(std::move(n)); // move the pointer
}
A std::unique_ptr can't be copied otherwise it would not be unique. You hav to move them.
I am trying to add element in a Set using Binary Tree:
bool TreeSet::add(const string &str)
{
if (treesize == 0)
{
TreeNode->data = str;
treesize++;
return true;
}
else
{
if (str < TreeNode->data)
return insert(TreeNode->left, str);
else if (str > TreeNode->data)
return insert(TreeNode->right, str);
else
return false;
}
return false;
}
bool TreeSet::insert(TREE *node, const string &str) //private
{
if (node == NULL)
{
node = new TREE;
node->data=str;
node->left = NULL;
node->right = NULL;
treesize++;
return true;
}
else
{
if (str < node->data)
return insert(node->left, str);
else if (str > node->data)
return insert(node->right, str);
else
return false;
}
return false;
}
As you can see, I want to initialize a TREE struct inside of insert and when I finish doing this I want to link it with the left or right node of the tree.
But when I gdb this, only 1 level of tree (top level) can be constructed, the *left and *right node are NULL no matter how many strings I was trying to add to it. Why?
My TREE is:
typedef struct tree
{
string data;
tree *left;
tree *right;
} TREE;
bool TreeSet::insert(TREE *node
should be
bool TreeSet::insert(TREE *&node
Pointers can also be passed by reference, and should be if you intend to modify them directly. Otherwise you pass by copy and you now have two pointers pointing at the same location. When you use the copied one to new up some data, it now points to a new memory location, leaving your original pointer still as NULL (nullptr in C++11)
On a side note, when a tree gets constructed, you should probably initialize left and right to NULL (nullptr in C++11):
typedef struct tree
{
string data;
tree *left;
tree *right;
tree():left(NULL),right(NULL){}
} TREE;
When you pass a pointer as a parameter in the function insert like this:
bool TreeSet::insert(TREE* node, const string& str);
then the pointer is copied into the argument node. Pointing node to something else only points the local copy of the pointer. The pointer passed to the function from the call site is unchanged.
node = new TREE; // Points local variable 'node' to newly allocated data.
// When the function goes out of scope 'node' will be destroyed
// and the memory will be leaked.
To change where the original call site pointer points, take the parameter by reference (or add another level of indirection):
bool TreeSet::insert(TREE*& node, const string& str);
By taking a parameter by reference, you make sure you are accessing the call site variable and not a local copy.
OK, I'm trying to write the stack pop method using linked lists for my C++ homework.
Let me just show you the node and list classes first, then tell you the problem:
class Node
{
public:
int data;
Node* next;
Node(int data, Node* next = 0)
{
this->data = data;
this->next = next;
}
};
class List
{
private:
Node* head; // no need for the tail when using the list for implementing a stack
public:
List()
{
head = 0;
}
void add_to_head(int data)
{
if(head == 0)
{
head = new Node(data);
}
else
{
head = new Node(data, head);
}
}
Node* get_head()
{
return head;
}
// this deletes the head element and makes 'head' points to the node after it.
void delete_head()
{
// storing the head so that we could delete it afterwards.
Node* temp = head;
// making the head point to the next element.
head = temp->next;
// freeing memory from the deleted head.
delete(temp);
}
};
Now here's the stack:
class stack
{
private:
List* list;
public:
stack()
{
list = new List();
flush();
}
void push(int value)
{
list->add_to_head(value);
}
bool pop(int& value_to_fill)
{
if(is_empty())
{
return false; // underflow...
}
value_to_fill = list->get_head()->data;
// deleting the head. NOTE that head will automatically point to the next element after deletion
// (check out the delete_head definition)
list->delete_head();
return true; // popping succeed.
}
bool peek(int& value_to_fill)
{
if(is_empty())
{
return false;
}
value_to_fill = list->get_head()->data;
return true;
}
// other stuff...
};
Now the problem is with pop and peek, I just don't find them to be convenient.
pop and peek shouldn't be given any parameters, but if I do this:
int peek()
{
if(is_empty())
// what should I do here?
return list->get_head()->data;
}
int pop()
{
if(is_empty())
// same thing here.
// deleting the tos then returning it.
// I know this is not what the pop in the STL stack does, but I like it this way
int tos = list->get_head()->data;
list->delete_head();
return tos;
}
I don't know what to do when an underflow occurs.
I can't just return -1 or 0 or something like that, cuz this will look like as if I popped -1 or 0 (tos == -1 or 0)
Is there a way of writing an anti-underflow pop/peek without having to pass anything by reference?
It's a question of specification. There are several possible solutions:
Make it a pre-condition of pop that the stack isn't empty. It is
the client's responsibility to ensure this (perhaps by calling
is_empty() before popping), and a violation of the precondition
results in an assertion failure.
Throw an exception if the stack is empty. This is the most obvious
solution, but probably the least generally applicable.
Don't have pop return a value (or have it return your bool). To
get the top element, you have a separate function, tos(), and a client
who wants to do both needs two function calls: x = s.tos(); s.pop();.
This is what the standard does, for example. In practice, it is often
the preferred method, because for types where copying can throw (e.g.
std::string), it's impossible to implement pop to return a value and
give the strong exception guarantee. (Whether this is a problem or not
is another issue, but it could be a problem in specific cases, and it is
the motivation behind the choice in the standard, where none of the pop
functions return a value.)
In the end, the important thing is for you to define the interface, so
that your user knows what to expect.
And by the way, you don't need the if in add_to_head. If head ==
NULL, you're going to call the constructor with the second argument
NULL, so you might as well just pass head in both cases.
(I'll skip the fact that using a linked list is a remarkably inefficient
way to implement a stack, since the code is obviously a learning
exercise.)
This a const member function, which allow me to get the minimum node of the tree:
BinarySearthTree* BinarySearchTree::min() const
{
// Return the minimum node (left-most node) value of the tree
BinarySearchTree * next = (BinarySearchTree *) this;
for (next ; next != NULL; next = next->pLeft)
if (next->pLeft == NULL)
return next;
}
I have to cast down the const-ness of 'this' pointer when assigning it to 'next', but this actually rises the potential that I may modify the value of what 'this' points to? Rather than always remind myself not to modify whatever 'next' points to, is there a way to prevent it happening by a better designing of the function?
Make next const:
const BinarySearthTree* BinarySearchTree::min() const
{
// Return the minimum node (left-most node) value of the tree
const BinarySearchTree *next;
for (next = this; next != NULL; next = next->pLeft)
if (next->pLeft == NULL)
return next;
return NULL;
}
If you don't want the contents to be modified, then you should make min() return a pointer to a const object.
Your next variable should also be a pointer to a const object, therefore.
Here is how I think your method should look:
const BinarySearchTree* BinarySearchTree::min() const
{
// Return the minimum node (left-most node) value of the tree
for (const BinarySearchTree* next = this; next != NULL; next = next->pLeft)
{
if (next->pLeft == NULL)
{
return next;
}
}
return this;
}
Also, in C++, you should avoid C-style casts. The const_cast exists for this purpose:
BinarySearchTree* next = const_cast<BinarySearchTree*>(this);
But that is not necessary in this instance.