I was writing a simple function to insert at the end of a linked list on C++, but finally it only shows the first data. I can't figure what's wrong. This is the function:
void InsertAtEnd (node* &firstNode, string name){
node* temp=firstNode;
while(temp!=NULL) temp=temp->next;
temp = new node;
temp->data=name;
temp->next=NULL;
if(firstNode==NULL) firstNode=temp;
}
What you wrote is:
if firstNode is null, it's replaced with the single node temp which
has no next node (and nobody's next is temp)
Else, if firstNode is not null, nothing happens, except that the temp
node is allocated and leaked.
Below is a more correct code:
void insertAtEnd(node* &first, string name) {
// create node
node* temp = new node;
temp->data = name;
temp->next = NULL;
if(!first) { // empty list becomes the new node
first = temp;
return;
} else { // find last and link the new node
node* last = first;
while(last->next) last=last->next;
last->next = temp;
}
}
Also, I would suggest adding a constructor to node:
struct node {
std::string data;
node* next;
node(const std::string & val, node* n = 0) : data(val), next(n) {}
node(node* n = 0) : next(n) {}
};
Which enables you to create the temp node like this:
node* temp = new node(name);
You've made two fundamental mistakes:
As you scroll through the list, you roll off the last element and start constructing in the void behind it. Finding the first NULL past the last element is useless. You must find the last element itself (one that has its 'next' equal NULL). Iterate over temp->next, not temp.
If you want to append the element at the end, you must overwrite the last pointer's NULL with its address. Instead, you write the new element at the beginning of the list.
void InsertAtEnd (node* &firstNode, string name)
{
node* newnode = new node;
newnode->data=name;
newnode->next=NULL;
if(firstNode == NULL)
{
firstNode=newnode;
}
else
{
node* last=firstNode;
while(last->next != NULL) last=last->next;
last->next = newnode;
}
}
Note, this gets a bit neater if you make sure never to feed NULL but have all lists always initialized with at least one element. Also, inserting at the beginning of list is much easier than appending at the end: newnode->next=firstNode; firstNode=newnode.
The last element in your list never has it's next pointer set to the new element in the list.
The problem is that you are replacing the head of the linked list with the new element, and in the process losing the reference to the actual list.
To insert at the end, you want to change the while condition to:
while(temp->next != null)
After the loop, temp will point to the last element in the list. Then create a new node:
node* newNode = new node;
newNode->data = name;
newNode->next = NULL;
Then change temps next to this new node:
temp->next = newNode;
You also do not need to pass firstNode as a reference, unless you want NULL to be treated as a linked list with length 0. In that case, you will need to significantly modify your method so it can handle the case where firstNode is NULL separately, as in that case you cannot evaluate firstNode->next without a segmentation fault.
If you don't want to use reference pointer, you could use pointer to pointer. My complete code goes like below:
void insertAtEnd(struct node **p,int new_data)
{
struct node *new_node=(struct node *)malloc(sizeof(struct node));
new_node->data=new_data;
new_node->next=NULL;
if((*p)==NULL)//if list is empty
{
*p=new_node;
return;
}
struct node* last=*p;//initailly points to the 1st node
while((last)->next != NULL)//traverse till the last node
last=last->next;
last->next=new_node;
}
void printlist(struct node *node)
{
while(node != NULL);
{
printf("%d->",node->data);
node=node->next;
}
}
int main()
{
struct node *root=NULL;
insertAtEnd(&root,1);
insertAtEnd(&root,2);
insertAtEnd(&root,3);
insertAtEnd(&root,4);
insertAtEnd(&root,5);
printlist(root);
return 0;
}
Understanding the need of the below two variables is key to understanding the problem:
struct node **p: Because we need to link it from the root node created in the main.
struct node* last: Because if not used, the original content will be changed with the contents of the next node inside the while loop. In the end only 2 elements will be printed, the last 2 nodes, which is not desired.
void addlast ( int a)
{
node* temp = new node;
temp->data = a;
temp->next = NULL;
temp->prev=NULL;
if(count == maxnum)
{
top = temp;
count++;
}
else
{
node* last = top;
while(last->next)
last=last->next;
last->next = temp;
}
}
#include <bits/stdc++.h>
using namespace std;
class Node
{
public:
int data;
Node *next;
};
void append(Node *first, int n)
{
Node *foo = new Node();
foo->data = n;
foo->next = NULL;
if (first == NULL)
{
first = foo;
}
else
{
Node *last = first;
while (last->next)
last = last->next;
last->next = foo;
}
}
void printList(Node *first)
{
while (first->next != NULL)
{
first = first->next;
cout << first->data << ' ';
}
}
int main()
{
Node *node = new Node();
append(node, 4);
append(node, 10);
append(node, 7);
printList(node);
return 0;
}
Output: 4 10 7
You can use this code:
void insertAtEnd(Node* firstNode, string name)
{
Node* newn = new Node; //create new node
while( firstNode->next != NULL ) //find the last element in yur list
firstNode = firstNode->next; //he is the one that points to NULL
firstNode->next = newn; //make it to point to the new element
newn->next = NULL; //make your new element to be the last (NULL)
newn->data = name; //assign data.
}
void InsertAtEnd (node* &firstNode, string name){
node* temp=firstNode;
while(temp && temp->next!=NULL) temp=temp->next;
node * temp1 = new node;
temp1->data=name;
temp1->next=NULL;
if(temp==NULL)
firstNode=temp1;
else
temp->next= temp1;
}
while loop will return at temp==null in your code instead you need to return last node pointer from while loop like this
while(temp && temp->next!=NULL) temp=temp->next;
and assign a new node to next pointer of the returned temp node will add the data to the tail of linked list.
Related
I am trying to create a doubly linked list and then printing its value but the output is showing only first value and then the whole program is crashing.
I can't understand where is the problem in the code .
Input
3
1 2 3
Expected output
1 2 3
current output
1
#include<iostream>
#include<stdlib.h>
using namespace std;
class node //declation of node
{
public:
int data;
node *next;
node *prev;
};
node *makenode(node *head,int val) //function to create node
{
node *newnode=new node;
node *temp;
newnode->data=val;
newnode->next=0;
newnode->prev=0;
if(head==0) temp=head=newnode;
else
{
temp->next=newnode;
newnode->prev=temp;
temp=newnode;
}
return head;
}
void display(node *head) //display function
{
system("cls"); //clearing output screen
while(head!=0)
{
cout<<head->data<<" ";
head=head->next;
}
}
int main()
{
node *head;
head=0;
int val;
int s; //size of list
cout<<"ENTER THE SIZE OF LIST";
cin>>s;
system("cls");
for(int i=0;i<s;i++)
{
cout<<"ENTER THE "<<i+1<<" VALUE\n";
cin>>val;
head=makenode(head,val); //calling makenode and putting value
}
display(head); //printing value
return 0;
}
node *makenode(node *head,int val) //function to create node
{
node *newnode=new node;
node *temp; // #1
newnode->data=val;
newnode->next=0;
newnode->prev=0;
if(head==0) temp=head=newnode;
else
{
temp->next=newnode; // #2
Between the lines marked #1 and #2 above, what exactly is setting the variable temp to point to an actual node rather than pointing to some arbitrary memory address?
"Nothing", I hear you say? Well, that would be a problem :-)
In more detail, the line:
node *temp;
will set temp to point to some "random" location and, unless your list is currently empty, nothing will change that before you attempt to execute:
temp->next = newnode;
In other words, it will use a very-likely invalid pointer value and crash if you're lucky. If you're unlucky, it won't crash but will instead exhibit some strange behaviour at some point after that.
If you're not worried about the order in the list, this could be fixed by just always inserting at the head, with something like:
node *makenode(node *head, int val) {
node *newnode = new node;
newnode->data = val;
if (head == 0) { // probably should use nullptr rather than 0.
newnode->next = 0;
newnode->prev = 0;
} else {
newnode->next = head->next;
newnode->prev = 0;
}
head = newnode;
return head;
}
If you are concerned about order, you have to find out where the new node should go, based on the value, such as with:
node *makenode(node *head, int val) {
node *newnode = new node;
newnode->data = val;
// Special case for empty list, just make new list.
if (head == 0) { // probably should use nullptr rather than 0.
newnode->next = 0;
newnode->prev = 0;
head = newnode;
return head;
}
// Special case for insertion before head.
if (head->data > val) {
newnode->next = head->next;
newnode->prev = 0;
head = newnode;
return head;
}
// Otherwise find node you can insert after, and act on it.
// Checknode will end up as first node where next is greater than
// or equal to insertion value, or the last node if it's greater
// than all current items.
node *checknode = head;
while (checknode->next != 0 && (checknode->next->data < val) {
checknode = checknode->next;
}
// Then it's just a matter of adjusting three or four pointers
// to insert (three if inserting after current last element).
newnode->next = checknode->next;
newnode->prev = checknode;
if (checknode->next != 0) {
checknode->next->prev = newnode;
}
checknode->next = newnode;
return head;
}
You aren't actually linking anything together. This line: if(head==0) temp=head=newnode; is the only reason your linked list contains a value at all. The very first value sets head equal to it and when you print head you get that value. In order to properly do a linked list you need a head and tail pointer. The head points to the first element in the list and the tail points to the last. When you add an element to the end of the list you use tail to find the last element and link to it. It is easiest to make Linked List a class where you can encapsulate head and tail:
struct Node {
public:
int data;
node *next;
node *prev;
Node(int data) : data(data), next(nullptr), prev(nullptr) {} // constructor
};
class LinkedList {
private:
Node* head;
Node* tail;
public:
LinkedList() { head = tail = nullptr; }
// This function adds a node to the end of the linked list
void add(int data) {
Node* newNode = new Node(data);
if (head == nullptr) { // the list is empty
head = newNode;
tail = newNode;
}
else { // the list is not empty
tail->next = newNode; // point the last element to the new node
newNode->prev = tail; // point the new element to the prev
tail = tail->next; // point the tail to the new node
}
}
};
int main() {
LinkedList lList;
lList.add(1);
lList.add(2);
// etc...
return 0;
}
I am writing a simple function to insert at the end of a linked list on C++, but finally it only shows the first data. I can't figure what's wrong. This is the function:
node* Insert(node* head, int data)
{
if (head == NULL) {
head = new node();
head->data = data;
head->link = NULL;
return head;
}
else {
node* temp = head;
while (temp != NULL) {
temp = temp->link;
}
node* temp2 = new node();
temp2->data = data;
temp2->link = NULL;
(temp->link) = temp2;
return head;
}
}
Change the condition in while construct from:
while (temp!=NULL) {
temp=temp->link;
}
To
while (temp->link!=NULL) {
temp=temp->link;
}
In statement, temp->link = temp2, temp is a null pointer. You were dereferencing a NULL pointer.
To append a node at the back, temp pointer should point to the last node of the linked list. So, in the while loop, you need to just stop linked list traversal when you have reached the last node, i.e, the node whose link member points to nothing (has NULL). while (temp->link!=NULL) will stop at the last node as last node will have link member pointing to NULL.
You can simplify your logic by doing this:
void Insert(node **pnode, int data)
{
while (*pnode) {
pnode = &(*pnode)->link;
}
*pnode = new node(data, NULL);
}
assuming you have a node constructor that initializes data and link from arguments.
Instead of calling it as
head = Insert(head, 42);
you'd now do
Insert(&head, 42);
change while(temp!=NULL) to while(temp->link!=NULL)
node* Insert(node* head, int data)
{
if (head == NULL) {
head = new node();
}
else {
while (head->link != NULL) {
head = head->link;
}
head = head->link = new node();
}
head->data = data;
head->link = NULL;
return head;
}
struct Node{
string val;
Node* next;
};
Node* makeList ()
{
string current;
Node* n;
Node* head= NULL;
Node* temp = n;
while(cin>>current && !cin.fail())
{
n = new Node;
n->val = current;
temp ->next = n;
temp = temp -> next;
}
n->next = NULL;
return n;
}
I am trying to learn about linked lists, and this function makeList() is supposed to create and return a linked list using input from a list of strings. To be honest, I'm kind of lost. Any help would be greatly appreciated.
First of all, you are returning the last node of the linked list.. I think you should return the head and assign it to the first Node.
Secondly you are using cin.fail() for a string which I think should not be done. cin.fail() will work if there is a data mismatch and for string I think it is rare.
The function would look somewhat like:
Node* makeList ()
{
string current;
Node* n;
Node* head= NULL;
Node* temp = n;
while(cin>>current && !cin.fail())
{
if(current == "0")
break;
n = new Node;
n->val = current;
temp ->next = n;
temp = temp -> next;
if(!head)
head = n;
}
n->next = NULL;
return head;
}
First of all, since your temp represents the last element I would put it to NULL at the beginning (nullptr is more in the spirit of C++, so I'll use it in the text that comes).
After that in a while loop ,when you are adding a new element, you should write n->next=nullptr,since the pointer next of the new element(if you're always adding it to the back of the list) will always point to nullptr. In your implementation your new element n is always pointing to itself.Later on in your while loop you need to check if head==nullptr, if that's true than you should assign head to the new element that you made head=n. If head is not equal to nullptr then you need to add your element n to the back temp->next=n. An at the and of the loop you should assign the n element as last-temp=n (that has to be outside of the else block since it is done in both of the above mentioned cases).
I'm afraid answers above all got some bugs...
Node *make_link_list_from_input(){
string value;
Node *head = nullptr;
Node *current = nullptr;
Node *last = nullptr;
while (cin >> value){
current = new Node();
if(head== nullptr){
head = current;
}
if(last!= nullptr){
last->next=current;
}
last=current;
}
if(last != nullptr) {
last->next = nullptr;
}
return head;
}
My following code print just only first element. In print_list() function, it stops after printing first element. It says after first element, head->next is 0. Shouldn't point towards second element?
I want to simply print whole list.
#include<iostream>
#include<cstdlib>
using namespace std;
struct node {
int x;
node *next;
};
node* add_element(node*);
bool is_empty(node*);
void print_list(node*);
node* search(node*);
int main()
{
node *head;
head=NULL;
node* current=head;
for(int i=0;i<5;i=i+1)
{
if (current==NULL)
{
current=add_element(current);
head=current;
}
else{
current=add_element(current);
}
}
cout<<head->next<<endl;
// DOUBT: head->next gives NULL value. It should give me pointer to 2nd node
print_list(head);
}
node* add_element(node* current)
{
node* temp;
temp=new node;
temp->next=NULL;
cout<<"enter element"<<endl;
cin>>temp->x;
current=temp;
return current;
}
bool is_empty(node* temp)
{
return temp==NULL;
}
void print_list(node* temp)
{
if (is_empty(temp)==false)
{
cout<<"here temp(head)"<<temp->next<<endl;
while(temp!=NULL)
{
cout<<temp->x<<endl;
temp = temp->next;
}
}
}
Print function print first element because you have just one node in the Linked List! Actually the mistake is present in add_element(node*) function, you overwrite address of head node with new node (so having memory leak) as I marked below:
node* add_element(node* current)
{
node* temp;
temp = new node; <---" You allocated memory"
temp->next = NULL; <---" Set next NULL"
cout<< "enter element" << endl;
cin>> temp->x; <---" Assign a value in new node"
// Replace below two line with suggested
current = temp; <---"MISTAKE: Overwrite first node"
"temp next is NULL so losing address of other nodes"
return current; <--- "return first node"
}
Next of new node (so first node) is NULL hence the print function prints only first node's value.
Suggestion:
You should Correct as follows to add new node as a first node in linked list:
temp -> next = current; // new nodes next if present first node
return temp; // new code becomes first node
Be careful current should be NULL initially.
With my suggestion in add_element() function also change the for loop code in main() as follows:
for(int i=0; i < 5; i = i + 1){
current = add_element(current);
}
head = current;
And check the working code at Codepade (instead of user input I added value using y = 100 variable).
Edit To append new node:
You need to check whether new node is first node of not (read comments).
// returns first node address in linked list = head
node* add_element(node* head){
node *temp, *new_nd;
// Create new node
new_nd = new node;
new_nd->next = NULL;
cout<<"enter element"<<endl;
cin>>new_nd->x;
// Is new node is the first node?
if(!head)
return new_nd;
// move to last
temp = head;
while(temp->next) temp = temp->next;
// add new node at last
temp->next = new_nd;
// return old head
return head;
}
Also simply main() as below:
int main(){
node *head = NULL;
for(int i = 0; i < 5; i = i + 1){
head = add_element(head);
}
print_list(head);
}
check this working code.
Your problem is here:
node* add_element(node* current)
{
node* temp; //You created a new node
temp=new node; //You allocated it here
temp->next=NULL; //You set its next property to null
cout<<"enter element"<<endl; //
cin>>temp->x;
current=temp; //This should be current->next = temp. You are overwriting it!
return current; //And now you are returning essentially the temp object that
//You created and you set its next property to NULL
}
You are assigning the node you created in temp = new node to the current node that was passed in. What you want to do is assign the node you just created to the current node's next property. It should be current->next = temp
head->next is NULL because you set it so in add_element(). To have a linked list, you should set current->next = temp.
As you're using C++, you might consider using std::list instead of implementing your own linked list.
if (current==NULL)
{ current=add_element(current);
head=current;
}
else
{ current->next=add_element(current);
current=current->next;
}
The correct code.
You have to make a small correction in the loop.
You have to add a new node and then make it point to the next of the current node.
so the simplified code is current->next=add_element(current)
and then make current point to the new current.
#include <iostream>
using namespace std;
struct Node
{
int item; // storage for the node's item
Node* next; // pointer to the next node
};
Node* addNode(Node*& head, int data , int& count)
{
Node * q; // new node
q = new Node; // allocate memory for the new mode
q->item = data; // inserting data for the new node
q->next = head; // point to previous node ?? how would i do that? ( am i doing it correctly?)
count++; // keep track of number of node
head = q;
return q;
}
int main()
{
int a, count=0;
int data;
bool repeat;
Node *head= NULL;
//^^ assuming thats creating the first node ^^
do
{
cout << "please enter the data for the next node" <<endl;
cin >> data;
addNode(head, data, count);
cout << "do you wish to enter another node? (enter true or false)" << endl;
cin >>repeat;
}
while (repeat == true);
// assuming this is the print function
while(head != NULL)
{
cout << "output" << temp->item << endl;
cout << temp->next << endl;
}
system("pause");
return 0;
}
okey i tried adding a new element in the list how would i move the head around like a LIFO memory (stack) so the last element is on the very top..
any help would be appreciated ! The pointers and the nodes are messing with my brain lately ....
temp is an uninitialized pointer. So -
temp-> item = a; // temp is not initialized or pointing to a memory location
// that has Node object to use operator ->
First, temp needs to be allocated memory location using new.
temp = new Node;
temp -> item = a;
And now assign it head. Similarly allocate memory for the child nodes too in the while loop. And return all the resources acquired from child to head using delete before program termination.
You seem to have some misunderstandings here:
Your "head" is the start of the list. It's always the start.
You add append elements to a linked list by assigning them to the last node's next pointer.
Third, you're not allocating anything.
Node *head= new Node();
Node *temp = new Node();
cout<<"enter something into data"<<endl;
cin >> a ;
temp->item = a;
head->next = temp;
Now ... to add the next thing, you either need to keep track of the last node (tail), or traverse the list to find the last node.
Node *nextNode = new Node();
nextNode->item = 0.0;
Node *i;
for (i = head; i->next != null; i = i->next);
i->next = nextNode;
This is O(n) execution time. By keeping track of the tail you make it O(1):
Node *head= new Node();
Node *tail = head;
Node *temp = new Node();
cout<<"enter something into data"<<endl;
cin >> a ;
temp->item = a;
tail->next = temp;
tail = temp;
Node *nextNode = new Node();
nextNode->item = 0.0;
tail->next = nextNode;
tail = nextNode;
EDIT: As pointed out, if you want to prepend to the list, you would:
temp->next = head;
head = temp;
Since I'm not sure every answer completely answers it, here's a linked list implementation (written without testig:
// your (correct) structure
struct Node
{
float item; // storage for the node's item
Node* next; // pointer to the next node
};
Now we need two pointers somewhere to look after the list:
/* some pointers */
struct List
{
Node* head;
Node* tail;
};
Now we need to create some elements. As others have said, you can do that with new:
/* create some elements we want to link in */
Node* elem1 = new Node();
Node* elem2 = new Node();
Node* elem3 = new Node();
/* maybe even set their properties! */
elem1->item = 3.14;
elem2->item = 3.14;
elem3->item = 3.14;
Notice how I didn't try to add these elements to a list yet? That's because I've got a function in mind which looks like this:
void addtolist(List &list, Node* node)
{
/* if no head, initialise the list */
if ( list->head == NULL )
{
list->head = node;
list->tail = node;
}
else if ( list->head != NULL && list->tail != NULL )
{
/* access the tail element and set its
next to this ptr.
Move tail to this node */
list->tail->next = node;
list->tail = node;
}
else
{
/* probably raise an exception! */
}
}
You can call this by doing this:
List l;
addtolist(l, elem1); /* etc */
Deleting elements is somewhat more tricky, since you have to go to that element, remember its previous element, grab it's next element, join them up and delete the Node* you're on.
Now for traversing lists... your terminology HEAD|TAIL reminds me of Erlang and tail recursion, where the current element is referred to as the head and the remainder the tail. If I write:
Node* cur = l.head;
while ( cur != NULL )
{
// do something with cur.item ?
cur = cur->next;
}
You can see this happening. Replacing cur with head here would be harmless thanks to the List struct.
Finally, I've used a very C-like approach here, but there's scope for templates:
template<typename T>
struct node
{
T item; // storage for the node's item
Node<T>* next; // pointer to the next node
};
and encapsulating the List struct as a class:
template<typename T>
class List
{
protected:
Node<T>* head;
Node<T>* tail;
public:
void addtolist(Node<T>* node);
Node<T>* gethead();
Node<T>* gettail();
}
Which brings you a little bit closer to std::list.
Additionally note that you are doing an implicit cast from int to float on
temp-> item = a;
as a is an int, while temp->item is a double.
To solve your problem: You want to allocate a new structure before accessing temp, thus
temp = new Node();