Implementing a linked list in c++ - c++

This code is printing 30 only what's wrong on this?
I've followed this tutorial
https://www.codementor.io/codementorteam/a-comprehensive-guide-to-implementation-of-singly-linked-list-using-c_plus_plus-ondlm5azr
I've no idea on how this printing only 30? Anything wrong on this code?
#include <iostream>
using namespace std;
struct node {
int data;
node *next;
};
class LinkedList {
private:
node *head, *tail;
public:
LinkedList() {
head = NULL;
tail = NULL;
}
// For adding nodes
void addNode(int value) {
node *tmp = new node;
tmp->data = value;
tmp->next = NULL;
if(head == tail) {
head = tmp;
tail = tmp;
tmp = NULL;
} else {
tail->next = tmp;
tail = tail->next;
}
}
// For displaying nodes
void display() {
node *tmp = head;
while(tmp != NULL) {
cout << tmp->data << endl;
tmp = tmp->next;
}
}
};
int main()
{
LinkedList a;
// For adding nodes
a.addNode(10);
a.addNode(20);
a.addNode(30);
// For displaying nodes
a.display();
return 0;
}

if condtion always returns true:
if(head == tail) {
at first insertion it returns true because head and tail are NULLs. At the second insertion this condition returns true as well, because head and tail are the same, and so on. So you don't add new items, but you always overwrite the first item.
You should fix it by
if (head == NULL)

I think the error is at line if(head == tail), if you change it to if(head == NULL) it should print 10 20 30. However, if you are wondering why if(head == tail) is causing this issue is because for every addNode operation head and tail are equal and at last head is also poiting to 30!

Related

Doubly Linked List Node Insertion in the end

I am trying to create a function for adding at the end for doubly linklist. I can't pinpoint out why it does not print out anything.
There was no error coming out when I build the program.
I am making sure
1. new node check if the head has any value first
created following pointer that is previous current
I connected previous node to new node and new node point to previous node while new node point out to nullptr as next.
#include "pch.h"
#include <iostream>
using namespace std;
class list;
class node {
public:
int data;
node *next;
node *prev;
friend class list;
};
class list {//double list
node* head;
node* tail;
public:
list(){ head = nullptr; tail = nullptr; head->next = tail; tail->prev = head;}
node* pushback(int newdata) {
node* curr = new node;
curr->data = newdata;
curr->next = nullptr;
if (head == nullptr) {
head = curr;
return head;
}
node*precurr = head;
while (precurr->next != nullptr){
precurr = precurr->next;
}
precurr->next = curr;
curr->prev = precurr;
return head;
}
void print() {
while (head->next != nullptr) {
cout << head->data << " " << endl;
head = head->next;
}
}
};
int main()
{
list test;
test.pushback(1);
test.pushback(2);
test.pushback(3);
test.pushback(4);
test.pushback(5);
test.pushback(6);
test.print();
return 0;
}
You have done a lot of things correctly, but you are confused on your constructor and on your use of the ->prev and tail pointers.
You immediate issue with your constructor, as identified in the comments, is you set head and tail to nullptr and then immediately derefernce both head and tail attempting to make head and tail self-referencing (which is only needed in a circular linked-list).
list(){ head = nullptr; tail = nullptr; head->next = tail; tail->prev = head;}
With head and tail to set to nullptr, you don't have a pointer to a valid node than can be dereferenced. Your attempt to set head->next = tail; tail->prev = head; fails immediately resulting in a SegFault.
For purposes on a normal non-circular list, you simply omit setting head->next and tail->prev in your constructor, e.g.
list() { head = nullptr; tail = nullptr; }
If you want to make your list a circular list, then you will make head and tail self-referencing in:
node *pushback (int newdata) {
...
if (head == nullptr) /* for circular-list 1st node initialization */
head = tail = head->prev = head->next = tail->prev = tail->next = curr;
(note: a tail pointer is optional with a circular list as head->prev always points to the last node in the list)
Since your question pertains to a double-linked-list and not a circular list, you simply need to set both head and tail equal to the new node curr for the addition of the 1st node, e.g.
node *pushback (int newdata) {
node *curr = new node;
curr->data = newdata;
curr->next = curr->prev = nullptr;
if (head == nullptr)
head = tail = curr;
For all other nodes, there is NO iteration required (that's what a tail pointer is for), you simply set curr->prev to tail, tail->next to curr and then update the tail pointer to the new end node by setting tail = curr;, e.g.
else {
curr->prev = tail;
tail->next = curr;
tail = curr;
}
return head;
}
The purpose of a double-linked-list is to allow you to iterate in both the forward and reverse direction over your nodes. For example:
void printfwd() {
node *iter = head;
while (iter != nullptr) {
std::cout << ' ' << iter->data;
iter = iter->next;
}
std::cout.put('\n');
}
void printrev() {
node *iter = tail;
while (iter != nullptr) {
std::cout << ' ' << iter->data;
iter = iter->prev;
}
std::cout.put('\n');
}
(the iteration scheme is slightly different for a circular list since you can iterate from any node in both forward and reverse direction without needed to start from head or tail. To insert in order for a circular list, you simply insert a new tail node).
Don't develop bad habits. Why is “using namespace std;” considered bad practice? Currently all you have to deal with is cout and endl, go ahead and remove using namespace std; and simply prefix cout and endl with std::.
Putting it altogether, you would have:
#include <iostream>
class list;
class node {
public:
int data;
node *next;
node *prev;
friend class list;
};
class list {//double list
node *head;
node *tail;
public:
list() { head = nullptr; tail = nullptr; }
node *pushback (int newdata) {
node *curr = new node;
curr->data = newdata;
curr->next = curr->prev = nullptr;
if (head == nullptr)
head = tail = curr;
else {
curr->prev = tail;
tail->next = curr;
tail = curr;
}
return head;
}
void printfwd() {
node *iter = head;
while (iter != nullptr) {
std::cout << ' ' << iter->data;
iter = iter->next;
}
std::cout.put('\n');
}
void printrev() {
node *iter = tail;
while (iter != nullptr) {
std::cout << ' ' << iter->data;
iter = iter->prev;
}
std::cout.put('\n');
}
};
int main() {
list test;
for (int i = 1; i <= 10; i++)
test.pushback(i);
std::cout << "\nforward:\n";
test.printfwd();
std::cout << "\nreverse:\n";
test.printrev();
}
Example Use/Output
$ ./bin/ll_double_int
forward:
1 2 3 4 5 6 7 8 9 10
reverse:
10 9 8 7 6 5 4 3 2 1
Look things over and let me know if you have further questions.

Reverse a linked list using recursion

The void reve(struct Node *head) and display(struct Node *head) methods take one argument - the head of the linked list. I want to print the whole linked list but my display function print only 4.
#include <iostream>
using namespace std;
struct Node {
int data;
struct Node *link;
};
void display(struct Node *head) {
if (head == NULL) {
return;
}
cout << head->data << "\t";
display(head->link);
//head = head->link;
}
struct Node *reve(struct Node *head) {
struct Node *p = head;
if (p->link == NULL) {
head = p;
return head;
}
reve(p->link);
struct Node *temp = p->link;
temp->link = p;
p->link = NULL;
}
struct Node *insert(struct Node *head, int new_data) {
Node *new_node = new Node();
new_node->data = new_data;
new_node->link = head;
head = new_node;
return head;
}
int main() {
Node *head = NULL;
head = insert(head, 1);
head = insert(head, 2);
head = insert(head, 3);
head = insert(head, 4);
cout << "The linked list is: ";
//display(head);
head = reve(head);
display(head);
return 0;
}
Output
If you want the recursive way:
Node* reverse(Node* head)
{
if (head == NULL || head->next == NULL)
return head;
/* reverse the rest list and put
the first element at the end */
Node* rest = reverse(head->next);
head->next->next = head;
head->next = NULL;
/* fix the head pointer */
return rest;
}
/* Function to print linked list */
void print()
{
struct Node* temp = head;
while (temp != NULL) {
cout << temp->data << " ";
temp = temp->next;
}
}
The function reve does not return a value if p->link is not NULL.
Since head has more than 1 element, head = reve(head); has undefined behavior.
Reversing a linked list is much easier to implemented in a simple loop than with recursion:
struct Node *reve(struct Node *p) {
if (p != NULL) {
struct Node *prev = NULL;
while (p->link) {
struct Node *next = p->link;
p->link = prev;
prev = p;
p = next;
}
}
return p;
}
If your task requires recursion, you can make a extract the first node, reverse the remainder of the list and append the first node. Beware that this is not tail recursion, hence any sufficiently long list may cause a stack overflow.
struct Node *reve(struct Node *head) {
if (head != NULL && head->link != NULL) {
struct Node *first = head;
struct Node *second = head->link;
head = reve(second);
first->link = NULL; // unlink the first node
second->link = first; // append the first node
}
return head;
}
In C++ you need not to use keywords struct or class when an already declared structure or a class is used as a type specifier.
The function reve has undefined behavior.
First of all head can be equal to nullptr. In this case this statement
if (p->link == NULL) {
invokes undefined behavior.
Secondly the function returns nothing in the case when p->link is not equal to nullptr.
//...
reve(p->link);
struct Node *temp = p->link;
temp->link = p;
p->link = NULL;
}
Here is a demonstrative program that shows how the functions can be implemented. I used your C approach of including keyword struct when the structure is used as a type specifier.
#include <iostream>
struct Node
{
int data;
struct Node *link;
};
struct Node * insert( struct Node *head, int data )
{
return head = new Node{ data, head };
}
struct Node * reverse( struct Node *head )
{
if ( head && head->link )
{
struct Node *tail = head;
head = reverse( head->link );
tail->link->link = tail;
tail->link = nullptr;
}
return head;
}
std::ostream & display( struct Node *head, std::ostream &os = std::cout )
{
if ( head )
{
os << head->data;
if ( head->link )
{
os << '\t';
display( head->link, os );
}
}
return os;
}
int main()
{
struct Node *head = nullptr;
const int N = 10;
for ( int i = 0; i < N; i++ )
{
head = insert( head, i );
}
display( head ) << '\n';
head = reverse( head );
display( head ) << '\n';
return 0;
}
The program output is
9 8 7 6 5 4 3 2 1 0
0 1 2 3 4 5 6 7 8 9
display is fine.
First thing I have notices is that you are trying to modify a copied value. For example, line 16. This code has no effect.
Note that you have a bug on insert: You return head instead of new_node.
Your version fails for lists with more than 1 item. reve() is supposed to return the last node of the original list, which you do not, hence lastNode would not point to the last node of the reversed list. So my advice is that you keep it aside.
So, reve:
struct Node* reve(struct Node* head) {
if (head->link == NULL) {
return head;
}
struct Node* lastNode = reve(head->link);
lastNode->link = head;
head->link = NULL;
return head;
}
and main:
int main() {
Node* head = NULL;
Node* last_node = head = insert(head, 1);
head = insert(head, 2);
head = insert(head, 3);
head = insert(head, 4);
head = reve(head);
cout << "The linked list is: ";
// Now, last_node is the new head
display(last_node);
return 0;
}

Unable to create or return Reversed Linked list

Here using the function returnReverseLinkedList I am returning the reversed linked list of the given linked list. But the problem with this approach is that i lose the original linked list. So I make another fucntion called createReversedLinkedList to make a copy of the original linked list and reverse the copy and maintain possession of both.
unfortunately createReversedLinkedList is giving Runtime error.
obviously my end goal is to check if the given linked list is palindrome or not. This issue is just a stepping stone.
Could someone tell me why?
//Check if a linked list is a palindrome
#include <iostream>
using namespace std;
class node
{
public:
int data;
node *next;
node(int data)
{
this->data = data;
this->next = NULL;
}
};
node *returnReverseLinkedList(node *head)
{
// Will Lose original Linked List
if (head == NULL)
return NULL;
else if (head != NULL && head->next == NULL)
return head;
node *prev = NULL;
node *curr = head;
node *tempNext = head->next;
while (tempNext != NULL)
{
curr->next = prev;
prev = curr;
curr = tempNext;
tempNext = tempNext->next;
}
curr->next = prev;
return curr;
}
node *createReversedLinkedList(node *head)
{
if (head == NULL)
return NULL;
else if (head != NULL && head->next == NULL)
return NULL;
else
{
node *temp = head;
node *newHead = NULL;
node *newTail = NULL;
while (temp != NULL)
{
node *newNode = new node(temp->data);
if (newHead == NULL)
{
newHead = newNode;
newTail = newNode;
}
else
{
newTail->next = newNode;
newTail = newNode;
}
}
return returnReverseLinkedList(newHead);
}
}
bool check_palindrome(node *head)
{
node *original = head;
node *reverse = returnReverseLinkedList(head);
while (original->next != NULL || reverse->next != NULL)
{
if (original->data != reverse->data)
return false;
cout << "debug 2" << endl;
original = original->next;
reverse = reverse->next;
}
return true;
}
// #include "solution.h"
node *takeinput()
{
int data;
cin >> data;
node *head = NULL, *tail = NULL;
while (data != -1)
{
node *newnode = new node(data);
if (head == NULL)
{
head = newnode;
tail = newnode;
}
else
{
tail->next = newnode;
tail = newnode;
}
cin >> data;
}
return head;
}
void print(node *head)
{
node *temp = head;
while (temp != NULL)
{
cout << temp->data << " ";
temp = temp->next;
}
cout << endl;
}
int main()
{
node *head = takeinput();
node *revese2 = createReversedLinkedList(head);
print(revese2);
// bool ans = check_palindrome(head);
// if (ans)
// cout << "true";
// else
// cout << "false";
// return 0;
}
As asked by the OP, building a reversed linked is simply done by building as you would a stack (e.g LIFO) rather than duplicating the same original forward chain. For example:
node *createReversedLinkedList(const node *head)
{
node *newHead = NULL;
for (; head; head = head->next)
{
node *p = new node(head->data)
p->next = newHead;
newHead = p;
}
return newHead;
}
Note we're not hanging our copied nodes on the tail of the new list; they're hanging on the head of the new list, and becoming the new head with each addition. That's it. There is no need to craft an identical list, then reverse it; you can reverse it while building the copy to begin with.
A note on the remainder of your code. You have a dreadful memory leak, even if you fix the reversal generation as I've shown above. In your check_palindrome function, you never free the dynamic reversed copy (and in fact, you can't because you discard the original pointer referring to its head after the first traversal:
bool check_palindrome(node *head)
{
node *original = head;
node *reverse = returnReverseLinkedList(head); // only reference to reversed copy
while (original->next != NULL || reverse->next != NULL)
{
if (original->data != reverse->data)
return false; // completely leaked entire reversed copy
original = original->next;
reverse = reverse->next; // lost original list head
}
return true;
}
The most obvious method for combating that dreadful leak is to remember the original list and use a different pointer to iterate, and don't leave the function until the copy is freed.
bool check_palindrome(const node *head)
{
bool result = true;
node *reverse = returnReverseLinkedList(head);
for (node *p = reverse; p; p = p->next, head = head->next)
{
if (p->data != head->data)
{
result = false;
break;
}
}
while (reverse)
{
node *tmp = reverse;
reverse = reverse->next;
delete tmp;
}
return result;
}

How do I make my Linked List Print backwards in C++

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.

Moving first item in linked list to end C++

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