struct Node
{
int w;
Node* w1;
};
int main(){
Node a;
Node *s;
}
In above code what is difference between a and *s. How are they different.Also why we use Node *s while creating a LinkList.
THANK YOU!!!
Node a is an object. It allocates some space in memory.
Node *s1 - is pointer to object of type Node, but the object itself must be created with, for example, a new operator. Or we must explicitly take and address of the object with & operator. It is just a variable that holds an address. The size of this variable depends on platform (4 bytes on x86, 8 bytes on x86_64).
Each node of a Linked list stores a pointer to the next node. That is why we need a pointer here. Thus if you you have access to the node, you can travel to the next and to the end of the list.
Disclaimer: The given code is very basic and given for explanation only. This is not how you create linked list in real-life. Manually connecting nodes is not a great pattern. I would recommend you to learn more about basic language concepts like pointers, references, object lifetime.
// Node type definition
struct Node
{
int w;
Node* w1;
};
int main() {
// Separate nodes
Node n1;
Node n2;
Node n3;
// Now this is a linked list
n1.w1 = &n2;
n2.w1 = &n3;
n3.w1 = nullptr; // to mark the end
// Get pointer to n2 from n1
Node *n2_ptr = n1.w1;
Node *n3_ptr = n2.w1;
// Check if n3 is the last element
if (n3_ptr->w1 == nullptr) {
// this is the end of the list
}
// walk the list
Node *node = &n1;
while (node != nullptr) {
node->w *= 2; // do smth with data
node = node->w1; // go to the next node
}
return 0;
}
Related
Let's say I have a linked list node like the following:
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
The goal is to write a function to delete a node in a singly-linked list. One efficient way to do it in constant time is something like this:
void deleteNode(ListNode* node) {
auto *tmp = node->next;
*node = *tmp;
delete tmp;
}
This works, but why do we need to dereference the pointers?
If node is a pointer and tmp is a pointer, why does it need to dereferenced? Why can't I do node = tmp?
When performing *node=*tmp you copy all the bytes of *tmp into *node thus
node->val now holds tmp->val and node->next now holds tmp->next.
The old content of node has been forgotten (it's normal since you want to get rid of this node) but you saved the content of the next node at this same place.
Then if you delete the next node (known through tmp) you don't lose its content (it has been saved in the previous node).
Let's break down the three lines of your deleteNode function:
auto *tmp = node->next;
This creates a local variable, tmp which will be a copy of the next field of the passed node parameter. This is a pointer to the next structure in the list and, once we've made a copy of it, we can erase or overwrite that member.
*node = *tmp;
This copies the actual data of the structure pointed to by tmp (that is, the next node in the list) to the current node, overwriting the next field as it does so. We need to dereference both pointers in order to copy the values of the structures pointed to.
delete tmp;
This deletes the 'next' node in the given list. However, we have already copied all its data (including its next member) into our current node, so our modified list now starts with (effectively) the second one in the original list (the passed parameter); notably, the next field of *node will now be the address originally stored in node->next->next – thus, we have 'skipped' an entry (the second) in the list and deleted it.
The reason you can't just write node = tmp is because that wouldn't change anything outside of your function.
Given this linked list
node0 -> node1 -> node2 -> node3
If you want to delete node1, the desired outcome would be
node0 -> node2 -> node3
If you don't want to actively modify the pointer value (that is, the address next) in node0, you have to move the value inside node2 to where node1 was.
Why can't I do node = tmp ?
You can do that, but it won't do anything useful. node is a local variable in deleteNode. As it is a pointer you can use that local pointer to modify what it points to, but modfying the pointer itself has no effect outside of the function.
Actually pointers are not different with respect to that. You also cannot observe any effect from outside when you have
void foo(int x) {
x = 42;
}
Passing a reference is different:
void bar(int& x) {
x = 42;
}
int a = 0;
bar(a); // now a == 42
Same with pointers:
void bar_ptr(int*& x) {
x = nullptr;
}
int* b = &a;
bar_ptr(b); // now b == nullptr
If you do node = tmp and after that delete tmp you will be deleting the ListNode, which node points to.
As others pointed out, node = tmp just changes the argument(local variable)
*node = *tmp is to copy the content of ListNode which is equivalent to
node.val = tmp.val; node.next = tmp.next
This function actually removes the next element - it works, but it invalidates the next pointer(if there was something that refers node->next as a pointer, it is now a dangling pointer)
What your function really does, is that it doesn't delete the node from the parameter, but the next node, overwriting the current node with the follower.
The dereferencing of the pointer acts like a memcpy() and moves the data from the next node to the current. You are not copying the pointers but the data it points to.
This way you can repeatedly call the function with the same node pointer, and it will move down the chain.
However, since you are not checking the pointer, the last node probably has a NULL pointer and will crash on derefencing.
So you need to do
if (tmp)
*node = *tmp;
Example:
typedef struct list
{
struct list *next;
int value;
} List;
void deleteNext(List* node)
{
auto *tmp = node->next;
if(tmp)
*node = *tmp;
delete tmp;
}
int main(int argc, char *argv[])
{
List *l0 = new List;
List *l1 = new List;
l0->value = 0;
l0->next = l1;
l1->value = 1;
l1->next = NULL;
deleteNext(l0);
deleteNext(l0); // Without the 'if' it will crash here.
return 0;
}
but why do we need to dereference the pointers?
Let's explore what happens if we don't indirect through the pointers:
auto *tmp = node->next;
node = tmp;
delete tmp;
This would be equivalent to just
delete node->next;
// resulting structure
previous node next (deleted) next next (leaked)
1---------->2----dangling--->_ 4
// desired structure that we get from the correct code
previous node next (deleted) next next
_
1-----------3---------------------------------->4
So, we end up with wrong node being deleted, and with a dangling pointer in the node that was supposed to be deleted.
Note that even the correct inirecting version is broken when attempting to delete the last node.
Hi I am from a Java background and quite new to C++
In my intermediate level of Java programming i never had situation where i declared an object of some
class within the body of that class, now am studying linked lists in C++, here in this code and in several
other places i have come across that pointer to that class/struct is declared within its body i.e Struct ListNode * next; in the following code
private:
// Declare a structure for the list
structListNode{
float value;
structListNode*next;
};
ListNode*head; // List head pointer
public:
FloatList(void) { // Constructor
head = NULL;
}
~FloatList(void) { }; // Destructor
void appendNode(float);
void displayList(void);
void deleteNode(float);
};
or Node * next ; in this code below
class Node {
int data; // The value stored in node
Node* next; // The address of next node
}
I can'really comprehend what it means or how is it going , can someone please explain it to me?
The pointer inside struct/class is not an "object" of that struct/class, instead, it is a pointer of the objects of the same type. It just stores/holds address of objects created somewhere else, so it can access or modify them without copying their content.
As an example;
class Node {
int data;
Node* next;
};
int main(){
Node* head = NULL; // This is a pointer, not an object.
// It points to NULL (i.e. nothing) yet.
Node n1, n2; // These two are "objects" of Node class
head = &n1; // head now points to n1, i.e. holds memory address of n1
n1.data = 10; // n1.data contains 10
n1.next = &n2; // n1.next points to the object n2
n2.data = 20; // n2.data contains 20
n2.next = NULL; // n2.next points to nothing
head->data = 5; // now, n1.data contains 5, instead of 10
head->next->data = 15; // now, n2.data contains 15, instead of 20
return 0;
}
In many occasions, we need to modify a linked list drastically so we will sometimes create another linked list and pass it to the old one. For example,
struct node { //let's say we have a linked list storing integers
int data;
node* next;
};
and suppose we already have a linked list storing integers 1,2,3.
node* head; //suppose we already store 1,2,3 in this linked list
node* new_head ; //suppose we make a temporary linked list storing 4,5,6,7
head = new_head; //modifying the original linked list
My Question
If I delete head (the old linked list) before the assignment then the whole program will crash.
Conversely, if I do not delete it, then there will be a memory leak.
Therefore, I am looking for a way to modify the linked list without memory leak.
My attempt
I tried to make a helper function similar to strcpy to do my work.
void passing_node(node*& head1, node* head2){ //copy head2 and paste to head1
node* ptr1 = head1;
for (node* ptr2 = head; ptr2 != nullptr; ptr2 = ptr2->next)
{
if (ptr1 == nullptr){
ptr1 = new node;
}
ptr1->data = ptr2->data;
ptr1 = ptr1->next;
}
}
// note that we assume that the linked list head2 is always longer than head1.
However, I still got a crash in the program and I cannot think of any other way to modify this. Any help would be appreciated.
Easier way to avoid memory leak is to avoid raw owning pointers.
You might use std::unique_ptr (or rewrite your own version):
struct node {
int data = 0;
std::unique_ptr<node> next;
};
You can move nodes.
You can no longer copy nodes (with possible double free issue).
so deep_copy might look like:
std::unique_ptr<Node> deep_copy(const Node* node)
{
if (node == nullptr) return nullptr;
auto res = std::make_unique<Node>();
res->data = node->data;
res->next = deep_copy(node->next.get());
return res;
}
I would suggest preallocating the linked list so it's easy to delete every node in one call. The nodes would then just reference somewhere inside this preallocated memory. For example:
struct Node
{
int value;
Node* next;
};
struct LinkedList
{
Node* elements;
Node* first;
Node* last;
Node* free_list;
LinkedList(size_t size)
{
first = nullptr;
last = nullptr;
elements = new Node[size]{0};
free_list = elements;
for (size_t i = 0; i < size-1; ++i)
free_list[i].next = &free_list[i+1];
free_list[count-1].next = nullptr;
}
~LinkedList()
{
delete[] elements;
}
void Add(int value)
{
if (free_list == nullptr)
// Reallocate or raise error.
// Take node from free_list and update free_list to
// point to the next node in its list.
// Update last node to the new node.
// Update the first node if it's the first to be added.
}
void Free(Node* node)
{
// Search for the node and update the previous and
// next's pointers.
// Update first or last if the node is either of them.
// Add the node to the last place in the free_list
}
};
From here you'll have many strategies to add or remove nodes. As long as you make sure to only add nodes to the allocated elements array, you'll never have any memory leak. Before adding, you must check if the array have the capacity to add one more node. If it doesn't, you either have to raise an error, or reallocate a new the LinkedList, copy over all values, and delete the old one.
It becomes a bit more complicated when the array becomes fragmented. You can use a 'free list' to keep track of the deleted nodes. Basically, a LinkedList of all nodes that are deleted.
Just take notice that my code is incomplete. The basic approach is to create an allocator of some sort from which you can allocate a bulk, use segments of it, and then delete in bulk.
Normally, I would just input head = new Node in main, which would set everything up, but the stipulation is that I do not have permission to mess with global variables. This is an assignment where I only have access to main, and due to other backend features, I have to leave the global variables intact so I can't overwrite it with head = new Node.
The point is just to add characters to a linked list. I just hardcoded inserting one just as an example, but I still can't avoid the error.
Is there a correct way to add them?
struct Node{
char key;
Node *next;
};
Node *head = NULL;
int main(){
char x = 'a';
cout<<x<<endl;
head->key=x;
}
assignment:
Find all nodes in a BST that are between a given range of values. Then build a linked list of the values and the list should be in ascending order.
NOTE: the head of the linked list is declared globally in the back end and its initial value is NULL. Just add the nodes to the linked list using head. The printing of the linked list will also be done in the backend. Helper functions can be used.
void RangeSearch(TreeNode *node, char m, char n);
Head is just a pointer, pointing to NULL. There is no real object / memory allocated for Node. You have first to allocate memory for it.
In your assignment, you can and should (as far as i understand it) add nodes to linked list, so you will have to allocate new nodes .
struct Node {
char key;
Node *next;
};
Node *head = NULL;
int main() {
char x = 'a';
head = new Node();
cout << x << endl;
head->key = x;
delete head;
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
class Node{
public:
int data;
Node * next;
};
void Append(Node * head, int newdata){
Node * n = head;
if(n->next != NULL)
{
n = n->next;
}
n->data = newdata;
cout<<"data-> "<<newdata<<" inserted!"<<endl;
}
void Display(Node * head){
Node * n = head;
if(n->next != NULL)
{
cout<<"data->"<<n->data<<endl;
n = n->next;
}
cout<<"data->"<<n->data<<endl;
}
int main(int argc, char * argcv[])
{
Node * headnode;
int newdata = 20;
Append(headnode, newdata);
Display(headnode);
return 0;
}
The output of this program is:
data-> 20 inserted!
data->1
data->20
Why the headnode has been assigned a "1" data member here?
Besides the comments, the problem here is that you are sending a pointer to a Node in your append function without initializing the data and the pointer that it contains.
On the if(n->next != NULL) inside append, n->next will also be random data, meaning that you will assign the value 20 not to the "head" but to the node that the head points to.
That is why the value 20 is on the next node when printing, and random value of (in this case 1) is in your head node.
You need to use the new in order to allocate the Nodes in the memory, as dereferencing a pointer that isn't pointing to allocated memory will most likely cause segfaults.
Apart from the comments and answer by #Milan, I think the design of class Node can be better implemented. It's not always required to expose data members( i.e., Node::data ) and especially in this case. class Node can also have member functions that does appending a new link and display the linked list. To get an idea, think of the way the container std::list is implemented( i.e., its member functions ). Take the advantage of powerful feature, data hiding, in C++.