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

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.

Related

I have been trying to merge 2 sorted linked lists using C++ but my output shows nothing ,just blank?

I have been trying to merge 2 sorted linked lists using C++ but my output shows nothing, just blank.
In main function, I created 2 sorted linked lists and in the mergeem function I joined them by making h (head) pointer and t (tail) pointer and incrementing the t pointer after it is decided which value will come next in the new joined linked list. mergeem returns h and I print the linked list with h as head.
Which part of my code is leading to a blank output?
class node
{
public:
int data;
node* next;
node(int d)
{
data=d;
}
};
node* mergeem(node *h1,node *h2)
{
node*h;
node*t;
if(h1->data<h2->data)
{
h=h1;
t=h1;
h1=h1->next;
}
else
{
h=h2;
t=h2;
h2=h2->next;
}
while(h1!=NULL && h2!=NULL)
{
if(h1->data<h2->data)
{
t->next=h1;
t=h1;
h1=h1->next;
}
else
{
t->next=h2;
t=h2;
h2=h2->next;
}
}
while(h1!=NULL)
{
t->next=h1;
}
while(h2!=NULL)
{
t->next=h2;
}
return h;
}
void print(node*head)
{
node*temp=head;
cout<<"All elements : "<<endl;
while(temp!=NULL)
{
cout<<temp->data<<endl;
temp=temp->next;
}
}
int main()
{
node*newnode1=new node(10);
node*newnode2=new node(15);
node*newnode3=new node(20);
node*newnode4=new node(25);
node*newnode5=new node(30);
newnode1->next=newnode2;
newnode2->next=newnode3;
newnode3->next=newnode4;
newnode4->next=newnode5;
node*ewnode1=new node(8);
node*ewnode2=new node(12);
node*ewnode3=new node(21);
node*ewnode4=new node(27);
node*ewnode5=new node(28);
ewnode1->next=ewnode2;
ewnode2->next=ewnode3;
ewnode3->next=ewnode4;
ewnode4->next=ewnode5;
node*head=mergeem(newnode1,ewnode1);
print(head);
return 0;
}
Suppose that h1 is not null after the main loop of mergeem.
Then the loop
while(h1!=NULL)
{
t->next=h1;
}
will never terminate, since the value of h1 doesn't change; you're just assigning the same value to t->next over and over.
The same reasoning applies to the loop with h2.
Since you just want to "take over" the tail of the remaining list, you should write if instead of while in both cases.
if (h1 != NULL)
{
t->next = h1;
}
You could also condense the tail-stealing to
t->next = h1 != NULL ? h1 : h2;

Copying a Linked List crashes the Program

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;

why does this code produce a runtime error?

#include<stdio.h>
#include<conio.h>
#include<windows.h>
struct node
{
int a;
struct node *next;
};
void createlist(struct node **head)
{
struct node *p,*temp;
int n;
printf("enter the number\n");
scanf("%d",&n);
p=(struct node*)malloc(sizeof(struct node));
p->a=n;
if(*head==0) {
*head=p;
p->next=0;
temp=p;
}
else {
temp->next=p;
temp=p;
p->next=0;
}
}
void frontbacksplit(struct node **head,struct node **head1,struct node **head2)
{
int counter=0,i;
struct node *temp,*p;
temp=*head;
while(temp!=0) {
counter++;
temp=temp->next;
}
int n;
if(counter%2==0) {
n=counter/2;
} else {
n=(counter+1)/2;
}
temp=*head;
for(i=0;i<n-1;i++) {
if(*head1==0) {
*head1=temp;
}
temp=temp->next;
}
p=temp;
temp=temp->next;
p->next=0;
for(i=n+1;i<counter;i++) {
if(*head2==0) {
*head2=temp;
}
temp=temp->next;
}
}
void display(struct node **head)
{
struct node *temp;
temp=*head;
while(temp!=0) {
printf("%d\t",temp->a);
temp=temp->next;
}
printf("\n");
}
int main()
{
int n=1,i,k;
struct node *head3,*head1,*head2;
head3=0;
head1=0;
head2=0;
while(n==1) {
printf("enter \n1-To add the elements\n2-To split the list into front and the back\n3-To display the elements\n");
scanf("%d",&i);
switch(i)
{
case 1:
createlist(&head3);
break;
case 2:
frontbacksplit(&head3,&head1,&head2);
break;
case 3:
printf("enter\n1-To display front list\n2-To display rear list\n");
scanf("%d",&k);
switch(k)
{
case 1:
display(&head1);
break;
case 2:
display(&head2);
}
break;
default:
printf("please enter a valid option\n");
}
printf("enter\n1-To continue\nany other number to exit\n");
scanf("%d",&n);
}
getch();
return 0;
}
I have written this code for front / back splitting of the linked list. For example if the list is [1 2 3 4 5] then this program splits the list into the two lists: front part (1 2 3) and back part(4 5), if the number of elements are equal both the parts get equal number of elements.
Problem: When I try to add elements in the source list, the first elements get added as usual but when I try add other element my program shows a run time error. I think there is problem with the pointer variable temp but almost same code for the creation of linked list worked properly.
I am using dev c++ ide on windows 8.
Of course point out if you did't like the way this question is asked, as this is my first time.
On first look this line temp->next = p in createlist function is wrong, temp is a local variable, although you make it point to the element when the list is created for the first time the value is lost after the createlist function returns, so will you be accessing junk addresses in consecutive calls to createlist
The pointer variable 'temp' in createlist() function is being used without assignment on calls subsequent to the first call. You could benefit using -Wall options if you are using GCC.
Maybe you should change to this:
void createlist(struct node **head)
{
struct node *p,*temp;
int n;
printf("enter the number\n");
while(scanf("%d",&n) != EOF)
{
p=(struct node*)malloc(sizeof(struct node));
p->a=n;
if(*head==0)
{
*head=p;
p->next=0;
temp=p;
}
else
{
temp->next=p;
temp=p;
p->next=0;
}
}
}

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?

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.