I want to reverse a linked list but when i compile this code it terminates unexpectedly.
#include <bits/stdc .h>
using namespace std;
class node{
public:
int data;
node* next;
node(int val){
data=val;
next=NULL;
}
};
For Inserting Elements in Linked List
void insertattail(node* &head,int lol){
node* n= new node(lol);
if(head==NULL){
head=n;
return;
}
node* temp=head;
while(temp->next!=NULL){
temp=temp->next;
}
temp->next=n;
}
Display Function to print linked list
void display(node* head){
node* temp =head;
do{
cout<<temp->data<<"->";
temp=temp->next;
}
while(temp!=NULL);
cout<<"Null";
}
Function to reverse Linked List
node* reverseit(node* head){
node* prevptr= NULL;
node* currptr= head;
node* nextptr= currptr->next;
while(currptr!=NULL){
currptr->next =prevptr;
prevptr=currptr;
currptr=nextptr;
nextptr=currptr->next;
}
return prevptr;
}
Main Function
int main()
{
node* head= NULL;
insertattail(head,1);
insertattail(head,2);
insertattail(head,3);
insertattail(head,8);
node* newhead= reverseit(head);
display(newhead);
return 0;
}
I think the problem is in logic of reverse function. I just used the code for linked list and made small changes.
CodePudding user response:
Your initialization and 'incrementing' of nextptr both (potentially/eventually) dereference a NULL value of currptr. You should initialize nextptr to NULL and only change that to the 'real' next if currptr is not NULL; thus, its (re)assignment should be at the start of the loop, not at the end:
node* reverseit(node* head){
node* prevptr = nullptr;
node* currptr = head;
node* nextptr = nullptr; // Don't assume a non-NULL currptr
while (currptr != nullptr) {
nextptr = currptr->next; // Safe here: save next
currptr->next = prevptr; // Do the reversal here
prevptr = currptr; // Step forward through
currptr = nextptr; // the list (prev/curr)
// nextptr = currptr->next; // WRONG HERE: currptr will be NULL at some point
}
return prevptr;
}
CodePudding user response:
The function invokes undefined behavior.
For example let's at first assume that the list is empty. That is the pointer head is equal to nullptr. In this case using this line before the while loop within the function
node* nextptr= currptr->next;
accesses memory using a null pointer.
Or let's consider another example when current->next is equal to nullptr. In this case within the while loop these statements
currptr=nextptr;
nextptr=currptr->next;
again access memory using a null pointer.
And declarations of many pointers before the while loop
node* prevptr= NULL;
node* currptr= head;
node* nextptr= currptr->next;
makes the code less readable and clear.
The function can be defined the following way
node * reverseit( node *head )
{
node *new_head = nullptr;
for ( node *current = head; head != nullptr; head = current )
{
current = head->next;
head->next = new_head;
new_head = head;
}
return new_head;
}
If actually your program is a C program then instead of nullptr use NULL.
Also in main there is no need to introduce the new pointer newhead
node* newhead= reverseit(head);
You could just write
head = reverseit(head);
The function display can again invoke undefined behavior if the passed pointer to the head node is equal to nullptr. And the parameter of the function should have the qualifier const because within the function the list itself is not changed.
The function can be defined the following way
std::ostream & display( const node *head, std::ostream &os = std::cout )
{
for ( const node *current = head; current != nullptr; current =current->next )
{
os << current->data << " -> ";
}
return os << "Null";
}
And the function can be called like
display( head ) << '\n';
