Why is this code stuck in an infinite loop? - c++

Why is head is going to some random value?
// Simple insertion at the starting of link list
#include<iostream>
using namespace std;
struct node{
int d;
node *next;
}; // creation of node
node *head=new node; // is there any problem?
void insert(int x)
{
if (head==NULL) { // is there something wrong?
head->d=x;
haad->next=NULL;
} else {
node *t=new node;
t->d=x;
t->next=head;
head=t;
}
}
int main() {
insert(1); // function calling
insert(2); // function calling
insert(3); // function calling
while(head!=NULL) {
cout<<head->d<<" ";
head=head->next;
} // this is going on to infinity
return 0;
}
This code is lopping till infinity and I am not able to understand why?
Why is head going to some random value after 3 2 1? Is there any problem in declaring head globally?

head is going to some random value because the last element in your list is pointing with next to a random value.
This last element is the first node you created in this line:
node *head=new node;
By doing that, you are allocating memory for this node on the heap, however, you're not setting any values to the node's fields, including next. Then in the loop, when head is pointing to the last node (that was allocated first) head->next is not NULL and therefore the loop continues.
Three side notes:
Using head itself to iterate over the list elements is not a good idea since you're losing the pointer to the head of the list.
head can be declared globally but usually you should have a good reason for that. In your program I'd define it in main() and pass it to the functions that need it.
This code:
if (head==NULL) { // is there something wrong?
head->d=x;
haad->next=NULL;
doesn't make lots of sense: it will never run, and in case it will --> segmentation fault (because if head is NULL you cannot refer to its fields.
Hope it helps.

Related

Printing elements of a linked list, but instead, it prints reversed C++

here i simply wanted to print the elements of the linked list i created but it is printing the list in REVERSE order. looks like there is a mistake in the code.help me solve it
push function adds node to linked list every time we input element to be inserted in linked list.I've passed reference of head and data. A node gets dynamically created every time push fuction called. I am using c++ here.
#include<iostream>
using namespace std;
class node{
public:
int data;
node* next;
};
//creating linked list
void push(node** head_ref,int new_data) //passing address of head and data to put in list
{
node* new_node=new node(); //new node created
new_node->data=new_data; //data inserted
new_node->next=*(head_ref);
*(head_ref)=new_node;
}
int main()
{
node* head=NULL;
int n;
cin>>n; //number of elements in linked list
for(int i=0;i<n;i++)
{
int val;
cin>>val;
push(&head,val); //push function which creates a linked list
}
//while loop for printing elements of linked list
while(head!=NULL)
{
cout<<head->data;
head=head->next;
}
return 0;
}
What you currently do is assigning each node to be the predecessor of the current head, so in the end your head will be the latest element you added , its successor the second last element, its successor the third last element etc. and thus resulting to a reversed list.
You should assign the new node as successor of the current "head", like this:
void push(node** tail_ref,int new_data) //passing address of tail and data to put in list
{
node* new_node=new node(); //new node created
new_node->data=new_data; //data inserted
(*tail_ref)->next= new_node;
*(tail_ref)=new_node;
}
Note that I renamed head_ref to tail_ref in the snippet above, which better describes what the pointer actually represents: a pointer to the current last element of the list, hence the tail of the list.
Of course, you will need to save the pointer to the first element. Otherwise you won't be able to iterate through your linked list.
Extension to Simon's answer, which is correct so far:
You already have a class 'node' – why not create a class 'list' or 'linked_list' as well:
class LinkedList
{
node* m_head = nullptr;
node* m_tail = nullptr;
};
Now you always have head and tail combined and don't need to store them separately. Note that in above example, they are both private. That's actually how you should design your class. If you don't, then you allow a user to break the list implementation from outside (someone might, for instance, just set one of these pointers to nullptr, producing a memory leak in case of head).
However, now you will have to provide appropriate means to access and modify the list:
class LinkedList
{
public:
void append(int new_data); // as Simon proposed
void prepend(int new_data); // your implementation
int head();
int tail();
void dropHead();
//void dropTail(); // is an O(n) operation with singly linked list, though!
private:
node* m_head = nullptr;
node* m_tail = nullptr;
};
The node class is very closely linked to your list, you might consider not letting it be a stand-alone class, but making it a nested class instead. There's yet quite a bit to add (e. g. how to iterate over the list). To get some hints I recommend to peek a bit into STL and get familiar with the concept of iterators.
Finally: Stop re-inventing the wheel. STL already provides fully implemented doubly (std::list) and singly (std::forward_list) linked lists. It's fine to experiment with an own implementation to get to know how the winds blow, but once you know, switch back to STL.

Data Structure in C++. insertion in the beginning of the node in linked list

I am learning data structures in C++. This is a simple program for insertion
using links and nodes. The insertion takes place at the beginning of the node.
I do not understand some parts of the code.
In the function display() the pointer np points to the inserted info and then takes the value of the previous info using the next node. The next pointer is pointing to the previous info using the insert_beginning() function.
Displaying is done using the while loop. How does the next pointer change its value during each loop?
PS: The program runs fine.
#include<iostream>
#include<process.h>
#include<cstdlib>
using namespace std;
struct node
{
int info;
node *next;
}*start,*newptr,*save,*ptr;
node *create_new_node(int);
void insert_beg(node*);
void display(node*);
/*----------------------------------------------------------------------------------------------------------------------------
The pointer 'start' points to the beginning of the list.
Function 'create_new_node()' takes one integer argument , allocates memory to create new node and returns
the pointer to the new node.(return type: node*)
Function 'insert_beg()' takes node* type pointer as an argument and inserts this node in the beginning of the list.
Function display takes node* type pointer as an argument and displays the list from this pointer till the end of the list
------------------------------------------------------------------------------------------------------------------------------
*/
int main()
{
start=NULL;
int inf;
char ch='y';
while(ch=='y'||ch=='Y')
{
system("cls");
cout<<"enter information for the new node ";
cin>>inf;
cout<<"\ncreating new node. Press enter to continue ";
system("pause");
newptr = create_new_node(inf);
if(newptr!=NULL)
{
cout<<"\nnew node created successfully. Press enter to
continue. ";
system("pause");
}
else
{
cout<<"\nCannot create new node. ABORTING!! ";
exit(1);
}
cout<<"\nnow inserting this node in the beginning of the list.
Press enter to continue ";
system("pause");
insert_beg(newptr);
cout<<"\nNow the list is \n";
display(start);
cout<<"\nPress 'Y' to enter more nodes, 'N' to exit\n";
cin>>ch;
}
return 0;
}
node *create_new_node(int n)
{
ptr=new node;
ptr->info=n;
ptr->next=NULL;
}
void insert_beg(node *np)
{
if(start==NULL)
start=np;
else
{
save=start;
start=np;
np->next=save;
}
}
void display(node *np)
{
while(np!=NULL)
{
cout<<np->info<<" ->";
np=np->next;
}
cout<<"!!!\n";
}
To cut the long story short - per my understanding, your basic question is:-
display is done using the while loop. how does the next pointer change
its value during each loop??
This happens precisely in this line:-
np=np->next;
You are basically advancing the pointer to the node structure to another node structure whose address is in next member of the first node structure. This is text book stuff and any basic algo book should cover this thoroughly
HTH!
Your question is somewhat unclear. Especially because you state that:
PS:the program runs fine.
which it for sure does not. There is a bug that simply means this program will not work.
The problem is that create_new_node is not returning the pointer value
node *create_new_node(int n)
{
ptr=new node;
ptr->info=n;
ptr->next=NULL;
return ptr; // This line is missing
}
Besides that it is a really bad idea to use global pointer variables!
Here
struct node
{
int info;
node *next;
}*start,*newptr,*save,*ptr;
you define the struct node but you also define 4 variables, i.e. 4 pointers to node. These variables will be global, i.e. available in all your code. Something that you should never do.
Instead make local variables as needed - for instance:
node *create_new_node(int n)
{
node *ptr; // Local variable instead of global
ptr=new node;
ptr->info=n;
ptr->next=NULL;
return ptr;
}
Then for the insert_beg change it so that it returns a new start pointer - like:
node* insert_beg(node* start, node *np)
{
np->next=start;
return np;
}
and use it in main like:
node* start = NULL;
...
...
start = insert_beg(start, newptr);
BTW - In modern C++ you would never use raw pointers and you would never write your own list. Use smart pointers instead of raw pointer. Use the standard containers instead of writing your own.

Geting Data from a Tree Structure

I have a tree structure that i am creating the following way. The tree is created correctly as far as i know. But when i want to get the data from a node, i get some weird acsii symbols.
How I set the data.Lets say its empty. Doesn't matter at the moment. I have a value in my program. The function feeds itself until i get to the end of the data.
struct Node {
char Data;
Node* Left;
Node* Right;
};
Node maketree(0,s,split)
{
Node node;
node.Data=' ';
Node n1=subsplit(0,s,splitingat);
Node n2= subsplit(1,splitingat+1,e);
node.Left=&n1;
node.Right=&n2;
return node;
}
This is how i get data from the tree.
char decode(Node node,string text)
{
int currentindex=0;
Node sub=node;
{
}
if(text[currentindex]=='0')
{
sub=*sub.Left;
cout<<" x "<<sub.Data<<endl;
}
else if(text[currentindex]=='1')
{
sub=*sub.Right;
cout<<" x "<<sub.Data<<endl;
}
// cout<<sub.Data<<endl;
}
I think that the mistake is that I am printing out the pointer and not the node. But I don't know where I went wrong.
The source of your problem appears to be here:
Node node;
node.Data=' ';
Node n1=subsplit(0,s,splitingat);
Node n2= subsplit(1,splitingat+1,e);
node.Left=&n1; // danger Will Robinson!
node.Right=&n2;
return node;
You're taking the addresses of local, temporary, automatic variables and storing them in pointers that you return through node. As soon as that return executes, n1 and n2 are destroyed and node.Left and node.Right are left pointing to garbage. You may be able to fix this like so:
Node* n1=new Node(subsplit(0,s,splitingat));
Node* n2=new Node(subsplit(1,splitingat+1,e));
// side note: probably better to have subsplit() return dynamically-allocated Node*s to avoid the copy
node.Left=n1;
node.Right=n2;
but you may still have issues crop up if similar things are being done elsewhere.
Kind of along the same lines, in your second block of code, you are making a copy of each node you examine and storing it into sub. It would probably make more sense to have sub be a Node*.
And finally, to avoid memory management issues (almost) altogether, use shared_ptr<Node> instead of Node* in all of the above. :)

Deleting a node in circular linked list

I have a basic linked list problem that I have attempted to solve below. I would appreciate any inputs on my approach, correctness of the algorithm (and even coding style). The problem calls for a function that deletes all occurrences of an int in a circular linked list and returns any node from the list or NULL (when the list is null).
Here's some C++ code that I have so far:
struct Node{
Node* next;
int data;
};
Node* deleteNode(Node* &node, int num){
if(!node){
return NULL;
}
Node* given = node;
Node* del;
while(node->next != given){
if(node->next->data == num){
del = node->next;
node->next = node->next->next;
delete del;
}
node = node->next;
}
//Check if the first node needs to be deleted, with variable node pointing to last element
if(given->data == num){
node->next = given->next;
delete given;
}
return node;
}
The delete node; should be delete del;.
Also, use Node* node as parameter, instead of Node* &node which will prevent non-lvalues from passing in.
p.s. Forgot a semicolon after struct definition? :)
Without following all your logic I can see at a glance this code cannot work.
You are checking for the input list being empty and that's the only case in which your code returns NULL. But what happens if you are passed a list in which all elements must be deleted?
This problem also has a subtlety in it. To check if you completed a circular list you need to compare to the first address to see if you got linked back to the start. However if this element has been deleted then by C++ standard you're not even allowed to use its address in a comparison.
To avoid making two passes over the elements to be deleted one possible trick is to "break the loop" when starting iteration so you can check for NULL instead of checking for the address of the starting node.

Can we delete the last node of a Single Linked list if we only know the address of last node

// Variables
typedef struct node
{
int value;
struct node *next;
}mynode;
// Globals (not required, though).
mynode *head, *tail, *temp;
// Functions
void add(int value);
// Function to add new nodes to the linked list
void add(int value)
{
temp = (mynode *) malloc(sizeof(struct node));
temp->next=(mynode *)0;
temp->value=value;
if(head==(mynode *)0)
{
head=temp;
tail=temp;
}
else
{
tail->next=temp;
tail=temp;
}
}
// The main() function
int main()
{
head=(mynode *)0;
// Construct the linked list.
add(1);
add(2);
add(3);
return(0);
}
If I only have a pointer to a node, whose value is 3(The Last node as seen in the aforementioned code) , Can we delete it and make a node whose value is 2(aforementioned code) as the last node.
No you can not. Unless you have some reference to previous node. like head pointer. If you have other reference than its pretty much easier. In fact if you don't have any pointers you will loose the list itself
No, but if you know what you are doing, you can modify the last node in-place. Deleting the last node requires access to the second-to-last node, and specifically its link to the last node.
The answer is no.
You can call free on that pointer to the last node, but that just means that the memory occupied by that node is no longer claimed. The data will most likely stay there unchanged for a while. And that means that the next-to-last node's pointer to it is still valid, even though it should not be.
To delete the node in a way that is meaningful to the list, that pointer contained in the next-to-last node has to be nullified. And that can't be done unless that next-to-last node can be accessed, either by a direct pointer to it, or by traversing the list from a preceding node.
You can use a doubly linked list to access the previous node. Or iterate through the entire list.
Yes you can.. Try the following code:
void deleteNode()
{
mynode *temp1;
for(temp1 = head; temp->next!= tail; temp1 = temp1->next);
tail = temp1;
free(tail->next);
}
It will delete the last node.