This question already has answers here:
When to use an elaborated type specifier
(5 answers)
Closed 2 years ago.
I was trying to make a tree in c++ and came across this code which is really confusing me.
struct node
{
int data;
struct node* left;
struct node* right;
};
// The code bellow this is the part i dont understand
struct node* newNode(int idata)
{
node* node = new struct node;
node->data = idata;
node->left = NULL;
node->right = NULL;
return node;
}
what is struct node* ? Some kind of a structure, but a pointer? Also shouldn't structs have ; at the end? For example, node has ; at the end of the body but not node* ?
struct node* is the return type of function newNode() and not a definition in itself. The line you are referring to is the signature of the function newNode. It is followed by the function definition between the two curly braces {}. A function definition does not need a ; at the end.
Related
Today I was taught Linked list in class and I wanted to implement it on my own.
Here's the part of the code that I wrote. Note that traverseLL traverses the Linked list and insertAtEnd inserts a new node at the end of the linked list.
I believe I can implement Linked list logic / methods / functions on my own. But my question is, inside insertAtEnd function when I create a newNode with the parameters - my data to be inserted, and nullptr (because inserting at the end), It inserts garbage values (or memory addresses maybe) in my node, ignoring the data passed to the constructor.
using namespace std;
#define NL '\n'
class Node {
public:
int data;
Node* next;
Node (int data, Node* nextPtr=nullptr) {
data = data;
next = nextPtr;
}
};
void insertAtEnd(Node* &head, int data) {
Node* newNode = new Node(data, nullptr); // <---- Issue in this line
// When I do as above, my linkedlist nodes always store garbage values and not the data being passed.
// However, when I un-comment the below line, I get the correct output.
// newNode->data = data;
if (head == nullptr)
head = newNode;
else {
Node* temp = head;
while (temp->next != nullptr)
temp = temp->next;
temp->next = newNode;
}
}
void traverseLL(Node* head) {
if (head == nullptr)
return;
while (head->next) {
cout << head->data << " -> ";
head = head->next;
}
cout << head->data << NL;
}
int main() {
Node* head = nullptr;
insertAtEnd(head, 10);
insertAtEnd(head, 20);
insertAtEnd(head, 30);
traverseLL(head);
return 0;
}
For example, the output for the above code when keeping newNode->data = data line commented, is :
16259544 -> 16258392 -> 16258392
But when I un-comment that line, my output becomes, which is intended:
10 -> 20 -> 30
Why is this happening? Even though I've defined my constructor, why is it not working?
I think the cause for this is the statement data = data in the constructor.
Reason for this:
Before executing the first statement of constructor, the member variables of the class are allocated memory and contain junk/default values, and when the statement data = data is seen the compiler changes the parameter but not the member variable.
As a result, you are seeing junk/garbage values.
To resolve this we can either explicitly specify the member using this or use member initialization syntax.
You can use any of the following workarounds.
Workarounds:
You can change your class constructor code like any of the below formats:
1.
class Node {
public:
int data;
Node* next;
Node (int data, Node* nextPtr=nullptr) {
this->data = data; // we are explicitly specifying which data to use
next = nextPtr;
}
};
class Node {
public:
int data;
Node* next;
Node (int d, Node* nextPtr=nullptr) {
data = d; // as the member variable and local variable are of different names, no conflict
next = nextPtr;
}
};
class Node {
public:
int data;
Node* next;
// use the member initialization syntax
// Here we are initializing the data while allocating memory itself,
// so answer is perfectly right!
Node (int d, Node* nextPtr=nullptr) : data(data), next(nextPtr) {}
};
More on the member initialization and constructor:
https://en.cppreference.com/w/cpp/language/constructor
How do C++ class members get initialized if I don't do it explicitly?
Hope this helps,
Thanks.
This question already has answers here:
Binary Search Tree Destructor
(6 answers)
Closed 2 years ago.
Please help me. I am stuck at this.
What am I trying to do: Binary search tree.
I am a C# developer and I learn C++ for about 2 weeks, therefore don't be so harsh with me and that's why pointers are still difficult for me.
I have a struct Node
struct Node
{
int Value;
Node* _LeftNode;
Node* _RightNode;
Node(int value)
: Value(value), _LeftNode(NULL), _RightNode(NULL)
{
}
};
and a Delete() function in BinarySearchTree.cpp
void BinarySearchТрее::Delete(Node* node)
{
if (node)
{
Delete(node->_LeftNode);
Delete(node->_RightNode);
delete(node);
node = NULL;
}
}
I want to delete the node and all of its child nodes.
When I first step in the recursion... For example:
I have two child nodes with values 10 and 19.
With recursion, I delete the nodes and set the pointers to NULL.
And here is the problem:
When I came out from the recursion the nodes are not NULL, but something strange.
And this is my problem. Why when I am in the recursion and I NULL the pointer everything is fine, but when I come out the pointer is something else.
As I talked in the comments, I think the thing is that how we can reset the pointer of the parent's(left or right child) of the initially passed node. (recursively deleting a node and its all children looks good.)
And I don't think it is possible in your current design. As Node does not contain a pointer to its parent, so there is no way to know who's the parent. node = NULL sets just the argument(local variable)'s value so it is pointless.
The C++ way would be to use std::unique_ptr.
struct Node
{
int Value;
std::unique_ptr<Node> LeftNode;
std::unique_ptr<Node> RightNode;
Node(int value)
: Value(value)
{
}
};
Then to destroy a node and all of its children, you'd call reset on the appropriate std::unique_ptr<Node>
I think what you actually want ist this:
struct Node
{
int Value;
Node* _LeftNode;
Node* _RightNode;
Node(int value)
: Value(value), _LeftNode(NULL), _RightNode(NULL)
{
}
~Node() {
delete _LeftNode;
delete _RightNode;
}
};
This way you are using the destructor to clean up recursivly.
delete nullptr is ok btw.
EDIT:
the unique_ptr<> usage in one of the other answers is probably the smarter way to do this.
Given:
struct Node
{
int data = 0;
struct Node * left = nullptr, * right = nullptr;
Node(int data) { this->data = data; }
};
This recursive function deletes a node & its childs (+ one comment):
void DeleteTree(struct Node* node) // A copy of the caller pointer
{
if (node)
{
DeleteTree(node->left); // Recur on left subtree
DeleteTree(node->right); // Recur on right subtree
delete node;
// node = nullptr; <-- This line is useless
}
}
To your wondering "but when I come out the pointer is something else":
There is no point in node = nullptr line, since when you call DeleteTree(my_node) function, node is a copy of my_mode, so when you set node = nullptr it has no effect on my_node that on exit from DeleteTree(my_node) points to a deleted, invalid object.
--
Possible solution:
#define DELETE_TREE(node) DeleteTree(node); node = nullptr; // Macro
int main()
{
struct Node* root = new Node(1);
root->left = new Node(2);
root->right = new Node(3);
root->left->left = new Node(4);
root->left->right = new Node(5);
DELETE_TREE(root->left); // root->left became nullptr
DELETE_TREE(root); // root became nullptr
return 0;
}
After DeleteTree function, the caller pointer points to an invalid object since its object already released. A possible solution is to define a DELETE_TREE Macro to "auto-nullify" the caller pointer after DeleteTree function.
--
Implementation with Modern C++ Smart Pointers:
#include <memory>
struct Node
{
int data = 0;
std::unique_ptr<Node> left, right;
Node(int data) { this->data = data; }
};
int main()
{
std::unique_ptr<Node> root;
root = std::make_unique<Node>(1);
root->left = std::make_unique<Node>(2);
root->right = std::make_unique<Node>(3);
root->left->left = std::make_unique<Node>(4);
root->left->right = std::make_unique<Node>(5);
root.reset();
return 0;
}
This question already has answers here:
Function does not change passed pointer C++
(4 answers)
Closed 5 years ago.
I am trying to implement a simple stack in C++ using a linked list, but I am completely stumped by the PUSH() function. I've been working on it all night and it's nearly driven me bonkers. It should insert an element at the top of the stack, but every way I've tried to implement is has had issues. An excerpt of my relevant code is as follows:
template <typename T>
struct NODE{
T data;
NODE<T> *next;
}
template <typename T>
void PUSH(T x, NODE<T> *S){
NODE<T> *tmp = new NODE<T>;
tmp->data = x;
tmp->next = S;
S = tmp;
}
int main(){
NODE<int> *test = new NODE<int>;
test->data = 111;
test->next = NULL;
PUSH(99, test);
PUSH(88, test);
std::cout << test->data << std::endl;
}
I would expect the last line to print 88, but instead it prints 111. When I try to access the next element, I get a segfault so clearly I must be doing something wrong. Maybe I'm just tired, but hopefully one of you could shine some light on where I'm messing up, it seems correct to me.
void PUSH(T x, NODE<T> *S)
{
}
You are passing S by value, so any changes you make to S inside PUSH will not be visible outside.So even though you are adding elements to your stack, but your top remains the first node (111).
You can either pass a pointer to pointer to S or a reference to S
void PUSH(T x, NODE<T> **S)
{
NODE<T> *tmp = new NODE<T>;
tmp->data = x;
tmp->next = *S;
*S = tmp;
}
I have a question on linked list, and they defined a Node struct:
struct Node {
int data;
struct Node* next;
}
that i can't change, so i created new struct in oreder to succeed answering the question:
struct tmpNode{
int data;
bool visit = false;
struct Node* next;
} t;
now i'm trying to do the folowing code but it failed on the last line - the purpose is to create parallel list with the struct i created:
t.data = head->data;
t.visit = true;
t.next = head->next;
t = t.next;
what am i doing wrong?
Thanks
You are trying to assign incompatible types. Type of t.next is Node*, while type of t is tmpNode.
Looked at every similar question on this compiler error. The following minimized code reproduces the error and I cannot see what the issue is. From reading here on SO, suspect it's the return type node* (being a struct) is invalid, but what else to specify as the return type? Thank you.
Header file:
#include<cstdio>
#include<cstdlib>
class double_clist {
struct node {
int info;
struct node *next;
struct node *prev;
};
node *start;
node *last;
int counter;
public:
node *create_node(int);
double_clist() {
start = NULL;
last = NULL;
}
};
Implementation File:
#include<cstdio>
#include<cstdlib>
node* double_clist::create_node(int value) { // Error on this line.
counter++;
struct node *temp;
temp = new(struct node);
temp->info = value;
temp->next = NULL;
temp->prev = NULL;
return temp;
}
When it reaches node here, it hasn't seen that it is inside double_clist yet. You need to also preface that with double_clist::.
double_clist::node* double_clist::create_node(int value) {