headnode of singly Linked list has default value? - c++

#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++.

Related

Why no "delete" after "new" in linked list insert node

I have been trying to understand memory allocation in C++ by reading some texts and looking stuff up. I have seen often that one should always call "delete" after "new". However, I also see code like this:
void LinkedList::add(int data){
Node* node = new Node();
node->data = data;
node->next = this->head;
this->head = node;
this->length++;
}
In structures like linked lists or stacks.
I have seen some great explanations on SO like:
Why should C++ programmers minimize use of 'new'?
When to use "new" and when not to, in C++?
However I am still confused why one would not call "delete" here for a new Node.
Edit: Let me clarify my question. I understand why not to immediately call delete in the same method. However, in the same code I do not see a matching delete statement for add. I assume that everything is deleted once the program ends, but I am confused that there is no apparent matching delete statement (ie: count all the news in the code, count all the deletes in the code, they do not match).
Edit: Here is the source that I am looking at: https://www.geeksforgeeks.org/linked-list-set-2-inserting-a-node/
The code for their linked list:
// A complete working C++ program to demonstrate
// all insertion methods on Linked List
#include <bits/stdc++.h>
using namespace std;
// A linked list node
class Node
{
public:
int data;
Node *next;
};
/* Given a reference (pointer to pointer)
to the head of a list and an int, inserts
a new node on the front of the list. */
void push(Node** head_ref, int new_data)
{
/* 1. allocate node */
Node* new_node = new Node();
/* 2. put in the data */
new_node->data = new_data;
/* 3. Make next of new node as head */
new_node->next = (*head_ref);
/* 4. move the head to point to the new node */
(*head_ref) = new_node;
}
/* Given a node prev_node, insert a new node after the given
prev_node */
void insertAfter(Node* prev_node, int new_data)
{
/*1. check if the given prev_node is NULL */
if (prev_node == NULL)
{
cout<<"the given previous node cannot be NULL";
return;
}
/* 2. allocate new node */
Node* new_node = new Node();
/* 3. put in the data */
new_node->data = new_data;
/* 4. Make next of new node as next of prev_node */
new_node->next = prev_node->next;
/* 5. move the next of prev_node as new_node */
prev_node->next = new_node;
}
/* Given a reference (pointer to pointer) to the head
of a list and an int, appends a new node at the end */
void append(Node** head_ref, int new_data)
{
/* 1. allocate node */
Node* new_node = new Node();
Node *last = *head_ref; /* used in step 5*/
/* 2. put in the data */
new_node->data = new_data;
/* 3. This new node is going to be
the last node, so make next of
it as NULL*/
new_node->next = NULL;
/* 4. If the Linked List is empty,
then make the new node as head */
if (*head_ref == NULL)
{
*head_ref = new_node;
return;
}
/* 5. Else traverse till the last node */
while (last->next != NULL)
last = last->next;
/* 6. Change the next of last node */
last->next = new_node;
return;
}
// This function prints contents of
// linked list starting from head
void printList(Node *node)
{
while (node != NULL)
{
cout<<" "<<node->data;
node = node->next;
}
}
/* Driver code*/
int main()
{
/* Start with the empty list */
Node* head = NULL;
// Insert 6. So linked list becomes 6->NULL
append(&head, 6);
// Insert 7 at the beginning.
// So linked list becomes 7->6->NULL
push(&head, 7);
// Insert 1 at the beginning.
// So linked list becomes 1->7->6->NULL
push(&head, 1);
// Insert 4 at the end. So
// linked list becomes 1->7->6->4->NULL
append(&head, 4);
// Insert 8, after 7. So linked
// list becomes 1->7->8->6->4->NULL
insertAfter(head->next, 8);
cout<<"Created Linked list is: ";
printList(head);
return 0;
}
// This code is contributed by rathbhupendra
The code you cited should delete the nodes at some point. Indeed, that code shows off tons of bad C++ practices. It doesn't delete the nodes because it's bad code.
Oh and BTW: ignore anything on the site you linked to. If there is something useful on that site, it's only by accident.
Generally new does a couple of things. It allocates memory for an object, on the heap (where dynamic memory resides), and initialises an object at the address.
When you have variables in your function like this:
void example(){
int a;
char b;
}
They reside on the stack, and when the function returns, those variables no longer exist. With new you can get memory outside the stack (on the heap). The good thing is that this persists throughout function calls. The bad thing that it persists across function calls. It's good because sometimes array lengths are not known and therefore they can not be allocated on the stack, or you need a large buffer which would not fit on the stack. It's bad because if you forget about it, then it won't go away. It will just sit there taking up memory. delete, basically destructs the object at the address, and then returns the memory to the OS. That's why people say that delete should be called after new.
Luckily in modern c++ you (generally) don't need to use raw pointers and not need to worry about this. std::shared_ptr<T> created by std::make_shared<T,Args...>, and std::unique_ptr<T> created by std::make_unique<T,Args...>. These are wrappers for pointers. std::shared_ptr<T> is just T*, but when everybody loses the pointer to the object, the memory is returned. std::unique_ptr<T> is the same, but only one reference exists.
A std::unique_ptr<T> LinkedList from cppreference:
#include <memory>
struct List {
struct Node {
int data;
std::unique_ptr<Node> next;
Node(int data) : data{data}, next{nullptr} {}
};
List() : head{nullptr} {};
// N.B. iterative destructor to avoid stack overflow on long lists
~List() { while(head) head = std::move(head->next); }
// copy/move and other APIs skipped for simplicity
void push(int data) {
auto temp = std::make_unique<Node>(data);
if(head) temp->next = std::move(head);
head = std::move(temp);
}
private:
std::unique_ptr<Node> head;
};
As to an other reason the use of new should be minimised: Apart from the above issue of potential memory leak, is that it is very expensive (std::make_shared/std::make_unique still has this issue though), as the program needs to ask the kernel to grant it some memory, meaning an expensive system call must be made.

Passing a linked list without memory leak in C++

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.

Getting wrong output with custom linked list implementation

I am learning list in C++ independently, and i have searched many websites about it. However, almost every approach to create a list is the same.
They usually create a struct as the node of a class. I want to create a class without using struct. So I created a class name ListNode which contains an int data and a pointer.
The main member functions of my class are AddNode and show.
Although, this program compiles successfully, it still does not work as I wish.
Here is the header file:
#ifndef LISTNODE_H_
#define LISTNODE_H_
#pragma once
class ListNode
{
private:
int data;
ListNode * next;
public:
ListNode();
ListNode(int value);
~ListNode();
void AddNode(ListNode* node,ListNode* headNode);
void show(ListNode* headNode);
};
#endif
Here is the implementation:
#include "ListNode.h"
#include<iostream>
ListNode::ListNode()
{
data = 0;
next = NULL;
}
ListNode::ListNode(int value)
{
data = value;
next = NULL;
}
ListNode::~ListNode()
{
}
void ListNode::AddNode(ListNode* node,ListNode* headNode) {
node->next = headNode;
headNode =node;
}
void ListNode::show(ListNode* headNode) {
ListNode * traversNode;
traversNode = headNode;
while (traversNode != NULL) {
std::cout << traversNode->data << std::endl;
traversNode = traversNode->next;
}
}
Main function:
#include"ListNode.h"
#include<iostream>
int main()
{
using std::cout;
using std::endl;
ListNode* head = new ListNode();
for (int i = 0;i < 3;i++) {
ListNode* Node = new ListNode(i);
head->AddNode(Node, head);
}
head->show(head);
return 0;
}
As far as I am concerned, the output should be
2
1
0
However, the output is a single zero. There must be something wrong in the AddNode and show function.
Could you please tell me what is wrong with these two functions?
When you call head->AddNode(node, head) you´re passing the memory directions which the pointers point, when the function arguments receive those directions, they are now pointing to the same directions, but those are another pointers, no the ones you declared in main. You could see it like this:
void ListNode::AddNode(ListNode* node,ListNode* headNode) {
/*when the arguments get their value it could be seen as something like:
node = Node(the one from main)
headNode = head(the one from main)*/
node->next = headNode;
/*Here you are modifying the new inserted node, no problem*/
headNode = node;
/*The problem is here, you´re modifying the memory direction
headNode points to, but the headNode argument of the function, no the one declared in main*/
}
So the pointer head in main() always points to the same first node you also declared in main().
In order to fix this you should change your code this way:
void ListNode::AddNode(ListNode* node,ListNode** headNode) {
/* second paramater now receives a pointer to apointer to a node */
node->next = *headNode;//the same as before but due to pointer syntaxis changes a bit
*headNode = node;//now you change the real head
}
And when you call it:
head->AddNode(Node, &head);//you use '&' before head
Now the real head, no the one in the function, will point to the last node you inserted.

C++ Linked Lists and Pointers to Pointers

First post but I have been a lurker for some time now :)
First, I am attempting to execute this skeleton code in Visual Studio 2015 and it should work as is according to my teacher so I am not sure what else could be wrong client side that may be causing that.
Finally, the overall issue here is I am not sure how to complete the remain commands. I understand the basic concepts of how the pointer to pointers work as well as the linked lists but not completely. My first issue is not helping either.
Any help would be greatly appreciated.
Thanks,
Several
#include <stdio.h>
#include <stdlib.h>
typedef struct _node {
int value;
struct _node *next;
} node;
void append(node**, int);
void prepend(node**, int);
void lprint(node*);
void destroy(node*);
int main(int argc, char **argv)
{
node *head = NULL;
append(&head, 1);
append(&head, 2);
append(&head, 3);
prepend(&head, 0);
prepend(&head, -1);
prepend(&head, -2);
lprint(head);
destroy(head);
return 0;
}
void append(node **head, int value)
{
if (*head == NULL)
{
*head = (node*)calloc(0, sizeof(node));
(**head).value = value;
}
else
{
node *temp;
for (temp = *head; (*temp).next != NULL; temp = temp->next);
(*temp).next = (node*)calloc(0, sizeof(node));
(*temp).(*next).value = value;
}
}
void prepend(node **head, int value)
{
}
void lprint(node *head)
{
node *temp;
for (temp = head; temp != NULL; temp = temp->next)
{
printf("%d ", temp->value);
}
printf("\n");
}
void destroy(node *head)
{
}
I was able to compile and run your code after changing this line:
(*temp).(*next).value = value;
to this:
(*temp).next->value = value;
When I ran it, it printed out:
1 2 3
... which is what I would expect, given that prepend() isn't implemented.
I could write an implementation of prepend() and post it here, but I don't want to risk doing your homework for you; instead I'll just describe how prepend() ought to work.
For the case where head is NULL, prepend() can do the exact same thing that append() does: allocate a node and set head to point to that node.
For the other case, where head is non-NULL (because the list is non-empty), it's pretty easy too -- even easier than the append() implementation. All you need to do is allocate the new node, set the new node's next pointer to point to the existing head node (*head), and then set the head pointer (*head) to point to the new node.
The destroy() function can work with a loop very similar to the one in your lprint() function, with one caveat -- you have to grab the next pointer out of a given node (and store it into a local variable) before you free() the node, because if you free the node first and then try to read the next-pointer from the already-freed node, you are reading already-freed memory which is a no-no (undefined behavior) and will cause bad things (tm) to happen.

Create and print a Linked list

#include <iostream>
using namespace std;
struct node
{
int num;
node * next;
};
//Create a list, if list is not empty have at least first middle and last node
void cList (node *);
//inserts a node
void iANode(node *);
//Inserts in order
void iIOrder(node *);
void main(){
int numM;
node *list, *current;
list = new node;
current = list;
cout<<"Input"<<endl;
cin>>numM;
//creates a list
void clist(node * record){
node * head = new node;
(*head).d1=0;
(*head).next =0;
return head;
}
//inserts a node
void iANode(node * record)
{
(*newnode).next = (*pred).next;
(*pred).next= new node;
++(*phead).counter;
}
//inserts in order
void iIOrder(node * new node, node*head){
node *pred = head;
int i = (*new node).d1;
node*succ=(*pred);
}
}
I am trying to create a linked list and sorting it after each user input.
Currently getting a whole lot of compile errors. Id appreciate if someone could help and point me in the right direction.
Thanks in advance.
Compile Errors:
Local function definitions are illegal for "cList" and "iANode"
";" missing after "node * record)"in cList
Expecting ")" after node in "void iIOrder(node * new node"
use struct node *next, instead of node *next. Same applies to *list and *current
some compilers does not accept void main(), try using int main()
put all function implementation outside main()
declare *current and *list as global variables (outside main())
C++ is case sensitive, cList is different from clist. fix cList implementation
not an error, but use -> operator: head->num = 0;
there is no field d1 in structure node (function cList and iIOrder). Use field num.
to nullify a pointer use NULL instead of 0
cList function is void, but you are returning a pointer, change return value
in iANode function you are using a lot of undeclared variables. You probably want to use *list, *current and *record.
There is a bunch of analythic errors, but you asked for syntax errors. Maybe you will find more errors later, try to fix theses first.