Copying a Linked List crashes the Program - c++

I have Linked List code, the Copy_List function crashes the program and won't work: it gives no syntax error so it's logical. I'm not sure where the exact problem lies, so any help would be appreciated.
Here is the code:
#include <iostream>
using namespace std;
struct node{
int info;
node *link;
};
class Linked_List{
private :
int count;
node *first;
node *last;
node *current;
public:
Linked_List() {
count=0;
first=NULL;
last=NULL;
}
void Initialize_List(){
cout<<"Enter Number OF Nodes"<<endl;
cin>>count;
first=last=current=new node;
for(int i =0;i<count;i++){
cout<<"Enter New Node Info :"<<endl;
cin>>current->info;
last->link=current;
last=current;
current=new node;
}
last->link=NULL;
}
bool Is_Empty(){
if(first==NULL)
{
return true;
}
else{
return false;
}
}
int Front () {
if (first != NULL)
return first-> info;
else return 0;
}
int Back () {
if (last != NULL)
return last-> info;
else return 0;
}
void Insert_Last(int x){
count++;
current=new node;
current->info=x;
last->link=current;
last=current;
last->link=NULL;
if(first==NULL)
first=current;
}
void Delete_First(){
if(!Is_Empty()) // Or if(first==NULL)
{
node *p;
p=first;
first=first->link;
delete p;
count --;
if(count==0)
first=last=NULL;
}
}
friend void Copy_List (Linked_List &n,Linked_List &m);
};
void Copy_List (Linked_List &n,Linked_List &m){
Linked_List temp;
while(!n.Is_Empty()){
temp.Insert_Last(n.Front());
n.Delete_First();
}
while (!temp.Is_Empty()) {
n.Insert_Last(temp.Front());
temp.Delete_First();
}
}
void main (){
Linked_List obj,obj2;
cout<<"Is the list empty ?"<<" "<<boolalpha<<obj.Is_Empty(); cout<<endl;
obj.Initialize_List();
cout<<"Is the list empty ?"<<" "<<boolalpha<<obj.Is_Empty(); cout<<endl;
Copy_List (obj,obj2);
}

Suggestions for improvement:
Add a default constructor to node so that it gets initialized properly when constructed.
struct node{
node(int in = 0) : info(in), link(NULL) {}
int info;
node *link;
};
You don't need current as a member of Linked_List. It's useful only in some functions as a function varible.
Implement Initialize_List() using Insert_Last. That keeps the function cleaner. It also avoids redundant code.
void Initialize_List(){
cout<<"Enter Number OF Nodes"<<endl;
int num;
cin>>num;
for(int i =0;i<num;i++){
cout<<"Enter New Node Info :"<<endl;
int info;
cin >> info;
this->Insert_Last(info);
}
}
Insert_Last had assumptions about which is a valid pointer and which is not, which won't be true if you started using to from Initialize_List. It can be simplified to:
void Insert_Last(int x){
count++;
node* current=new node;
current->info=x;
if ( first == NULL )
{
first = last = current;
}
else
{
last->link=current;
last=current;
}
}
Implementation of Copy_List you posted deleted all items from the first argument and put them in the second argument. I am not sure that was the purpose. If you want to keep the contents of the first argument unchanged and want to copy its contents to the second argument, an alternate method is necessary. Here's what I came up with:
void Copy_List (Linked_List &n,Linked_List &m){
Linked_List temp;
node* current = n.first;
for ( ; current != NULL; current = current->link )
{
temp.Insert_Last(current->info);
}
current = temp.first;
for ( ; current != NULL; current = current->link )
{
m.Insert_Last(current->info);
}
}
You don't have a destructor in Linked_List. The default implementation provided by the compiler won't release the memory allocated by the class. In order to deallocate the memory allocated by the class, you need to implement a destructor.
~Linked_List() {
node* current=first;
while ( current != NULL )
{
node* temp = current->link;
delete current;
current = temp;
}
}

In the new list last pointer is not initialized firstly:
void Insert_Last(int x) {
...
last->link=current; // for the new List last should be initialized
last = current;
last->link=NULL;
Supposed change - remove the line last->link=current;
last = current;
last->link=NULL;

Related

what is the problem in creat_list2 function?

I want to know what is the problem in creat_list2 function..
I have a problem in this code and as i knew it's in the creat_list2 cause the program run Successfully
when i stop this function it ask the user to enter a numbers that will be stored in the list 1 then print them but the problem as i saw is in the second fuction that creat the second list...,I have to submit my assignment tomorrow so I wish if any body can help me to solve this problem.
#include<iostream>
using namespace std;
struct node{
int x;
node *next;
};
struct snode{
int y;
snode *next;
};
creat_list1(node *&head, node *&tail)
{
int num;
cout<<"enter number\n";
cin>>num;
while(num!=0)
{
node *np=new node;
np->x=num;
if(head==nullptr)
head=np;
else
tail->next=np;
tail=np;
tail->next=nullptr;
cout<<"enter number again\n";
cin>>num;
}
}
creat_list2(node *&head, snode *shead, snode *stail)
{
int sum=0;
while(head!=nullptr)
{
for(int i=0;i<head->x;i++)
sum+=i;
snode *np= new snode;
np->y=sum;
if(head==0)
shead=np;
else
stail->next=np;
stail=np;
stail->next=nullptr;
}
head=head->next;
}
void print_list1 (node *head)
{
while(head!=nullptr)
{
cout<<head->x<<"\t";
head=head->next;
}
}
void print_list2(snode *shead)
{
while(shead!=nullptr)
{
cout<<shead->y<<"\t";
shead=shead->next;
}
}
main()
{
node *head=nullptr, *tail=nullptr;
snode *shead=nullptr, *stail=nullptr;
creat_list1(head,tail);
creat_list2(head,shead,stail);`enter code here`
print_list1(head);
print_list2(shead);
}
There are couple of issues with yours code,
creat_list2(node *&head, snode *shead, snode *stail) if u updated
head like head=head->next; it will reflect at the main.
shead and stail are just a local pointer and any update to just a pointer like stail=np;will not have any changes at the `main
There seems to be typo if(head==0) shead=np; instead it should be
if(shead==0) shead=np; which is causing null pointer exception.
I tried to fix the error at creat_list2 but functionality is still ambiguous to me,
void creat_list2(const node *head, node *&shead, node *&stail) //updated in argument
{
int sum = 0;
while (head != nullptr)
{
//for (int i = 0; i < head->x; i++)
// sum += i;
node *np = new node;
np->x = sum;
if (shead == 0) //error : head instead shead
shead = np;
else
stail->next = np;
stail = np;
stail->next = nullptr;
head = head->next;
}
}

Need some advice with classes in C++, doubly linked list

I'm trying to print all the elements of the list, but I'm getting a wrong output.
The code gets 2, 0 and 10, and when I call the procedure "travel_in" it only shows 0, 2.
And have some doubts with my del_start(), it deletes the 0 and not the 2..
What I'm doing wrong?
Compiled in Windows 64bits with Cygwin
Output
2 0 10 0 2
Here is the code
# include < iostream >
# include < stdio.h >
using namespace std;
template <class clali>
class double_list
{
protected:
clali node1;
clali *listad;
public:
double_list()//constructor
{
listad=NULL;
}
void insert_strt(clali node1)
{
clali *temp;
temp=new clali;
*temp=node1;
//check if list is not empty
if (listad==NULL)
{
listad=temp;
listad->next=NULL;
listad->before=NULL;
}
else
{
temp->next=listad;
listad->before=temp;
temp->before=NULL;
listad=temp;
}
}
int vertam()
{
int res=0;
clali *temp;
temp=listad;
if (temp==NULL)
{
cout<<"Empty list!"<<endl;
res=0;
}
else
while(temp!=NULL)
{
res++;
temp=temp->next;
}
return res;
}
void insert_mid(clali node1, int pos)
{
int i;
clali *temp,*temp2;
temp2=new clali;
temp=listad;
if(pos<vertam)
{
for(i=1;i<pos;i++)
temp=temp->next;
*temp2=node1;
temp2->next=temp->next;
temp->before=listad;
temp->next=temp2;
}
else
cout<<"Cant show the data!"<<endl;
}
clali del_start()
{
clali a,*temp;
a=*listad;
temp=listad;
listad=listad->next;
delete temp;
return a;
}
void insert_end(clali node1)
{
clali *temp,*temp2;
temp=listad;
while(temp->next!=NULL)
{
temp=temp->next;
}
temp2=new clali;
*temp2=node1;
temp->next=temp2;
temp2->before=temp;
temp2->next=NULL;
}
clali clear_end()
{
clali b,*temp,*temp2;
int j=1;
temp=listad;
do
{
temp=temp->next;
cout<<"Element : "<<j<<endl;
j++;
}while(temp->next!=NULL);
b=*temp;
temp2=temp->before;
temp2->next=NULL;
// delete temp;
return b;
}
void travel_in()
{
clali *temp;
temp=listad;
while(temp->next!=NULL)
{
cout<<temp->data<<endl;
temp=temp->next;
}
}
};
struct integer
{
int data;
integer*next,*before;
};
typedef struct integer Integer;
int main()
{
Integer node;
node.next=NULL;
node.before=NULL;
double_list<Integer> test_list;
test_list.insert_strt(node);
node.data=2;
cout<<node.data<<endl;
test_list.insert_end(node);
node.data=0;
cout<<node.data<<endl;
test_list.insert_end(node);
node.data=10;
cout<<node.data<<endl;
test_list.del_start();
test_list.travel_in();
}
I see at least one obvious bug. Initial analysis indicates that the listad class member is the pointer to the first element in the doubly-linked list. In that case, the following is obviously wrong (reformated for legibility, please indent your code correctly):
void insert_mid(clali node1, int pos)
{
int i;
clali *temp,*temp2;
temp2=new clali;
The purpose of this class method is, apparently, to insert the new node in the middle of the linked list.
temp2 is the new node.
temp=listad;
if(pos<vertam)
{
for(i=1;i<pos;i++)
temp=temp->next;
temp appears to be the insert position in the middle of the list.
temp->before=listad;
For some unclear reason this code attempts to set the before pointer of an existing node in the middle of the list to the head of the list. This makes no sense, and is wrong.
Let's go step by step in main().
When you first call insert_strt() the argument node has garbage value for member data. So an Integer object with some garbage value for data gets inserted at the start of test_list. Then you insert Integer objects with data 2 and 0, respectively, at the end of the list.
Later, you delete the first clali object from test_list which deletes the object with garbage value in its data field. So, after deletion, you have objects with data value 2, and 0 in the list in that order.
At the end, you print the list with travel_in() but it does not do what you think it does. What it is actually doing is that if the list has at least one element then it prints all but the last element in the list. If the list is empty, it will cause a segmentation fault (in the condition of while loop as temp would be NULL). So it will print: 2 (but your list has 2 and 0).
You can write travel_in() as follows.
void travel_in()
{
clali *temp = listad;
while(temp != NULL)
{
cout << temp->data << " ";
temp = temp->next;
}
cout << endl;
}
By the way, comment/remove the cout statements in the main() function. They may confuse you.

delete a node in the middle of a single linked list, given only access to that node

This is an interview question in "Cracking the coding interview". My code and test cases are here:
#include<iostream>
using namespace std;
struct node
{
int data;
node* next;
};
node* init(int a[], int n);
void remove(node* & c);
void printList(node* head);
int main()
{
int a[]={0,1,2,3,4,5,6,7,8,9};
node* testHead=init(a, 10);
printList(testHead);
cout<<endl;
int nth=9;
node *c=testHead;
for(int i=0; i<nth; i++)
{
c=c->next;
}
remove(c);
printList(testHead);
system("PAUSE");
return 0;
}
node* init(int a[], int n)
{
node *head, *p;
for(int i=0; i<n; i++)
{
node *nd=new node();
nd->data=a[i];
if(i==0)
{
head=nd;
p=nd;
}
else
{
p->next=nd;
p=nd;
}
}
return head;
}
void remove(node* & c)
{
if(c==NULL)
return;
node* tmp=c->next;
if(tmp==NULL)
{
delete c;
c=NULL;
}
else
{
c->data=tmp->data;
c->next=tmp->next;
delete tmp;
}
}
void printList(node* head)
{
while(head!=NULL)
{
cout<<head->data<<" ";
head=head->next;
}
}
Here in the main function, I tried to delete the last node, with the data value 9.
However, even in the function "remove", I checked the last node and if it is, I set it to NULL, the output will produce an error.
Can anyone tell me why this happen?
Thanks.
The problems are actually as follows:
You should make the last node of list point to NULL while building the list.
When you delete the last node in the linked list, the previous node -> next becomes a dangling pointer. This pointer has to be made to point to NULL. Since you do not have its address, you will again have to traverse this list from the head node till you get the address of the node prior to the node to be deleted.
void remove(node* & c) // --> 1
{
if(c==NULL)
return;
node* tmp=c->next;
if(tmp==NULL)
{
delete c; // --> 2
c=NULL; // --> 3
}
else
{
c->data=tmp->data;
c->next=tmp->next;
delete tmp;
}
}
This is the thing:
When you pass in as a pointer, you does not necessary to pass in as a reference. It is redundant. //Check #WhozCraig comment for correction
delete releases c allocated memory
Therefore, you cannot assign a NULL to c
Other word, how can you assign NULL to a variable that has been released?

C++ Access violation reading location in single link list

I am using c++ to implement a single link list of integers. My program simply asks the user to fill the list with 5 integers, the program should then delete any even integer and print the list after deletion.
Here is my code:
#include <iostream>
using namespace std;
class IntSLLNode
{
public:
IntSLLNode() { next = 0; }
IntSLLNode(int i, IntSLLNode *ptr = 0)
{
info = i;
next = ptr;
}
int info;
IntSLLNode *next;
};
class IntSLList
{
public:
IntSLList() {head = tail =0; }
void AddToTail(int);
void DeleteNode(int);
void DisplayList();
void deleteEven();
IntSLLNode * getHead()
{
return head;
}
private:
IntSLLNode *head, *tail;
};
void IntSLList::AddToTail(int el)
{
if (tail != 0) // if list not empty;
{ tail->next = new IntSLLNode(el);
tail = tail->next;
}
else
head = tail = new IntSLLNode(el);
}
void IntSLList::deleteEven()
{
IntSLLNode *current;
current=head;
int num;
while (current!=0)
{
num=current->info;
current=current->next;
if(num%2==0)
{
DeleteNode(num);
}
}
}
void IntSLList::DeleteNode(int el)
{
if(head !=0)
if(head==tail && el==head->info)
{
delete head;
head=tail=0;
}
else if(el==head->info)
{
IntSLLNode *tmp=head;
head=head->next;
delete tmp;
}
else
{
IntSLLNode *pred, *tmp;
for(pred=head, tmp=head->next;
tmp!=0 && !(tmp->info==el);
pred=pred->next, tmp=tmp->next);
if(tmp!=0)
{
pred->next=tmp->next;
if(tmp==tail)
tail=pred;
delete tmp;
}
}
}
void IntSLList::DisplayList()
{
IntSLLNode *current;
current=head;
if(current==0)
cout<<"Empty List!";
while (current!=0)
{
cout<<current->info<<" ";
current=current->next;
}
}
I got Unhandled exception at 0x002c1744 in ex4.exe: 0xC0000005: Access violation reading location 0xfeeefeee in statment int num=current->info; Can anyone suggest how to solve this?
I'm not sure about this, but I think the problem is laid here:
void IntSLList::deleteEven()
{
IntSLLNode *current;
current=head;
while (current!=0)
{
if(current->info%2==0)
DeleteNode(current->info);
current=current->next; // this line
}
}
I think there is a relation between deleted node which is preformed in the if statement and your next line. If you delete that specific pointer which points to an element in DeleteNode() then your current which it might be deleted till now will be pointing to a wrong address.
EDIT
void IntSLList::deleteEven()
{
IntSLLNode *current;
current=head;
while (current!=0)
{
if(current->info%2==0)
{
int ind = current->info;
current=current->next;
DeleteNode(ind);
}
else
{
current=current->next;
}
}
}

what is mistakes/errors in this code c++ tell me the correction?

here in this code the compiler print error :
132 C:.... `createlist' undeclared (first use this function)
(Each undeclared identifier is reported only once for each function it appears in.)
and repeat it again in all calls in main function :(
what's the problem ?? plzzzz help me
#include<iostream>
#include<string>
using namespace std;
template <typename T>
struct Node
{
T num;
struct Node<T> *next;
// to craet list nodes
void createlist(Node<T> *p)
{ T data;
for( ; ; ) // its containue until user want to stop
{ cout<<"enter data number or '#' to stop\n";
cin>>data;
if(data == '#')
{ p->next =NULL;
break;
}
else
{ p->num= data;
p->next = new Node<T>;
p=p->next;
}
}
}
//count list to use it in sort function
int countlist (Node<T> *p)
{
int count=0;
while(p->next != NULL)
{ count++;
p=p->next;
}
return count;
}
// sort list
void sort( Node<T> *p)
{ Node<T> *p1, *p2; //element 1 & 2 to compare between them
int i, j , n;
T temp;
n= countlist(p);
for( i=1; i<n ; i++)
{ // here every loop time we put the first element in list in p1 and the second in p2
p1=p;
p2=p->next;
for(j=1; j<=(n-i) ; j++)
{
if( p1->num > p2->num)
{ temp=p2->num;
p2->num=p1->num;
p1->num=temp;
}
}
p1= p1->next;
p2= p2->next;
}
}
//add new number in any location the user choose
void insertatloc(Node<T> *p)
{ T n; //read new num
int loc; //read the choosen location
Node<T> *locadd, *newnum, *temp;
cout <<" enter location you want ..! \n";
cin>>loc;
locadd=NULL; //make it null to checked if there is location after read it from user ot not
while(p->next !=NULL)
{ if( p->next==loc)
{ locadd=p;
break;
}
p=p->next;
}
if (locadd==NULL)
{cout<<" cannot find the location\n";}
else //if location is right
{cout<<" enter new number\n"; // new number to creat also new location for it
cin>>n;
newnum= new Node/*<T>*/;
newnum->num=n;
temp= locadd->next;
locadd->next=newnum;
newnum->next=temp;
}
locadd->num=sort(locadd); // call sort function
}
// display all list nodes
void displaylist (Node<T> *p)
{
while (p->next != NULL)
{
cout<<" the list contain:\n";
cout<<p->num<<endl;
p=p->next;
}
}
};//end streuct
int main()
{
cout<<"*** Welcome in Linked List Sheet 2****\n";
// defined pointer for structer Node
// that value is the address of first node
struct Node<int>*mynodes= new struct Node<int>;
// create nodes in mynodes list
cout<<"\nCreate nodes in list";
createlist(mynodes);
// insert node in location
insertatloc(mynodes);
/* count the number of all nodes
nodescount = countlist(mynodes);
cout<<"\nThe number of nodes in list is: "<<nodescount;*/
// sort nodes in list
sort(mynodes);
// Display nodes
cout<<"\nDisplay all nodes in list:\n";
displaylist(mynodes);
system("pause");
return 0;
}
createlist is a method of your Node class, but inside main() you're calling it as a function. I recommend either treating Node like a C-struct and implementing those methods as functions taking a struct like Thomas mentions, which is how your code is structured anyway, or reading a tutorial on C++ classes.
My guess is you are missing a closing '}' for your node structure:
template <typename T>
struct Node
{
T num;
struct Node<T> *next;
}; // <--- add this line.
createlist is defined to take a parameter of Node<T> *p but you are passing it an instance of struct Node<int>*
createlist is a member method of Node. You are attempting to access Node::createlist from main. You cannot do this (even if you add "Node::" scoping to your call), because createlist is not a static method.
Change it to:
// to create list nodes
static void createlist(Node<T> *p)
and:
// create nodes in mynodes list
cout<<"\nCreate nodes in list";
Node::createlist(mynodes);
Or pull createlist out of the Node class entirely, and make it into its own function.