I am trying to build a linked list in C++. My understanding is that the code I have created should create a node and then progressively link 4 more onto the end. Unfortunately, while I would expect to see the cout results as "12 123 1234 12345" I'm seeing "12 12 12 12" and in my main I am unable to traverse the list - it just crashes.
I have the following code:
struct listNode {
int val;
listNode* next;
};
int nodeCount = 0;
listNode* addToEnd(listNode* node) {
listNode* newNode = new listNode;
newNode->val = ++nodeCount;
newNode->next = NULL;
if (node == NULL) {
return newNode;
}
listNode* current = node;
cout<<"\n\n";
do {
if (current->next == NULL) {
current->next = newNode;
}
cout<<current->val<<"\n";
current = current->next;
} while (current->next != NULL);
cout<<current->val<<endl;
}
int main()
{
listNode* first = addToEnd(NULL);
addToEnd(first);
addToEnd(first);
addToEnd(first);
addToEnd(first);
cout<<"Third: "<<first->next->next->val;
}
Any help is appreciated, as I am at wit's end!
It is obvious that function addToEnd is wrong
listNode* addToEnd(listNode* node) {
listNode* newNode = new listNode;
newNode->val = ++nodeCount;
newNode->next = NULL;
if (node == NULL) {
return newNode;
}
listNode* current = node;
cout<<"\n\n";
do {
if (current->next == NULL) {
current->next = newNode;
}
cout<<current->val<<"\n";
current = current->next;
} while (current->next != NULL);
cout<<current->val<<endl;
}
Let's assume that the list already contains two nodes and consider the do-while loop inside the function. At first current_next != null so the following statement is executed
current = current->next;
Now current points to the second node. Its data member next is equal to NULL. So the condition of the loop
} while (current->next != NULL);
will be false and no iteration will be repeated. So we added nothing.
Also the function returns nothing if node is not equal to NULL.
Rewrite the function the following way
listNode* addToEnd( listNode* node )
{
listNode* newNode = new listNode { ++nodeCount, NULL };
if ( node == NULL) return newNode;
listNode* current = node;
while ( current->next != NULL ) current = current->next;
current->next = newNode;
return newNode;
// or
//return node;
}
Take into account that this statement
cout<<"Third: "<<first->next->next->val;
outputs only the value of the third node.
If you want to output all the list you should write
for ( listNode *current = first; current; current = current->next )
{
std::cout << current->val << ' ';
}
std::cout << std::endl;
By the way using my function you could write in main for example the following way:)
listNode* first;
addToEnd( addToEnd( addToEnd( addToEnd( first = addToEnd( NULL ) ) ) ) );
Use a for loop to get you to the last node instead of a while, and then assign the new node OUTSIDE of the loop. Trying to do it inside will result in an infinite loop (and make the code harder to read):
listNode* current;
for(current = node; current->next != NULL; current = current->next) ;
current->next = newNode;
You're also forgetting to return newNode at the end of the function.
You're falling off the end of a function with non-void return type. The fact that you don't use the return value does not make that ok.
6.6.3 in the Standard says that:
Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function.
There is no return statement just in case the if condition that checks if(node==null) fails..
Is it against the rules to use recursive functions in your question?
Why not do...
void addToEnd(listNode* node){
if(node == NULL){
*node = new listNode;
node->next = NULL;
node->val = ++nodeCount;
}else{
addToEnd(node->next);
}
return;
}
int main(){
listNode* first = NULL;
addToEnd(first); // 1
addToEnd(first); // 2
addToEnd(first); // 3
addToEnd(first); // 4
addToEnd(first); // Linked list is now 5 long
}
This is how I would have coded adding five nodes to a linked list that holds a node count. If anyone has advice it is welcome.
#include <iostream>
#include <cstdlib>
using namespace std;
struct listNode{
int val;
listNode* next;
};
listNode* addToEnd(listNode*, int);
int main()
{
listNode* first = NULL;
listNode* temp;
int nodeCount = 1;
for(int i = 0; i < 5; i++){
first = addToEnd(first, nodeCount);
nodeCount++;
}
temp = first;
while(temp){
cout << temp->val << ' ';
temp = temp->next;
}
temp = first;
//Deallocate memory
while(temp){ //could do memory deallocation while displaying
nodeToDelete = temp; //the value of nodeCount but wanted to illustrate
//both methods individually
temp = temp->next;
delete nodeToDelete;
}
first = NULL; //eliminate hanging pointer
return 0;
}
listNode* addToEnd(listNode* node, int nodeCount)
{
listNode* newNode = new (nothrow) listNode;
listNode* current = node;
if(newNode){
newNode->val = nodeCount;
newNode->next = NULL;
if (node == NULL)
node = newNode;
else{
while (current->next != NULL)
current = current->next;
current->next = newNode;
}
}
else
cout << "error allocationg memory" << endl;
return node;
}
Related
I am writing a program to check whether a singly linked list is a palindrome or not. For that, I want to reverse the list, and compare it to the original list.
But I am facing the following problem - when I reverse the list, the head pointer of the original list gets modified, and points to NULL.
So, when I have the following original list, following happens after reversing the original list:
Original list: 1->1->2->1->NULL
Reversed list: 1->2->1->1->NULL
But, after calling reverseList, the Original list becomes: 1->NULL
This is, because I have the following code to reverse the list:
ListNode* reverseList(ListNode* head)
{
ListNode* temp = head;
ListNode* temp1 = temp;
ListNode* current = NULL, * nextNode = NULL;
if (temp)
current = temp->next;
if (current)
nextNode = current->next;
while (current)
{
current->next = temp;
temp = current;
current = nextNode;
if (current)
nextNode = current->next;
}
temp1->next = NULL;
return temp;
}
As soon as I do temp1->next = NULL in the above reverseList function (the second last line in the function), the head of the original list is modified and the original list now points to 1->NULL, instead of 1->1->2->1->NULL.
Below if the full code, that calls the function reverseList:
struct ListNode
{
int val;
ListNode* next;
ListNode(int x):val(x),next(NULL){}
};
ListNode* reverseList(ListNode* head)
{
ListNode* temp = head;
ListNode* temp1 = temp;
ListNode* current = NULL, * nextNode = NULL;
if (temp)
current = temp->next;
if (current)
nextNode = current->next;
while (current)
{
current->next = temp;
temp = current;
current = nextNode;
if (current)
nextNode = current->next;
}
temp1->next = NULL;
return temp;
}
bool isPalindrome(ListNode* head) {
//reverse the Linked list and then compare the two lists.
if (head == NULL)
return true;
ListNode* head1 = head;
ListNode* head2 = reverseList(head);
while (head1 && head2)
{
if (head1->val != head2->val)
return false;
head1 = head1->next;
head2 = head2->next;
}
return true;
}
int main()
{
ListNode* head = new ListNode(1);
head->next = new ListNode(1);
head->next->next = new ListNode(2);
head->next->next->next = new ListNode(1);
head->next->next->next->next = NULL;
bool palindrome = isPalindrome(head);
cout << palindrome << endl;
return 0;
}
So, when the reverseList function returns, following happens in isPalindrome function:
head2 is set to: 1->2->1->1->NULL
head and head1 are set to 1->NULL
And I can no longer compare the two linked lists to check if they are palindromes of each other (since the comparison will give me wrong result).
This all is happening because I set temp1->next=NULL in the reverseList function.
Do you know how I should properly terminate the list in reverseList function, such that it does not effect the original list?
Thanks a lot!
Following is the corrected code, where I incorporated the Deep Copy of the original list (in isPalindrome function):
struct ListNode
{
int val;
ListNode* next;
ListNode(int x):val(x),next(NULL){}
};
ListNode* reverseList(ListNode* head)
{
ListNode* temp = head;
ListNode* temp1 = temp;
ListNode* current = NULL, * nextNode = NULL;
if (temp)
current = temp->next;
if (current)
nextNode = current->next;
while (current)
{
current->next = temp;
temp = current;
current = nextNode;
if (current)
nextNode = current->next;
}
temp1->next = NULL;
return temp;
}
bool isPalindrome(ListNode* head) {
//reverse the Linked list and then compare the two lists.
if (head == NULL)
return true;
ListNode* head1 = head;
ListNode* temp1 = NULL, *temp2=NULL;
bool firstEntry = true;
//Deep Copy
temp2 = temp1 = new ListNode(head1->val);
while (head1->next)
{
temp1->next = new ListNode(head1->next->val);
temp1 = temp1->next;
head1 = head1->next;
}
temp1->next = NULL;
ListNode* head2 = reverseList(head);
while (temp2 && head2)
{
if (temp2->val != head2->val)
return false;
temp2 = temp2->next;
head2 = head2->next;
}
return true;
}
int main()
{
ListNode* head = new ListNode(1);
head->next = new ListNode(1);
head->next->next = new ListNode(2);
head->next->next->next = new ListNode(1);
head->next->next->next->next = NULL;
bool palindrome = isPalindrome(head);
cout << palindrome << endl;
return 0;
}
It's been a week since i started learning about linked list and i only managed to learn about singly linked list. So today i implemented the linked list which i learned in c++ and while i tried to run it the code goes into an infinite loop of some random numbers. I tried debugging the code but i coudn't find whats so ever is wrong with the code. The code is below. Help is appreciated.Thanks
#include <iostream>
using namespace std;
struct node{
int data;
node * next;
};
class singly{
private:
node * head,*tail;
public:
singly(){
head=NULL;
tail=NULL;
}
void createNode(int value){
node * temp = new node;
temp->data=value;
temp->next=NULL;
if(head==NULL){
head=temp;
tail=temp;
temp=NULL;
}
else{
tail->next=temp;
tail=temp;
}
}
void display(){
node * temp = new node;
head=temp;
while(temp!=NULL){
cout << temp->data << "\t" << endl;
temp->next=temp;
}
}
void insert_end(int value){
node*newnode = new node;
node*temp = new node;
newnode->data=value;
newnode->next=NULL;
temp=head;
while(temp->next!=NULL){
temp = temp->next;
}
temp->next=newnode;
}
void delete_node(){
node*current = new node;
node*previous = new node;
current = head;
while(current->next!=NULL){
previous=current;
current=current->next;
}
tail=previous;
previous->next=NULL;
delete current;
}
};
int main(){
singly lists;
lists.createNode(32);
lists.createNode(654);
lists.createNode(34);
lists.createNode(234);
cout<<"\n--------------------------------------------------\n";
cout<<"---------------Displaying All nodes---------------";
cout<<"\n--------------------------------------------------\n";
lists.display();
cout<<"\n--------------------------------------------------\n";
cout<<"-----------------Inserting At End-----------------";
cout<<"\n--------------------------------------------------\n";
lists.createNode(55);
lists.display();
cout<<"\n--------------------------------------------------\n";
cout<<"-----------------Deleing At End-------------------";
cout<<"\n--------------------------------------------------\n";
lists.delete_node();
lists.display();
}
The member function display does not make sense.
It overwtites the data member head with uninitialized newly created temp.
node * temp = new node;
head=temp;
so the function invokes undefined behavior.
The function can look like
void display()
{
for ( node * temp = head; temp != nullptr; temp = temp->next )
{
cout << temp->data << "\t";
}
}
Or it is better to define it the following way
std::ostream & display( std::ostream &os = std::cout )
{
for ( node * temp = head; temp != nullptr; temp = temp->next )
{
os << temp->data << "\t";
}
return os;
}
The data member insert_end is also wrong. It does not take into account that head and tail can be equalto nullptr and does not change them.
The function can be defined the following way
void insert_end(int value)
{
node *newnode = new node { value, nullptr };
if ( tail == nullptr )
{
head = tail = newnode;
}
else
{
tail = tail->next = newnode;
}
}
The member function delete_node firstly does not make sense for a singly-linked list and again is wrong and invokes undefined behavior. The function should remove the first node from the list.
Nevertheless if you want to remove the last node from the list then the function can look like
void delete_node()
{
if ( head != nullptr )
{
tail = nullptr;
node *current = head;
while ( current->next )
{
tail = current;
current = current->next;
}
if ( tail == nullptr )
{
head = tail;
}
else
{
tail->next = nullptr;
}
delete current;
}
}
For starters, display() is wrong. You want the update to be temp = temp->next; and it can also be initialized as node * temp = head hence not requiring the second line.
Your delete_node() can be re-written to:
if (head->next == NULL) // handles the case that it consists of 1 element
{
delete head;
head = NULL;
}
else
{
node *nextToEnd = head;
node *end = head->next;
while (end->next != NULL)
{
nextToEnd = end;
end = end->next;
}
delete end;
nextToEnd->next = NULL;
}
As stated in the comments, review the use of the new keyword
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;
}
I don't understand why the display() func show me only the first member of the list. I think I did a mess with pointers, but I can't understand where. I have compared this to other linked list source and it seem that the function is written in the-good-way.
#include "stdafx.h"
#include <string>
#include <iostream>
using namespace std;
struct Node
{
int Data;
Node * next;
};
void initNode(struct Node *head,int n);
void AddNode(int n,Node* head);
void display(Node* head);
int main()
{
Node * head = new Node;
initNode(head,5);
display(head);
AddNode(10,head);
display(head);
AddNode(15,head);
display(head);
cin.get();
return 0;
}
void AddNode(int n,Node * head)
{
Node * node = new Node;
node->Data = n;
node->next = NULL;
Node * nextNode = head;
while(nextNode)
{
if(nextNode->next == NULL)
{
nextNode->next = node;
}
nextNode = nextNode->next;
}
}
void display(Node * head)
{
while(head)
{
cout << head->Data << " "<<endl;
head = head->next;
}
}
void initNode(struct Node *head,int n)
{
head->Data = n;
head->next = NULL;
}
Your AddNode method is over-complicated. Do something like this to add to the front:
Node *AddNode(int n, Node *head)
{
Node *newNode = new Node;
newNode->Data = n;
newNode->next = head;
return newNode;
}
Or to add to the end:
Node *AddNode(int n, Node *head)
{
Node *newNode = new Node;
newNode->Data = n;
newNode->next = NULL;
if(head == NULL) return newNode;
Node *current = head;
while(current->Next != NULL)
{
current = current->Next;
}
current->Next = newNode;
return head;
}
Doing AddNode this way you will not need initNode. Now you can just day:
Node *head = NULL;
head = AddNode(5, head);
head = AddNode(10, head);
head = AddNode(15, head);
display(head);
Also, you don't need to say struct Node in C++, it is only required in C.
Function AddNode has an infinite loop.
void AddNode(int n,Node * head)
{
Node * node = new Node;
node->Data = n;
node->next = NULL;
Node * nextNode = head;
while(nextNode)
{
if(nextNode->next == NULL)
{
nextNode->next = node;
}
nextNode = nextNode->next;
}
}
Let assume that you have only one element that is the head (after a call of initNode). And as the result head->next = NULL. So inside the body of the loop you make assignment
nextNode->next = node;
Now head->next is not equal to NULL. So after statement
nextNode = nextNode->next;
nextNode caontains the new element. As it is not equal to NULL then iteration of the loop will be repeated. Again for the new node its data member next is equal to NULL. And you add it to it itself.
Now you have no any element in the list that would have data member next equal to NULL. So you are unable to add new elements. The last element contains reference to itself.
You could write the function the following way
void AddNode(int n,Node * head)
{
Node * node = new Node;
node->Data = n;
node->next = NULL;
Node * nextNode = head;
while( nextNode -> next ) nextNode = nextNode->next;
nextNode->next = node;
}
But take into account that it is assumed that head is not equal to NULL. otherwise the function will be incorrect. I think that you should redesign you list.
In your AddNode function add a break in the if block.
void AddNode(int n,Node * head)
{
Node * node = new Node;
node->Data = n;
node->next = NULL;
Node * nextNode = head;
while(nextNode)
{
if(nextNode->next == NULL)
{
nextNode->next = node;
break;
}
nextNode = nextNode->next;
}
}
Now it should add properly.
Node * nextNode = head;
while(nextNode)
{
if(nextNode->next == NULL)
{
nextNode->next = node;
}
nextNode = nextNode->next;
}
The problem is this block of code. When you find the end of the list (if nextNode->next == NULL) you need to break out of the loop. Try it with an example to convince yourself.
Each time you add a node you traverse from head to the end of the list
You can change it as follows
void AddNode(int n){
Node *node=new Node;
node->data=n;
node->next=NULL; //head is global
if(head==NULL){
t=head=n;
}
else{
t->next=n; //t is global
t=t->next;
}
}
I know this is probably trivial to the c++ programmer, but I'm a noobie trying to figure this out. In my main, if I print my short list manually(cout << head->value etc) it works, but when I use my print function I get a segmentation fault. I've been trying to use a debugger, but I'm not very good at unix/c++ and I'm getting frustrated trying to figure this out.
#include <iostream>
using namespace std;
class ListNode
{
public:
int value;
ListNode* next;
};
void insertAtHead(ListNode** head, int value)
{
ListNode *newNode = new ListNode;
newNode->value = value;
if(head == NULL)
{
*head = newNode;
newNode->next = NULL;
}
else
{
newNode->next = *head;
*head = newNode;
}
}
void printList(ListNode* head)
{
while(head != NULL)
{
cout << head->value << "->";
head = head->next;
}
}
//inserts after the node with given value
void insertAfterNode(ListNode** head,ListNode** newNode, int value)
{
ListNode* current = *head;
while(current != NULL && (current->value != value))
{
//cout << "Im Here";
current = current->next;
cout << current->value;
}
(*newNode)->next = current->next;
current->next = *newNode;
}
int main()
{
ListNode *head;
insertAtHead(&head, 5);
insertAtHead(&head, 10);
ListNode* newNode = new ListNode;
newNode->value = 8;
newNode->next = NULL;
insertAfterNode(&head,&newNode, 5);
printList(head);
}
Check this modifications in your functions
void insertAtHead(ListNode** head, int value)
{
ListNode *newNode = new ListNode;
newNode->value = value;
newNode->next = *head;
*head = newNode;
}
void printList(const ListNode* head)
{
while(head != NULL)
{
cout << head->value << "->";
head = head->next;
}
}
In insertAtHead you are pasing a double pointer, so comparison should be like this.
Added checking for whether *head is null before accessing. and if null adding new node as head
void insertAfterNode(ListNode** head,ListNode** newNode, int value)
{
ListNode* current = *head;
if (current != NULL)
{
while(current != NULL && (current->value != value))
{
//cout << "Im Here";
current = current->next;
cout << current->value;
}
(*newNode)->next = current->next;
current->next = *newNode;
}
else
{
*head = *newNode;
}
}
And in main intialise head before use
int main()
{
ListNode *head = NULL;
insertAtHead(&head, 5);
printList(head); // <== note: by-value, not by address or reference.
You need to check if the next value you are trying to access is not null like this :
void printList(ListNode* head)
{
if (head != NULL)
{
while(head->next != NULL)
{
cout << head->value << "->";
head = head->next;
}
}
}
Dude the first answer is correct
But i would like to make another correction
In your while loop in function insert after node
current!=NULL is incorrect because then your condition will be true if and only if the last node in the list matches the value of 5
Condition should be just while(current->value!=value)
by this you will reach the node having value 5