I need to move the first item in a linked list to the end of the list. My problem is I'm going in to an infinite loop. When I remove the cause for the infinite loop (tail -> link != NULL; in the for loop), I get a seg fault. So, looking for ideas on how to get this code to work.
#include <iostream>
#include <string>
using namespace std;
struct Node
{
string data;
Node *link;
};
class Lilist
{
public:
Lilist() {head = NULL;}
void add(string item);
void show();
void move_front_to_back();
Node* search(string target);
private:
Node *head;
};
int main()
{
Lilist L1, L2;
string target;
L1.add("Charlie"); //add puts a name at the end of the list
L1.add("Lisa");
L1.add("Drew");
L1.add("Derrick");
L1.add("AJ");
L1.add("Bojian");
cout << "Now showing list One:\n";
L1.show(); // displays the list (This function displayed the list properly)
cout << "\n";
L1.move_front_to_back();
L1.move_front_to_back();
L1.show();
cout << "\n";
return(0);
}
void Lilist::add(string item)
{
Node *temp;
if(head == NULL)
{
head = new Node;
head -> data = item;
head -> link = NULL;
}
else
{
for(temp = head; temp -> link != NULL; temp = temp -> link)
;
temp -> link = new Node;
temp = temp -> link;
temp -> data = item;
temp -> link = NULL;
}
}
void Lilist::show()
{
for(Node *temp = head; temp != NULL; temp = temp -> link)
std::cout << temp -> data << " ";
}
void Lilist::move_front_to_back()
{
Node *temp;
Node *tail;
temp = head;
for(tail = head; tail != NULL; tail = tail -> link)
;
head = head -> link;
tail -> link = temp;
temp -> link = NULL;
}
The problem is in how you compute tail. Notice this (unrelated lines omitted for brevity):
for(tail = head; tail != NULL; tail = tail -> link)
;
tail -> link = temp;
Notice that the for loop will only terminate once tail is NULL. Then, you dereference tail ... which is null.
So change the for loop condition:
for (tail = head; tail->link != NULL; tail = tail->link)
;
This will find the last element in the list, instead of flowing off the end.
[Live example]
Angew already explained why your original code was failing. I would suggest an alternative approach - give Lilist a tail member that is managed alongside its head member. Then you don't have to hunt for the tail whenever you need it, you always know exactly which Node is the current tail, eg:
#include <iostream>
#include <string>
using namespace std;
struct Node
{
string data;
Node *next;
Node(string s);
};
class Lilist
{
public:
Lilist();
~Lilist();
void add(string item);
void show();
void move_front_to_back();
Node* search(string target);
private:
Node *head;
Node *tail;
};
Node::Node(string s)
: data(s), next(NULL)
{
}
Lilist::Lilist()
: head(NULL), tail(NULL)
{
}
Lilist::~Lilist()
{
for(Node *temp = head; temp != NULL; temp = temp->next)
delete temp;
}
void Lilist::add(string item)
{
Node *temp = new Node(item);
if (head == NULL)
head = temp;
if (tail != NULL)
tail->next = temp;
tail = temp;
}
void Lilist::show()
{
for(Node *temp = head; temp != NULL; temp = temp->next)
cout << temp->data << " ";
}
void Lilist::move_front_to_back()
{
if (head == tail)
return;
Node *temp = head;
head = temp->next;
temp->next = NULL;
tail->next = temp;
tail = temp;
}
Node* Lilist::search(string target)
{
for(Node *temp = head; temp != NULL; temp = temp->next)
{
if (temp->data == target)
return temp;
}
return NULL;
}
Related
I am trying to code for insertion and deletion in linked list.
Here is my code for basic insertion and deletion of nodes in a singly linked list.
There are no errors in the code, but the output on the terminal shows segmentation fault. Can someone explain why am I getting a segmentation fault? And what changes do i make to remove the fault.
I believe the segmentation fault is in the deletion part. Please help.
// class is a type of user defined datatype
class Node {
public:
int data;
Node* next;
//constructor
Node(int data) {
this -> data = data;
this -> next = NULL;
}
// destructor
~Node() {
int value = this -> data;
//memory free krr rhe hain
if(this -> next != NULL){
delete next;
this -> next = NULL;
}
cout << "memory is free for node with data" << value << endl;
}
};
void insertAtHead(Node* &head, int data) {
// creating new node called temp of type Node
Node* temp = new Node(data);
temp -> next = head;
head = temp;
}
void insertAtTail(Node* &head, Node* &tail, int data) {
// //New node create
// Node* temp = new Node(data);
// tail -> next = temp;
// tail = temp;
Node* temp = new Node(data);
if (head == nullptr) { // If this is the first node of the list
head = temp;
} else { // Only when there is already a tail node
tail -> next = temp;
}
tail = temp;
}
void insertAtPosition(Node* &tail, Node* &head, int position, int data) {
// Insert at starting
if(position == 1) {
insertAtHead(head, data);
return;
}
// Code for inserting in middle
Node* temp = head;
int cnt = 1;
while(cnt < position-1) {
temp = temp -> next;
cnt++;
}
// Creating a node for data
Node* nodeToInsert = new Node(data);
nodeToInsert -> next = temp -> next;
temp -> next = nodeToInsert;
// Inserting at last position (tail)
if(temp -> next == NULL) {
insertAtTail(head,tail, data);
return;
}
}
void deleteNode(int position, Node* &head) {
//deleting first or starting node
if(position == 1) {
Node* temp = head;
head = head -> next;
//memory free start node
temp -> next = NULL;
delete temp;
} else {
// deleting any middle node
Node* curr = head;
Node* prev = NULL;
int cnt = 1;
while(cnt <= position) {
prev = curr;
curr = curr -> next;
cnt++;
}
prev -> next = curr -> next;
curr -> next = NULL;
delete curr;
}
}
void print(Node* &head) {
Node* temp = head;
while(temp != NULL) {
cout << temp -> data << " ";
temp = temp -> next;
}
cout << endl;
}
int main() {
Node* head = nullptr; // A list has a head
Node* tail = head; // a tail.
insertAtHead(head, 10); // pass the head
insertAtTail(head, tail, 20);
insertAtTail(head, tail, 30);
insertAtHead(head, 5);
print(head); // Print the whole list
cout << "head" << head -> data << endl;
cout << "tail" << tail -> data << endl;
deleteNode(1, head);
print(head);
}
The problem is not with the delete function since even commenting it out leads to segmentation fault.
The problem is that you are initializing tail = head which is set to nullptr at the start. However, when you insertAtHead, you set the value of head but leave the tail to nullptr. You need to do tail = head when adding the first node (when head == nullptr).
Refer below for working code:
// Online C++ compiler to run C++ program online
#include <iostream>
using namespace std;
// class is a type of user defined datatype
class Node {
public:
int data;
Node* next;
//constructor
Node(int data) {
this -> data = data;
this -> next = NULL;
}
// destructor
~Node() {
int value = this -> data;
//memory free krr rhe hain
if(this -> next != NULL){
delete next;
this -> next = NULL;
}
cout << "memory is free for node with data" << value << endl;
}
};
void insertAtHead(Node* &head,Node* &tail, int data) {
// creating new node called temp of type Node
Node* temp = new Node(data);
temp -> next = head;
if (head == nullptr)
tail = temp; //inializing tail
head = temp;
}
void insertAtTail(Node* &head, Node* &tail, int data) {
// //New node create
// Node* temp = new Node(data);
// tail -> next = temp;
// tail = temp;
Node* temp = new Node(data);
if (head == nullptr) { // If this is the first node of the list
head = temp;
} else { // Only when there is already a tail node
tail -> next = temp;
}
tail = temp;
}
void insertAtPosition(Node* &tail, Node* &head, int position, int data) {
// Insert at starting
if(position == 1) {
insertAtHead(head,tail, data);
return;
}
// Code for inserting in middle
Node* temp = head;
int cnt = 1;
while(cnt < position-1) {
temp = temp -> next;
cnt++;
}
// Creating a node for data
Node* nodeToInsert = new Node(data);
nodeToInsert -> next = temp -> next;
temp -> next = nodeToInsert;
// Inserting at last position (tail)
if(temp -> next == NULL) {
insertAtTail(head,tail, data);
return;
}
}
void deleteNode(int position, Node* &head) {
//deleting first or starting node
if(position == 1) {
Node* temp = head;
head = head -> next;
//memory free start node
temp -> next = NULL;
delete temp;
} else {
// deleting any middle node
Node* curr = head;
Node* prev = NULL;
int cnt = 1;
while(cnt <= position) {
prev = curr;
curr = curr -> next;
cnt++;
}
prev -> next = curr -> next;
curr -> next = NULL;
delete curr;
}
}
void print(Node* &head) {
Node* temp = head;
while(temp != NULL) {
cout << temp -> data << " ";
temp = temp -> next;
}
cout << endl;
}
int main() {
Node* head = nullptr; // A list has a head
Node* tail = head; // a tail.
insertAtHead(head,tail, 10); // pass the head
insertAtTail(head, tail, 20);
insertAtTail(head, tail, 30);
insertAtHead(head,tail, 5);
print(head); // Print the whole list
cout << "head" << head -> data << endl;
cout << "tail" << tail -> data << endl;
deleteNode(1, head);
print(head);
}
The segfault is actually in the function insertAtTail(), and is because, while you handle the case where head is a null pointer, you do not handle the case where there is a head node but no tail node. The following code fixes this issue:
void insertAtTail(Node* &head, Node* &tail, int data) {
// //New node create
Node* temp = new Node(data);
if (head == nullptr) { // If this is the first node of the list
head = temp;
} else if (tail == nullptr) { // if there's a head but no tail
head -> next = temp;
} else { // Only when there is already a tail node
tail -> next = temp;
}
tail = temp;
}
If you have a look at this part of your code:
int main()
{
Node* head = nullptr; // A list has a head
Node* tail = head; // a tail.
insertAtHead(head, 10); // pass the head
insertAtTail(head, tail, 20);
return 0;
}
tail is a nullptr as you pass it into insertAtTail(head, tail, 20);
Then in insertAtTail you are going to access this nullptr:
void insertAtTail(Node* &head, Node* &tail, int data) {
// //New node create
// Node* temp = new Node(data);
// tail -> next = temp;
// tail = temp;
Node* temp = new Node(data);
if (head == nullptr) {
head = temp;
} else {
// here you have nullptr access resulting in your segmentation fault
tail -> next = temp;
}
tail = temp;
}
This code is supposed to reverse a linked list. The following code returns an empty linked list even when provided with a non empty list.
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* curr, *prev, *next;
if (head == NULL)
{
return head;
}
curr = head;
prev = NULL;
while (curr != NULL)
{
next = curr -> next;
curr -> next = prev;
prev = curr;
curr = next;
}
head = prev;
return head;
}
};
While this code strangely works where I added a cout statement just to check if the else was triggered.
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* curr, *prev, *next;
if (head == NULL)
{
cout << "Triggered";
return head;
}
curr = head;
prev = NULL;
while (curr != NULL)
{
next = curr -> next;
curr -> next = prev;
prev = curr;
curr = next;
}
head = prev;
return head;
}
};
Can someone please explain why this is happening?
Pretty simple, you have to initialize the pointers, else it leads to unexpected behavior that includes not showing it at all or just showing it if an initialized cout is triggered - but it doesn't have to do anything and that's up to your compiler implementation.
//cpp17
listNode* curr{}, *prev{}, *next{};
//before
listNode* curr = nullptr, *prev = nullptr, *next = nullptr;
It is still not in the reverse order as you intended to do.
class Solution {
public:
ListNode* reverseList(ListNode* head) {
listNode* curr{}, *prev{}, *next{};
//ListNode* curr, *prev, *next;
if (head == NULL)
{
return head;
}
curr = head;
prev = NULL;
while (next != NULL)
{
next = curr -> next;
curr -> next = prev;
prev = curr;
curr = next;
}
head = prev;
return head;
}
};
cheers :)
Like mentioned before I found time to write a solution for an other approach of solving your problem to reverse a linked list via class. For a better understanding for beginners I skipped the rule of three/five and initialized the list in the main function and not via constructor in the class:
#include <iostream>
class listElement
{
std::string data;
listElement* next;
listElement* last;
public:
void setData(std::string);
void append(std::string);
void displayElements();
void reverseDisplayElements(listElement*);
void freeMemory();
listElement* reverseList(listElement*);
};
void listElement::setData(std::string newData)
{
last = this;
data = newData;
next = nullptr;
}
void listElement::append(std::string newData)
{
// Double linked list
// last->next = new listElement();
// last->next->data = newData;
// last->next->next = nullptr;
// last = last->next;
// Singly linked list
//has next the value nullptr?
//If yes, next pointer
if (next == nullptr)
{
next = new listElement();
next->data = newData;
next->next = nullptr;
}
//else the method again
else
next->append(newData);
}
listElement* listElement::reverseList(listElement* head)
{
//return if no element in list
if(head == nullptr)
return nullptr;
//initialize temp
listElement* temp{};
while(head != nullptr){
listElement* next = head->next;
head->next = temp;
temp = head;
head = next;
}
return temp;
}
void listElement::displayElements()
{
//cout the first entry
std::cout << data << std::endl;
//if the end is not reached, call method next again
if (next != nullptr)
next->displayElements();
}
void listElement::reverseDisplayElements(listElement*head)
{
//recursiv from the last to the list beginning - stop
listElement *temp = head;
if(temp != nullptr)
{
if(temp->next != nullptr)
{
reverseDisplayElements(temp->next);
}
std::cout << temp->data << std::endl;
}
}
void listElement::freeMemory()
{
//If the end is not reached, call the method again
if (next != nullptr)
{
next->freeMemory();
delete(next);
}
}
int main ()
{
//Pointer to the Beginning of the list
listElement* linkedList;
//Creating the first element
linkedList = new listElement();
//Write data in the first element
linkedList->setData("Element 1");
//add more elements
linkedList->append("Element 2");
linkedList->append("Element 3");
linkedList->append("Element 4");
//display list
linkedList->displayElements();
//space divider
std::cout << "\nPrint in reverse order:" << std::endl;
//display list in reverse order
//pass list beginning as stop point
linkedList->reverseDisplayElements(linkedList);
std::cout << std::endl;
linkedList->displayElements();
std::cout << "\nReverse elements:" << std::endl;
linkedList = linkedList->reverseList(linkedList);
linkedList->displayElements();
std::cout << std::endl;
//destruct the list and free memory
linkedList->freeMemory();
delete(linkedList);
return 0;
}
Btw. there are many different solutions for that task.
Fairly new to implementing stacks and was looking for some possible feedback. My code gives the correct output, but I know this doesn't always mean it is working as it is suppose to. I chose to take the approach that implementing a stack using a linked list was essentially the same as your regular linked list implementation except that all the operations are done on the end of the list. I was not too sure if this approach was correct, but it followed the first in last out approach, and has the same complexity for access & search (O(n)) and insertion and deletion O(1). Such as pop() would just be deleting a node from the end of the linked list, and push() would just be appending a node to the end of the linked list. I have pasted my code below with comments within them explaining what I am doing or trying to do (if it is incorrect).
#include <iostream>
struct Node{
int data;
Node* next;
};
bool isEmpty(Node** stack){
if(*stack == NULL){
return true;
}
return false;
}
void push(Node** stack, int data){
Node* new_node = new Node();
new_node->data = data;
new_node->next=NULL;
// stack similar to "head"
if(isEmpty(&(*stack))){
*stack = new_node;
return;
}
Node* temp = *stack;
while(temp->next != NULL){
temp = temp->next;
}
temp->next = new_node;
}
void pop(Node** stack){
// checking if stack is empty
if(isEmpty(&(*stack))){
std::cout<<"Stack underflow"<<std::endl;
return;
}
Node* deleteMe = *stack;
// if at the first element in the stack
if(deleteMe->next == NULL){
*stack = (*stack)->next;
delete deleteMe;
return;
}
while(deleteMe->next != NULL){
if(deleteMe->next->next==NULL){
// saving the current location of the node before the node which I want to delete
Node* temp = deleteMe;
// updating the deleteMe pointer to the node which I want to delete
deleteMe = deleteMe->next;
// setting the current node before the deleteMe node to point to NULL instead of the node which I want to delete
temp->next = NULL;
delete deleteMe;
return;
}
deleteMe = deleteMe->next;
}
}
void printList(Node* stack){
Node* temp = stack;
while(temp!=NULL){
std::cout<<temp->data<<" ";
temp = temp->next;
}
std::cout<<"\n";
}
int top(Node** stack){
Node* top = *stack;
while(top->next!=NULL){
top = top->next;
}
return top->data;
}
int main(){
Node* stack = NULL;
// testing implementation below
push(&stack,10);
std::cout<<top(&stack)<<std::endl;
push(&stack,20);
std::cout<<top(&stack)<<std::endl;
push(&stack,30);
push(&stack,40);
printList(stack);
std::cout<<top(&stack)<<std::endl;
pop(&stack);
pop(&stack);
push(&stack,40);
std::cout<<top(&stack)<<std::endl;
}
Your implementation looks fine, one additional improvement can be done by maintaining head and tail pointer so that you can remove 1st and last element as needed. Here is example c++ code.
#include <iostream>
using namespace std;
template <class T> class node {
public:
node<T>() {}
~node<T>() {}
T data;
node<T> *next;
};
template <class T> class linked_list {
public:
linked_list<T>() : head(NULL), tail(NULL) {}
~linked_list<T>() {}
virtual void addFirst(T data) {
node<T> *n = new node<T>();
if (head == NULL)
tail = n;
n->data = data;
n->next = head;
head = n;
size++;
}
virtual void addLast(T data) {
node<T> *n = new node<T>();
n->data = data;
if (tail == NULL) {
head = n;
} else {
tail->next = n;
}
n->next = NULL;
tail = n;
}
virtual void reverse() {
if ((head == NULL) || (head->next == NULL))
return;
node<T> *current = head;
node<T> *previous = NULL;
node<T> *next = current->next;
tail = current;
while (current) {
next = current->next;
current->next = previous;
previous = current;
current = next;
}
head = previous;
}
virtual void print_nodes() {
node<T> *temp = head;
while (temp) {
cout << temp->data << " " << flush;
temp = temp->next;
}
cout << endl;
}
virtual void removeLast() {
node<T> *temp = head;
while (temp->next->next) {
temp = temp->next;
}
tail = temp;
delete temp->next;
temp->next = NULL;
}
virtual void removeFirst() {
node<T> *temp = head;
head = head->next;
delete temp;
}
private:
node<T> *head;
node<T> *tail;
uint32_t size;
};
int main(int argc, const char *argv[]) {
linked_list<uint32_t> *llist = new linked_list<uint32_t>();
llist->addLast(1);
llist->addFirst(5);
llist->addFirst(10);
llist->addFirst(15);
llist->addFirst(20);
llist->addLast(30);
llist->addFirst(40);
llist->print_nodes();
llist->reverse();
llist->print_nodes();
llist->removeLast();
llist->print_nodes();
llist->removeFirst();
llist->print_nodes();
return 0;
}
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.
I need to make a queue linked list in which the first node always has the smallest value , so it needs to be sorted , I have written this code :
#include <iostream>
using namespace std;
struct Node
{
int key;
Node *link;
};
class qlinkedlist
{
private:
Node *head;
Node *tail;
Node *curr;
Node *prev;
int count;
public:
void Enqueue(int value)
{
Node *newnode = new Node;
newnode -> key = value;
newnode -> link = NULL;
if(head==NULL)
{
head=tail=newnode;
count++;
}
else if(newnode->key < head->key)
{
newnode -> link = head;
head = newnode;
count++;
}
else
{
prev=head;
curr=head->link;
while(curr != NULL)
{
if(newnode->key < curr->key)
{
prev->link = newnode;
newnode->link = curr;
count++;
}
else
{
prev = curr;
curr = curr ->link;
}
}
}
}
void Dequeue()
{
if(head==NULL)
{
cout<< "Queue is empty" << endl;
}
else
{
curr = head;
head = head -> link;
delete curr;
count--;
}
}
void print()
{
curr = head;
while (curr!=NULL)
{
cout << curr -> key << endl;
curr = curr -> link;
}
}
};
void main()
{
qlinkedlist obj;
obj.Enqueue(5);
obj.Enqueue(4);
obj.Enqueue(3);
obj.Enqueue(2);
obj.Enqueue(1);
obj.print();
}
problem is it works only if I add nodes in the above order , for example if I try to add the 3 then 2 then 5 it does not work , what's wrong with the code ?
Thank you
Because if you try to add an element that is bigger than everything you have in the list, it will never pass your only condition to add a node: if(newnode->key < curr->key). Try this instead:
while(curr != NULL && newnode->key > curr->key)
{
prev = curr;
curr = curr ->link;
}
prev->link = newnode;
newnode->link = curr;
count++;
This way, you go through the linked list until you find the right spot, then add the new node even if you get to the end (curr==NULL).