How to adjust head, tail pointers when building a LinkedList - c++

I am making a simple implementation of LinkedList. My Trial:
#include<bits/stdc++.h>
using namespace std;
class ListNode
{
public:
ListNode* next;
int val;
ListNode(int x) : val(x), next(NULL) {}
};
int main()
{
ListNode* head = NULL;
ListNode* tail;
int data;
cout<<"Enter data. Enter -1 to terminate insertion"<<endl;
while(1)
{
cin>>data;
if(data != -1)
{
if(head == NULL)
{
head = new ListNode(data); // Returns the address of a new ListNode and stores it in head
tail = head->next; // tail now points to head's next
}
else
{
tail = new ListNode(data); // address of a new ListNode is in tail
tail = tail->next; // Tail now points to the new ListNode's next
}
}
else
break;
}
tail = NULL; // Tail ends with a NULL
while(head)
{
cout<<head->val<<" ";
head = head->next;
}
}
When I input 1, 2, 3: I expect the Linked List to be formed as 1->2->3->NULL.
However, the Linked List is always only the first element 1->NULL
I ran on the debugger and indeed, head->next is always NULL. But I dont understand why. I am specifically changing head's next to a new ListNode non-null address when I do tail = new ListNode(data), but apparently thats not happening. Where am I going wrong?
Here is the code: http://cpp.sh/6ardx

Problem: tail is always NULL.
How do you want to make the connection between tail and appended node to your list when tail is NULL ?
When list is empty and you create the first node, after inserting first node head and tail should point to the same node. Change
if(head == NULL)
{
head = new ListNode(data); // Returns the address of a new ListNode and stores it in head
tail = head->next; // tail now points to head's next
}
to
if(head == NULL)
{
tail = head = new ListNode(data); // Returns the address of a new ListNode and stores it in head
}
the second issue, when you add to the end of list you should update tail->next to point to the inserted node, so change
tail = new ListNode(data); // address of a new ListNode is in tail
tail = tail->next; // Tail now points to the new ListNode's next
to
tail->next = new ListNode(data); // address of a new ListNode is in tail
tail = tail->next; // Tail now points to the new ListNode's next

Related

LInked list not reversing

Bellow, I have some code that is supposed to display a linked list, reverse it, and then display the now reversed linked list, but it seems that it never displays. My only guess is that somehow the linked list is becoming null. What am I doing wrong? Both the reverse function and the function that should display the reversed array run, but there is no visual output after.
#include <iostream>
using namespace std;
class Node{
public:// creation of a simple Node class
int data;
Node* next;
};
class LinkedList{
public:
Node* head;
LinkedList() { head = NULL; }
void append( int x){
Node* temp = new Node;// allocate new node
Node* end = head;//used later
temp->data = x;//giving the node data
temp->next = NULL;//since this node will be last make the next of it NULL
if(head == NULL){// if list is empty then set new Node as the head
head = temp;
return;
}
while(end->next != NULL){// go until the last node
end = end->next;
}
end->next = temp;// change the next of the last node to the new node.
}
void reverse(){
Node* current = head;
Node* next = NULL;
Node* prev = NULL;
while(current != NULL){
next = current->next;// Store next
current->next = prev;// Reverse current node's pointer
prev = current;// Move pointers one position ahead.
current = next;
}
head = prev;
}
void display(){
while(head != NULL){// print data while not out of bounds
cout<<" "<<head->data;
head = head->next;
}
}
};
int main() {
LinkedList list;
list.append(1);
list.append(10);
list.append(32);
list.append(64);
list.append(102);
list.append(93);
list.display();
cout<<endl;
list.reverse();
cout<<"list reversed"<<endl;
list.display();
cout<<"reverse display ran"<<endl;
Turns out it was an oversight on my part, I should have set up a temporary variable that represented the head, in my current program I'm changing what head references in order to loop through the linked list, and thus setting head equal to null once it reaches the end of the list a correct way to write the display function would be:
void display(){
Node* temp = head;
while(temp != NULL){// print data while not out of bounds
cout<<" "<<temp->data;
temp = temp->next;
}
}
thanks to user Retired Ninja for reminding me that debuggers exist.

Strange behaviour when I am trying to implement my linked list in c++

I'm trying to implement my singly linked list , and I have this problem:
When I'm trying to pushBack some elements in my linked list , it will print only the first one which I added.For example , if I try to pushBack 2,3,4 - it will print only 2.
In case if I want to pushUp some elements in my linked list , it will print only the third one which I added. For example , if I try to pushUp 2,3,4 - it will print only 4.
This is my code:
enter code here
#include<iostream>
#include<vector>
using namespace std;
struct Node {
int data;
Node* next;
};
class LinkedList {
private:
// Create pointers for head and tail
Node *head , *tail;
public:
LinkedList(){
// Initiate them as null pointers
head = NULL;
tail = NULL;
}
public:
void pushBack(int value){
// Should add a node at the end of the linked list
Node* temp = new Node(); // temporary node which should be added
temp->data = value; // value to store
temp->next = NULL; // pointer to the next node
if(head != NULL){
// If there are some elements , then
temp->next = tail->next;
tail = temp;
}
if(head == NULL){
// If there are no elements , our node will be a head and a tail in the same time.
head = temp;
tail = temp;
}
}
void pushUp(int value){
// Shound add a node at the beginning of the linked list
Node* temp = new Node();
temp->data = value;
temp->next = NULL;
if(head == NULL){
// If there are no elements , our node will be a head and a tail in the same time.
head = temp;
tail = temp;
}
if(head != NULL){
// If there are some elements , just make our node to be new head.
temp->next = head->next;
head = temp;
}
}
void traversal(){
Node *temp = new Node();
temp = head;
while(temp != NULL){
cout << temp->data << " ";
temp = temp->next;
}
}
};
int main(){
// Pointer for our first node.
LinkedList a;
a.pushUp(2);
a.pushUp(124);
a.pushUp(3);
// a.pushBack(2);
// a.pushBack(124);
// a.pushBack(3); // Outputs only 2
a.traversal(); // Outputs only 3
}
You are missing edge cases. When you add the first node you are pointing it via head and tail ok but then you should check if there is only one node by comparing the address. And you should consider it for both function because if there is only one node head tail will change or head will be overwritten in your code.

class LinkedList {
private:
// Create pointers for head and tail
Node *head , *tail;
public:
LinkedList(){
// Initiate them as null pointers
head = NULL;
tail = NULL;
}
public:
void pushBack(int value){
// Should add a node at the end of the linked list
Node* temp = new Node(); // temporary node which should be added
temp->data = value; // value to store
temp->next = NULL; // pointer to the next node
if(head != NULL){
// If there are some elements , then
if(tail!=NULL){
tail->next = temp;
}else {
tail = temp;
head->next = tail;
}
}else {
// If there are no elements , our node will be a head and a tail in the same time.
head = temp;
}
}
void pushUp(int value){
// Shound add a node at the beginning of the linked list
Node* temp = new Node();
temp->data = value;
temp->next = NULL;
if(head == NULL){
// If there are no elements , our node will be a head and a tail in the same time.
head = temp;
}else {
// If there are some elements , just make our node to be new head.
if(tail != NULL){
temp->next = head;
head = temp;
}else {
tail = head;
head = temp;
temp->next = tail;
}
}
}
void traversal(){
Node *temp = new Node();
temp = head;
while(temp != NULL){
cout << temp->data << " ";
temp = temp->next;
}
}
};

```

Why it is printing only 1st value of doubly linked list and than my program is crashing

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;
}

C++ linked lists read access violation

I'm new to C++ and I'm currently studying linked lists and I came upon this problem and I still can't find a solution.
This is how a basic node looks like.
struct node {
int data;
node *next;
};
I'm trying to swap the position of the first and the last node with this function.
void swap_first_and_last() {
node *temp = new node;
node *temp2 = new node;
temp->data = head->data;
temp->next = NULL;
temp2->next = head->next;
temp2->data = tail->data;
head = temp2;
tail = temp;
}
The error I'm getting is: Exception thrown: read access violation, this->tail was nullptr.
Can anyone explain what I'm doing wrong?
You havn't deleted head & tail.
Assuming tail is the last, there is somewhere a node::next pointing to it, and you didn't changed it to point to temp
What if the list is empty? you didn't checked if head or tail is null.
Edit added fixed method
void swap_first_and_last()
{
//if there is less than 2 nodes - finished.
if(!head || !tail || head==tail) return;
node *temp = new node;
node *temp2 = new node;
node *temp3;
temp->data = head->data;
temp->next = NULL;
temp2->next = head->next;
temp2->data = tail->data;
temp3 = head;
head = temp2;
delete temp3; //delete old head
temp3 = tail;
//find the tail previous
for(tail=head; tail->next!=temp3;tail=tail->next);
//make tail previous point to tail
tail->next = temp;
tail = temp;//now it will point to new tail...
delete temp3;//delete old tail
}
A better solution:
void swap_first_and_last()
{
node *temp;
//if there is less than 2 nodes - finished.
if(!head || !tail || head==tail) return;
for(temp=head; temp->next!=tail;temp=temp->next);
temp->next = head; //set tail precedor's next to point to head, prepere for head = tail
tail->next = head->next; //set tail's next to point head->next, prepere for head = tail
head = tail; //set tail as head
tail = temp->next; //set old head as tail
tail->next = NULL; // tail next is always null (was point to the 2nd).
}
// V----- where does tail get initialized?
temp2->data = tail->data;
When swap_first_and_last is called, but tail hasn't been initialized, just as the runtime says: you're going to have a bad time.
You can either -
Make sure that tail is initialized with a value before calling
swap_first_and_last
Check to see if tail is initialized before
trying to do any read access on it.
I think the latter is a better option.
if (head) {
temp->data = head->data;
}
if (tail) {
temp2->data = tail->data;
}
A question you should ask yourself - why don't I put this initialization in the constructor of node?
Your new to C++ so I understand this isn't particularly easy to grasp, but once you get the hang of it you will understand the comments above.
head and tail are pointers node *head; so you don't need to create copies of the objects that they point to.
head points to a block of memory that has the content (data = 42; next = tail) and tail points to a block of memory that holds (7 and null). You can copy head into temp and tail into temp2 and then copy them back into tail and head but why? What do you gain by creating copies of the memory blocks, apart from memory leaks? You don't care about the blocks of memory, you don't want to move them, you don't want to change them all you want to do is change which pointer points to which block of memory.
node* pTemp = head;
head = tail;
tail = head;
Unfortunately this breaks your list because now head->next = null so you just need to repair that:
pTemp = head->next; // Which should always be null.
head->next = tail->next;
tail->next = pTemp;
Now if you stick that in a little function that takes the two pointers as parameters you have a block of code that can switch any two given nodes in your list, meaning sorting your list becomes a lot easier.

Linked List pushback member function implementation

I am a novice programmer and this is my second question on Stack Overflow.
I am trying to implement a pushback function for my Linked List by using a tail pointer. It seems straightforward enough, but I have a nagging feeling that I am forgetting something or that my logic is screwy. Linked Lists are hard!
Here is my code:
template <typename T>
void LinkedList<T>::push_back(const T n)
{
Node *newNode; // Points to a newly allocated node
// A new node is created and the value that was passed to the function is stored within.
newNode = new Node;
newNode->mData = n;
newNode->mNext = nullptr;
newNode->mPrev = nullptr;
//If the list is empty, set head to point to the new node.
if (head == nullptr)
{
head = newNode;
if (tail == nullptr)
{
tail = head;
}
}
else // Else set tail to point to the new node.
tail->mPrev = newNode;
}
Thank you for taking the time to read this.
Your pointing the wrong mPrev to the wrong node. And you never set mNext of the prior tail node if it was non-null to continue the forward chain of your list.
template <typename T>
void LinkedList<T>::push_back(const T n)
{
Node *newNode; // Points to a newly allocated node
// A new node is created and the value that was passed to the function is stored within.
newNode = new Node;
newNode->mData = n;
newNode->mNext = nullptr;
newNode->mPrev = tail; // may be null, but that's ok.
//If the list is empty, set head to point to the new node.
if (head == nullptr)
head = newNode;
else
tail->mNext = newNode; // if head is non-null, tail should be too
tail = newNode;
}