I am having problem with a copy constructor for my Linked List class.
Function works properly but visual studio debugger has a "lag" so I can assume that something bad happens inside that function.
I cannot catch an error, and I don't know what is wrong in my logic.
Here's the code:
Linked_List::Linked_List(const Linked_List & obj)
: head(nullptr)
{
Node * currrentNode = obj.head;
Node * lastNode = nullptr;
while (currrentNode != nullptr)
{
Node * newNode = new Node;
newNode->character = currrentNode->character;
if (head != nullptr)
{
head = newNode;
lastNode = head;
}
else
{
lastNode->next = newNode;
lastNode = newNode;
}
currrentNode = currrentNode->next;
}
}
That code is inserting new nodes in the wrong direction. You are looping through the source list from front-to-back (as you should be), but you are trying to insert nodes into the target list in back-to-front order. But you are never assigning head at all, and you access lastNode before it has been assigned to point at a node. And worse, even if you were assigning the head and lastNode correctly, you are not updating each new node to point at the previous head node as its next node when you replace the current head with the new node. So your target list will still be malformed and leak memory.
The code should be inserting new nodes in front-to-back order instead:
Linked_List::Linked_List(const Linked_List & obj)
: head(nullptr)
{
Node * currentNode = obj.head;
Node * lastNode = nullptr;
while (currentNode)
{
Node * newNode = new Node;
newNode->character = currentNode->character;
if (lastNode)
lastNode->next = newNode;
else
head = newNode;
lastNode = newNode;
currentNode = currentNode->next;
}
}
Which can be simplified to this:
Linked_List::Linked_List(const Linked_List & obj)
: head(nullptr)
{
Node * currentNode = obj.head;
Node ** newNode = &head;
while (currentNode)
{
*newNode = new Node;
(*newNode)->character = currentNode->character;
newNode = &(newNode->next);
currentNode = currentNode->next;
}
}
Related
What am I doing wrong here? I'm new to linked lists and would appreciate some insight.
I am trying to add a new node in an empty list, or add a new node at the beginning if a node exists:
void insert(node* previous, int value){
if(previous == nullptr){
node* newNode = new node;
newNode->next = nullptr;
newNode->prev = nullptr;
(*head) = newNode;
(*tail) = newNode;
}else{
node* newNode = new node;
newNode->next = (*head);
newNode->prev = nullptr;
(*head)->prev = newNode;
(*head) = newNode;
}
}
class dlist {
public:
dlist() { }
struct node {
int value;
node* next;
node* prev;
};
node* head() const { return _head; }
node* tail() const { return _tail; }
private:
node* _head = nullptr;
node* _tail = nullptr;
}
There are these issues:
The code refers to head and tail, but these are not defined. There are _head and _tail members which should be used. They are not pointer-pointers, but just pointers.
The code uses previous only to test against nullptr, nothing more. This can never accomplish that the new node should be inserted after that previous node.
The code assumes that if previous is nullptr that the list is currently empty, but that is not the meaning of previous. previous is a reference to the node after which a new node must be inserted. This tells us nothing about the list being empty or not.
The code assumes that the new node will always become the first in the list (as newNode->prev is always set to nullptr), but the goal is to make newNode the successor of previous, so that when previous is an existing node, newNode->prev should point to that previous node.
The value argument is never used. This value should be assigned to the new node's value member.
Here is a possible correction to your code, although we have no way to test it on whichever platform you are to submit it:
void insert(node* previous, int value) {
node* newNode = new node; // Always create a new node (no matter what the case is)
newNode->value = value; // Assign the argument as value
newNode->prev = previous; // previous is always going to be the predecessor
if (previous == nullptr) { // newNode becomes the first node of the list
newNode->next = _head;
_head = newNode; // Set it is the new head
} else { // newNode must come after previous
newNode->next = previous->next;
previous->next = newNode; // Set the reverse link
}
// If there is a node after the new node, it should have a backreference to it
if (newNode->next != nullptr) {
newNode->next->prev = newNode;
}
if (_tail == previous) { // Update tail
_tail = newNode;
}
}
**following is my linked list code...
its not working for some reason. Can someone help me out here?
void insertAtTheEnd(node *&head, int data){
node *newNode= new node(data);
newNode->data=data;
node *temp=head;
while(temp!=NULL){
temp=temp->next;
}
temp->next=newNode;
newNode->next=NULL;
newNode->prev=temp->next;
}
As you have it coded, temp is guaranteed to be NULL when your while loop exits. Hence, temp->next=NULL will crash.
When you probe for a position in the list, you typically need to keep "previous" variable to point to the item before the one you are iterating with.
node* temp = head->next;
node* previous = head;
while (temp)
{
previous = temp;
temp = temp->next;
}
// when the while loop returns, `previous` is the last element in the list
previous->next = newNode;
newNode->prev = previous;
newNode->next = nullptr;
Another case you missing in your code. When head is NULL (empty list), you need to update head to be your newNode
// empty list - return the new node as head
if (head == nullptr)
{
newNode->next = nullptr;
newNode->prev = nullptr;
head = newNode;
return;
}
I have to write a method that's going to delete the last node from the List. Do you guys have any ideas on how I should approach this?
If you have a single-linked list, you have no choice but to iterate through the entire list to the last node, maintaining a pointer to the previous node so you can reset its next field when freeing the last node:
if (head)
{
node *curNode = head;
node *prevNode = NULL;
while (curNode->next)
{
prevNode = curNode;
curNode = curNode->next;
}
if (prevNode) prevNode->next = NULL;
delete curNode;
}
If you were using a double-linked list instead, this would be easier, as you can keep a pointer to the last node in the list and just operate on it directly:
if (head == tail)
{
delete head;
head = tail = NULL;
}
else if (tail)
{
node *curNode = tail;
tail = curNode->previous;
tail->next = NULL;
delete curNode;
}
Of course, if you are really using C++ then you should be using the STL's std::list (double-linked) or std::forward_list (single-linked) containers instead, which handle these details for you.
To delete the last element on a list all you need to do is maintain two separate nodes. Initially one should point to the head of the list and the other should point to the second element on the list. You should do something like the following :
if(head == NULL)
return 0;
else if(head->next == NULL){
Node *temp = head;
delete temp;
head = NULL;
}
else{
Node *one = head;
Node *two = head->next;
while(two->next != NULL){
two = two->next;
one = one->next;
}
one->next = NULL;
delete two;
}
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;
}
}
Hello My problem with this code is on my 2nd else loop; i never enter it and therefore i never make new nodes for my list. can anyone help me see what i am missing?
bool List::Insert(int data)
{
Node* P = new Node;
if(P==NULL)
{
return false;
}
else
{
P ->info = data;
P ->next = NULL;
if(Head == NULL)
{
Head = P;
}
else
{
Node* lastNode;
for(lastNode = Head; lastNode ->next != NULL; lastNode = lastNode ->next)
{
lastNode ->next = P;
}
}
return true;
}
}
This:
Node* lastNode;
for(lastNode = Head; lastNode ->next != NULL; lastNode = lastNode ->next)
{
lastNode ->next = P;
}
is dead wrong. It will change the next pointer, for every single node currently in the list, to point to your new node. You need to only change the pointer in the last node:
Node* lastNode = Head;
while (lastNode->next != NULL)
lastNode = lastNode->next;
lastNode->next = P;
You may also, for efficiency, want to maintain a separate Tail pointer (in addition to your Head) so that you can simply replace that whole operation with:
Tail->next = P;
Tail = P;
That way, you won't have to traverse the entire list every time you want to append a new node. Your code then becomes something like (without the traversal, and with updating the tail pointer as well):
// Prepare new node.
Node *P = new Node;
P->info = data;
P->next = NULL;
// If list empty, set head and tail to new node, otherwise
// append it.
if (Head == NULL) {
Head = P;
Tail = P;
} else {
Tail->next = P;
Tail = P;
}
I'll stop short of criticising the fact that your Insert method doesn't actually insert but rather appends. My near-anal-retentive nitpicking nature is unlikely to endear me to you:-)
lastNode ->next = P; // this must go after the for