I am trying to display a doubly linked list backwards, but every time I try to run anything even remotely touching the "prev" pointer in the program I get a seg fault.
I've been trying to figure this out for about 4 hours now and I just can't seem to pin it down. I can't tell if the issue is coming from my print backwards function or from the actual prev pointers themselves.
#include <iostream>
#include "list.h"
LinkedList::LinkedList(){
head = NULL;
tail = NULL;
};
bool LinkedList::addAtBeginning(int val){
Node *upd8L = head; // This Node will update Last
Node *upd8 = head;; // This Node will update the previous pointers
Node *point = new Node(); // This Node will insert the new node at the beginning
point->data=val; // This sets the data in the new node
point->next=head; // This sets the next pointer to the same as head
head = point; // This sets the head to the new Node
while(upd8){
upd8 = upd8->next;
upd8->prev = upd8L;
upd8L=upd8L->next;
}
return true;
};
bool LinkedList::remove(int val){
Node *temp = head;
Node *trail = 0;
while(temp != NULL){
if(temp->data == val){
if(temp->next == head->next){
head = head->next;
}else{
trail->next = temp->next;
}
delete temp;
}
trail = temp;
temp = temp->next;
}
return true;
};
void LinkedList::printForward() const{
Node *temp;
temp = head;
while(temp){
cout << temp -> data << endl;
temp = temp->next;
}
};
void LinkedList::printBackward() const{
Node *temp = head;
while(temp){
temp = temp->next;
cout << temp->data << endl;
}
while(temp){
cout << temp->data;
cout << "Pop" << endl;
temp = temp-> prev;
}
};
If possible, I'd love an explanation as to what is bugging up my program rather than just a straight answer, I want to know what I'm doing wrong and why it's wrong.
Thank you!
edit
Here's list.h
#ifndef LIST_H
#define LIST_H
#include <iostream>
using namespace std;
class LinkedList
{
private:
struct Node
{
int data;
Node * next;
Node * prev;
};
Node * head, * tail;
public:
LinkedList();
bool addAtBeginning(int val);
bool remove(int val);
void printForward() const;
void printBackward() const;
};
#endif
The function printBackward() may cause a seg-fault in the last iteration of the loop. while(temp) means iterate till you get the element out of the list NULL. Then you assigning temp = temp->next where temp->next is NULL. Now when you are calling cout << temp->data << endl; you are trying to get data from NULL pointer. Try to change the order. First display the node data, then change the temp pointer. An example:
void LinkedList::printBackward() const{
Node *temp = head;
while(temp){
cout << temp->data << endl;
temp = temp->next;
}
What you are doing wrong is getting the data from a NULL pointer.
So, I figured it out after a ton of trial and error!
The biggest issue I was having that kept giving me segmentation errors was whenever I was removing elements of the list I was failing to update the "prev" part of the node, and as a result any time I tried to read the list backwards I was getting a seg error.
//put your implementation of LinkedList class here
#include <iostream>
#include "list.h"
LinkedList::LinkedList(){
head = NULL;
tail = NULL;
};
bool LinkedList::addAtBeginning(int val){
Node *point = new Node(); // This Node will insert the new node at the beginning
point->data=val; // This sets the data in the new node
point->next=head; // This sets the next pointer to the same as head
head = point; // This sets the head to the new Node
if(head->next != NULL){
Node *temp = head->next;
temp->prev = head;
}
return true;
};
bool LinkedList::remove(int val){
Node *temp = head->next;
Node *trail = head;
if(head->data ==val){
head = head->next;
head->prev = NULL;
delete trail;
}else{
while(temp != NULL){
if(temp->data == val){
if(temp->next != NULL){
trail->next = temp->next;
delete temp;
temp= temp->next;
temp->prev=trail;
}else{delete temp;
trail->next = NULL;
}
}
trail = temp;
temp = temp->next;
}
}
return true;
};
void LinkedList::printForward() const{
Node *temp;
temp = head;
while(temp){
cout << temp->data << endl;
temp = temp->next;
}
};
void LinkedList::printBackward() const{
Node *temp = head;
while(temp->next != NULL){
temp = temp->next;
}
while(temp->prev != NULL){
cout << temp->data << endl;
temp = temp->prev;
}
cout << head->data << endl;
};
Related
I'm solving problems in algorithms and I have to reverse a forward linked list.
Here is my code:
For a node:
struct Node{
int value;
Node* next;
};
For reversing, here is the algorithm I made:
Node* reverse(Node* head){
Node* node = head->next;
Node* sentry = new Node;
sentry->next = head;
while(node != nullptr){
head->next = node->next;
node->next = sentry->next;
sentry->next = node;
node = head->next;
}
return sentry;
}
Here is a print function to test:
void print(Node* head){
Node* node = head->next;
while(node != nullptr){
std::cout << node->value << '-';
node = node->next;
}
}
The problem is that the reversed list has as last node the head, so when I try to do: delete head; before return sentry; to delete that node I get Core Dump error. I know that I can just search in internet a method to reverse the list, but I want to understand why this happens, why can't I just delete the head node.
Edit: here's is the code deleting the head:
Node* reverse(Node* head){
Node* node = head->next;
Node* sentry = new Node;
sentry->next = head;
while(node != nullptr){
head->next = node->next;
node->next = sentry->next;
sentry->next = node;
node = head->next;
}
delete head; // head = nullptr; also doesn't work.
return sentry;
}
Here is a main function to test:
int main(){
Node* node5 = new Node{5,nullptr};
Node* node4 = new Node{4,node5};
Node* node3 = new Node{3,node4};
Node* node2 = new Node{2,node3};
Node* node1 = new Node{1,node2};
Node* head = new Node;
head->next = node1;
head->value;
print(reverse(head));
return 0;
}
Let's look at your code:
void print(Node* head){
Node* node = head->next;
while(node != nullptr){
std::cout << node->value << '-';
node = node->next;
}
}
This code will never print the head. Slightly better code would be:
void print(Node* head) {
for (Node * node = head; node != nullptr; node = node->next) {
std::cout << node->value << '-';
}
}
Now, from your code in main it looks like you don't expect to print the head -- you're using it as a pointer. That would be odd. You basically have an extra, empty node just hanging out. So your main could do this:
int main(){
Node* node5 = new Node{5,nullptr};
Node* node4 = new Node{4,node5};
Node* node3 = new Node{3,node4};
Node* node2 = new Node{2,node3};
Node* head = new Node{1,node2};
std::cout << "Original version: ";
print(head);
std::cout << "\n\n";
std::cout << "Reversed version: ";
print(reverse(head));
std::cout << "\n";
return 0;
}
Finally, your reverse method is flat out broken. You shouldn't have to allocate anything.
Linked lists and other forms of linked structures (like trees) can be very confusing. At this stage in your learning, drawing pictures REALLY helps. I did so for years and years, and I still do when it gets complicated.
Note * reverse(Node *head) {
Node * prev = nullptr;
while (head != nullptr) {
Node * nextNode = head->next;
head->next = prev;
prev = head;
head = nextNode;
}
return prev;
}
There's probably a more elegant way to do this, but I don't want to think that hard :-)
Think about what this does. It keeps track of the previous node. The first time through the loop, there is no previous node. After that, the previous node is the old head, then old head->next, et cetera.
At each node, it sets the next pointer to this previous node. So head->next becomes nullptr (it's the new end of the list). Old Head->next->next comes old head, et cetera.
I haven't tested this code.
This is my final copy with a compile and output:
^ make Foo && Foo
g++ Foo.cpp -o Foo
Original: 1 : 2 : 3 : 4 : 5 :
Reversed: 5 : 4 : 3 : 2 : 1 :
^ cat Foo.cpp
#include <iostream>
struct Node{
Node (int v): value(v) {}
int value = 0;
Node* next = nullptr;
};
void print(Node* head);
Node * reverse(Node* head);
int main() {
// This part is gross, but I was in a hurry
Node * head = new Node(1);
head->next = new Node(2);
head->next->next = new Node(3);
head->next->next->next = new Node(4);
head->next->next->next->next = new Node(5);
std::cout << "Original: ";
print(head);
std::cout << "\n\nReversed: ";
print(reverse(head));
std::cout << "\n";
}
void print(Node* head) {
for (Node * node = head; node != nullptr; node = node->next) {
std::cout << node->value << " : ";
}
}
Node * reverse(Node *head) {
Node * prev = nullptr;
while (head != nullptr) {
Node * nextNode = head->next;
head->next = prev;
prev = head;
head = nextNode;
}
return prev;
}
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;
}
}
};
```
The following code works fine:
#include <iostream>
using namespace std;
struct Node{
int data;
struct Node *next;
Node(int data, Node *next = nullptr){
this->data = data;
this->next = next;
}
};
void push_back(Node **head, int data){
if(*head == nullptr){
*head = new Node(data);
}
else{
Node *current = *head;
while(current->next != nullptr){
current = current->next;
}
current->next = new Node(data);
}
}
void Print(Node **head){
Node *current = *head;
while(current != nullptr){
cout << current->data << " ";
current = current->next;
}
cout << endl;
}
int main(){
Node *head = nullptr;
push_back(&head, 5);
push_back(&head, 2);
push_back(&head, 1);
push_back(&head, -7);
Print(&head);
}
But when I try that bellow, nothing happens and head remains nullptr along with all the operations.
All I did was that I passed single pointers to function instead of double pointers:
#include <iostream>
using namespace std;
struct Node{
int data;
struct Node *next;
Node(int data, Node *next = nullptr){
this->data = data;
this->next = next;
}
};
void push_back(Node *head, int data){
if(head == nullptr){
head = new Node(data);
}
else{
Node *current = head;
while(current->next != nullptr){
current = current->next;
}
current->next = new Node(data);
}
}
void Print(Node *head){
Node *current = head;
while(current != nullptr){
cout << current->data << " ";
current = current->next;
}
cout << endl;
}
int main(){
Node *head = nullptr;
push_back(head, 5);
push_back(head, 2);
push_back(head, 1);
push_back(head, -7);
Print(head);
}
I don't understand why do I need double pointers to make it work?
Is the second program only sending a copy of head to the functions and nothing more?
void push_back(Node *head, int data){
if(head == nullptr){
head = new Node(data);
}
else{
Node *current = head;
while(current->next != nullptr){
current = current->next;
}
current->next = new Node(data);
}
}
you can't change the value of pointer head by push_back in main function. We can change a object by passing its pointer or reference to another function, but not by passing itself! So each time head = new Node(data);(try to change head) actually not change head in the function which called push back() and caused memory overflow
How do I make my program print the Linked List backwards? I got the printForward function working fine but the printBackwards function just doesn't seem to do anything. I think I'm on the right track but I'm a little stuck right now. I think the while loop isn't running because temp is NULL for some reason.
Any help would be great.
Thanks
List.h
#include <iostream>
using namespace std;
class LinkedList
{
private:
struct Node
{
int data;
Node * next;
Node * prev;
};
Node * head, *tail;
public:
LinkedList();
bool addAtBeginning(int val);
bool remove(int val);
void printForward() const;
void printBackward() const;
};
#endif
List.cpp
#include "List.h"
LinkedList::LinkedList()
{
head = NULL;
tail = NULL;
}
bool LinkedList::addAtBeginning(int val)
{
Node* temp;
temp = new Node;
temp->data = val;
temp->next = head;
head = temp;
return false;
}
bool LinkedList::remove(int val)
{
return false;
}
void LinkedList::printForward() const
{
Node* temp = head;
while (temp != NULL) {
cout << temp->data << " ";
temp = temp->next;
}
cout << endl;
}
void LinkedList::printBackward() const
{
Node* temp = tail;
while (temp != NULL) {
cout << temp->data << " ";
temp = temp->prev;
}
cout << endl;
}
app.cpp
#include "list.h"
int main()
{
LinkedList aList;
aList.addAtBeginning(3);
aList.addAtBeginning(10);
aList.addAtBeginning(1);
aList.addAtBeginning(7);
aList.addAtBeginning(9);
aList.addAtBeginning(12);
aList.printForward();
aList.printBackward();
system("pause");
return 0;
}
I find it a bit odd that you only have an addAtBeginning method, and no method to add at the end, the latter which I would consider to be normal use of a linked list. That being said, I think the immediate problem here is that you never assign the tail to anything. Try this version of addAtBeginning:
bool LinkedList::addAtBeginning(int val)
{
Node* temp;
temp = new Node;
temp->data = val;
temp->next = head;
if (head != NULL)
{
head->prev = temp;
}
if (head == NULL)
{
tail = temp;
}
head = temp;
return false;
`}
The logic here is that for the first addition to an empty list, we assign the head and tail to the initial node. Then, in subsequent additions, we add a new element to the head of the list, and then assign both the next and prev pointers, to link the new node in both directions. This should allow you to iterate the list backwards, starting with the tail.
Update addAtBeginning function with given:
bool LinkedList::addAtBeginning(int val)
{
Node* temp;
temp = new Node;
temp->data = val;
temp->prev = temp->next = NULL;
// If adding first node, then head is NULL.
// Then, set Head and Tail to this new added node
if(head == NULL){
// If this linked list is circular
temp->next = temp->prev = temp;
head = tail = temp;
}else{ // If we already have at least one node in the list
// If this linked list is circular
temp->prev = head->prev;
temp->next = head;
head->prev = temp;
head = temp;
}
return false;
}
But remember, if you copy this function with the parts that it makes this list circular, you will get an infinite loop. So, either change print function or dont copy that parts.
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