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.
Related
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.
This bit of code inserts at the tail of a linked list and it works perfectly when the head node is not null, i.e. it already points to some linked list.
void Insert(node *head,int x)
{
if (head==NULL)
{
head=new node;
head->key=x;
head->next=NULL;
}
else
{
link=head;
while (link->next!=NULL)
{
link=link->next;
}
link->next=new node;
link->next->key=x;
link->next->next=NULL;
}
}
For the first part of the code, if the head node is Null, which it initially is, I simply put in the data and pointer in the node.
When its not null, the 'link' node begins at the head of the list and traverses till the tail, therein I put in the node.
This bit of code below, which only takes one function works in all cases. Why is that? head is equal to NULL and globally defined in both cases.
void insert(int x)
{
if (head==NULL)
{
head=new node;
head->key=x;
head->next=NULL;
}
else
{
link=head;
while (link->next!=NULL)
{
link=link->next;
}
link->next=new node;
link->next->key=x;
link->next->next=NULL;
}
}
Note: This is not an assignment or homework or anything related. I am just trying to learn basic stuff regarding linked lists and this is a problem i came across while doing some stuff on Hacker Rank.
In case anyone's interested in the display function:
void display()
{
node *trav=head;
while (trav!=NULL)
{
cout<<trav->key;
trav=trav->next;
}
}
Struct has been defined in my program.
struct node
{
int key;
node *next;
}
For the sake of convenience, I have defined head pointer globally, but with some slight adjustments i could change that. I think. Also 'link' is also global in case anyone's confused where it came from.
node *head = NULL;
node *link = NULL;
So to summarize, the question is :
Why does it work in one argument but not for the two arguments version when head is NULL.
In the first function, where you pass head as an argument, you pass the argument by value. That means inside the function head is a copy of the value you pass when calling the function, and modifying a copy will not modify the original.
You need to pass the argument by reference, which is easily done in C++ using the ampersand (&) when declaring the argument:
void Insert(node *& head,int x) { ... }
// ^
// Note ampersand here
That tells the compiler that head is a reference to the original variable you use when you call the function.
Hello I am trying to use pointers and learning the basics on unique pointers in C++. Below is my code I have commented the line of code in main function. to debug the problem However, I am unable to do so. What am I missing ? Is my move() in the insertNode() incorrect ? The error I get is below the code :
#include<memory>
#include<iostream>
struct node{
int data;
std::unique_ptr<node> next;
};
void print(std::unique_ptr<node>head){
while (head)
std::cout << head->data<<std::endl;
}
std::unique_ptr<node> insertNode(std::unique_ptr<node>head, int value){
node newNode;
newNode.data = value;
//head is empty
if (!head){
return std::make_unique<node>(newNode);
}
else{
//head points to an existing list
newNode.next = move(head->next);
return std::make_unique<node>(newNode);
}
}
auto main() -> int
{
//std::unique_ptr<node>head;
//for (int i = 1; i < 10; i++){
// //head = insertNode(head, i);
//}
}
ERROR
std::unique_ptr>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)' : attempting to reference a deleted function
Aside from other small problems, the main issue is this line:
return std::make_unique<node>(newNode);
You are trying to construct a unique pointer to a new node, passing newNode to the copy constructor of node. However, the copy constructor of node is deleted, since node contains a non-copyable type (i.e. std::unique_ptr<node>).
You should pass a std::move(newNode) instead, but this is problematic since you create the node on the stack and it will be destroyed at the exit from the function.
Using a std::unique_ptr here is a bad idea in my opinion, since, for example, to print the list (or insert into the list), you need to std::move the head (so you lose it) and so on. I think you're much better off with a std::shared_ptr.
I was having the same problem and indeed using a shared_ptr works.
Using the smart pointer as an argument in the function copies the pointer (not the data it points to), and this causes the unique_ptr to reset and delete the data it was previously pointing at- hence we get that "attempting to reference a deleted function" error. If you use a shared_ptr this will simply increment the reference count and de-increment it once you are out of the scope of that function.
The comments in the answers above suggest that using a shared_ptr is baseless. These answers were written before the C++17 standard and it is my understanding that we should be using the most updated versions of the language, hence the shared_ptr is appropriate here.
I don't know why we have to expose node type to user in any case. Whole thingamajig of C++ is to write more code in order to write less code later, as one of my tutors said.
We would like to encapsulate everything and leave no head or tail (pun intended) of node to user. Very simplistic interface would look like:
struct list
{
private:
struct node {
int data;
std::unique_ptr<node> next;
node(int data) : data{data}, next{nullptr} {}
};
std::unique_ptr<node> head;
public:
list() : head{nullptr} {};
void push(int data);
int pop();
~list(); // do we need this?
};
The implementation does something what Ben Voigt mentioned:
void list::push(int data)
{
auto temp{std::make_unique<node>(data)};
if(head)
{
temp->next = std::move(head);
head = std::move(temp);
} else
{
head = std::move(temp);
}
}
int list::pop()
{
if(head == nullptr) {
return 0; /* Return some default. */
/* Or do unthinkable things to user. Throw things at him or throw exception. */
}
auto temp = std::move(head);
head = std::move(temp->next);
return temp->data;
}
We actually need a destructor which would NOT be recursive if list will be really large. Our stack may explode because node's destructor would call unique_ptr's destructor then would call managed node's destructor, which would call unique_ptr's destructor... ad nauseatum.
void list::clear() { while(head) head = std::move(head->next); }
list::~list() { clear(); }
After that default destructor would ping unique_ptr destructor only once for head, no recursive iterations.
If we want to iterate through list without popping node, we'd use get() within some method designed to address that task.
Node *head = list.head.get();
/* ... */
head = head->next.get();
get() return raw pointer without breaking management.
How about this example, in addition to the sample code, he also mentioned some principles:
when you need to "assign" -- use std::move and when you need to just traverse, use get()
I am working on some binary tree algorithms and need a "find node with searchindex..." function. The design for treenodes is basically
class TreeNode {
int index; // some identifier
TreeNode *left;
TreeNode *right;
}
and a tree is defined by a pointer to the root-node.
My implementation for the search function is:
void Tree::searchNode(TreeNode * root, int nodeIndex, TreeNode *resultNode){
/* Recursive search */
if (root->index == nodeIndex) {
resultNode = root;
} else {
/* search children if the current node is not a leaf */
if(!root->isLeaf()) {
this->searchNode(root->left,nodeIndex,resultNode);
this->searchNode(root->right,nodeIndex,resultNode);
}
}
}
Arguments: *root is the root-node of the tree, nodeIndex is the search-index and *resultNode is the pointer to the found (or not) node in the tree.
The function does not return a reference or pointer to the found node but modifies the pointer resultNode so it points to the found node. The idea is to initialize resultNode with NULL, perform the search and modify it if a match occurs. Otherwise it remains NULL and I can easily check if there are search results or not.
Another class with a tree buildingTree as member utilizes the search-function in this way:
TreeNode *resultNodePtr = NULL;
this->buildingTree->searchNode(this->buildingTree->rootPtr,
currentNodeIndex, resultNodePtr);
// do sth. with resultNodePtr if != NULL
I create *resultNodePtr on the stack because I just need it temporarily inside the function. Is this done correctly? However: The function does not work. resultNodePtr is always NULL, even if the tree contains a node with the search-index. I debugged it very carefully step by step, it detects
(root->index == nodeIndex)
correctly but
resultNode = root;
does not work (I want resultNode to point to the same adress root points to).
Debugger says resultNode before assignment is 0x0, root node is some adress, after the assignment resultNode remains 0x0.
Do I have to overload the operator= in this case for the class TreeNode?
I have tried it:
TreeNode & TreeNode::operator=(const TreeNode & oldTreeNode){
*this = oldTreeNode;
return *this;
// ignore childs for now
}
I am not an expert but this operator= seems trivial. Does it affect the assignment of two TreeNode pointers *node1 = *node2 at all?
Maybe you can help me. Thanks for reading, appreciate your help.
If I find a solution myself I will post it here.
Regards,
Mark
Because you pass resultNode into the function as a pointer by value, its original value never changes. Think of TreeNode* as literally nothing more than a number representing a memory address; when you reassign it:
resultNode = root;
This modifies the copy that searchNode has, but not the original pointer in the code which invokes searchNode. Take this simpler example:
void Foo(int x)
{
x = 100;
}
void Bar()
{
int x = 0;
Foo(x);
// at this point, x is still 0
}
resultNode's value doesn't change from NULL for the same reason that x doesn't change from 0 when the function Bar is invoked. To fix this issue, pass the pointer in as a pointer to a pointer, or a pointer by reference:
void Tree::searchNode(TreeNode* root, int nodeIndex, TreeNode*& resultNode)
{
// same code
}
... or:
void Tree::searchNode(TreeNode* root, int nodeIndex, TreeNode** resultNodePtr)
{
// assign to *resultNodePtr instead
}
Your resultNode pointer is being passed by value, not by reference. So when the function call completes the pointer on the calling side does not receive a value.
Your algorithm looks fine :)
I have a method in a static class which tries to convert a binary tree to a list
I'd like to make it recursive but I couldn't
I've implemented some other methods in my class like add(), delete(), find().
Here is the code
class ARB
{
private:
struct BT
{
int data;
BT *l;
BT *r;
};
struct BT *p;
public
ARB();
~ARB();
void del(int n);
void add(int n);
};
void ARB::del(int num)
{
//The code ,don't care about it
};
main()
{
//
BTR T;
T.add(3);
T.add(5);
};
Here is what should we do to transfer the code from binary tree to list.
LLC ARB::changeit()
{ LLC x;
while(this!=NULL)
{
x.add(this->data); //
if(this.l==NULL)
{
x.print(); //To print the elemnts of List
return(x);
}
else
{
x=changeit(this.l);
}
if(this.r!=NULL)
{
x.~LLC();
x=changeit(this.r);
return(x);
}
}
}
The description of the problem is hard to follow but I noticed that you used the keywords this and static, which are generally mutually exclusive.
Any static function pertains to a class, not an object. Static functions can be called using the ARB::myStaticFunction() syntax and do not require an actual ARB object. So, this inside such a function does not refer to any object and is meaningless.
This call is meaningless:
x=changeit(this.l);
Since this refers to the ARB object that has no member called l. The same goes for this code:
this->data
You sometimes do this.data and sometimes this->data so you seem to be confused over the notion of an object pointer. Your ARB has the BT* called p which is the tree root, supposedly. You should start from it.
Also this is obviosly wrong:
x.~LLC();
Don't call the destructor of LLC explicitly!
The general algorithm for recursively placing a binary tree into a list (pseudocode):
tolist(node, list):
if node == NULL:
return
else:
tolist(node.left, list)
list.append_to_end(node.data)
tolist(node.right)
This assumes append_to_end of list is efficient, to make sense (this is achievable with an end pointer in the list). Also, it takes a list as an argument and modifies it. You can easily change it to have an internal recursive method that does that and an external method that creates a list, calls this method, and returns the list.