I was solving the Print in reverse challenge on Hackerrank
The void ReversePrint(Node* head) method takes one argument - the head of the linked list. You should NOT read
any input from stdin/console. The head may be empty so nothing should be printed. Print the elements of the linked list in reverse order to
stdout/console (using printf or cout) , one per line.
Sample Input
1 --> 2 --> NULL
2 --> 1 --> 4 --> 5 --> NULL
Sample Output
2
1
5
4
1
2
I solved it using this
#include <vector>
void ReversePrint(Node *head)
{
// This is a "method-only" submission.
// You only need to complete this method.
std::vector<int> nodeList;
if(head != NULL){
while(head != NULL){
nodeList.push_back(head->data);
head = head->next;
}
for (std::vector<int>::iterator it = nodeList.end()-1 ; it != nodeList.begin()-1; --it){
std::cout << *it <<endl;
}
}
}
It works perfectly but extending to use recursion provides the wrong answer, why is this happening?
std::vector<int> nodeList;
void ReversePrint(Node *head){
if(head != NULL){
nodeList.push_back(head->data);
ReversePrint(head->next);
}
else{
for (std::vector<int>::iterator it = nodeList.end()-1 ; it != nodeList.begin()-1; --it){
std::cout << *it <<endl;
}
}
}
the result is
2
1
5
4
1
2
2
1
NB: The structure of the Node is given as
struct Node
{
int data;
struct Node *next;
}
Why so complicated?
/* Function to reverse print the linked list */
void ReversePrint(Node* head)
{
// Base case
if (head == NULL)
return;
// print the list after head node
ReversePrint(head->next);
// After everything else is printed, print head
std::cout << head->data << '\n';
}
In case, you want to return reversed linked list:
Node* List::reverseList()
{
if(head == NULL) return;
Node *prev = NULL, *current = NULL, *next = NULL;
current = head;
while(current != NULL){
next = current->next;
current->next = prev;
prev = current;
current = next;
}
return prev;
}
You can reverse the linked list recursively then print the linked list.
Node* reverse(Node* node)
{
if (node == NULL)
return NULL;
if (node->next == NULL)
{
head = node;
return node;
}
Node* temp= reverse(node->next);
temp->next = node;
node->next = NULL;
return node;
}
Related
I can't for the life of me figure this out I've spent days on this exercise but to no avail.
I'm trying to delete nodes with the value 0 from a singly liked list.
Let's say i have |1|3|0|4|0|5|0|0|. The outcome should be |1|3|4|5|
Here is all the code for reference
#include <iostream>
#include <fstream>
using namespace std;
struct node {
int data;
node* next;
};
node* head, *last;
int n;
void creating_list()
{
node* aux;
ifstream f("in.txt");
f >> n;
for(int i=0;i<n;i++)
{
if (head == NULL)
{
head = new node;
f >> head->data;
head->next = NULL;
last = head;
}
else
{
aux = new node;
f >> aux->data;
last->next = aux;
aux->next = NULL;
last = aux;
}
}
}
void displaying_list()
{
node* a;
a = head;
if (a == NULL)
cout << "List is empty! ";
else
{
cout << "Elements of list are: | ";
while (a)
{
cout << a->data<<" | ";
a = a->next;
}
}
}
void delete_first_node()
{
if (head == NULL)
cout << "List is empty";
else
{
cout << "Deleting first node\n";
node* aux;
aux = head;
head = head->next;
delete aux;
}
}
void delete_last_node()
{
if (head == NULL)
cout << "List is empty";
else
{
if (head == last)
{
delete head;
head = last = NULL;
}
else
{
node* current;
current = head;
while (current->next != last)
current = current->next;
delete current->next;
current->next = NULL;
last = current;
}
}
}
void delete_value_0()
{
node* aux;
if (head == NULL)
cout << "List is empty. Can't delete! ";
else
// if (head->data == 0)
// delete_first_node();
// if (last->data == 0)
// delete_last_node();
// else
{
node* a;
a = head;
while (a)
if (a->next->data != 0)
{
a = a->next;
cout << a->data<<" | ";
}
else
if (a->next != last)
{
aux = a->next;
a->next = a->next->next;
delete aux;
break;
}
}
}
int main()
{
creating_list();
displaying_list(); cout <<endl;
delete_value_0();
return 0;
}
Here is the problem that gives me metal problems
I've tried to move one node short of the node that has the 0 value, store the value in another node, aux in this case and delete aux;
I've put comment on those lines because if I don't and the condition it's met it doesn't execute the rest of the code...
If I put break at the end it only shows me the first few numbers until the 0 and then stops short, doesn't move through the full list.
if I don't put break the the program is doesn't stop, it's in an infinite loop, it doesn't exit with code 0
void delete_value_0()
{
node* aux;
if (head == NULL)
cout << "List is empty. Can't delete! ";
else
// if (head->data == 0)
// delete_first_node();
// if (last->data == 0)
// delete_last_node();
// else
{
node* a;
a = head;
while (a)
if (a->next->data != 0)
{
a = a->next;
cout << a->data<<" | ";
}
else
if (a->next != last)
{
aux = a->next;
a->next = a->next->next;
delete aux;
break;
}
}
}
Honestly I'm at a loss I've spent so much time trying to figure this out, and this should be a very simple exercise. I feel like the answear Is really simple but i don't know what to do anymore, Maybe this is not for me.
This is much simpler than it appears on the first glance. The trick to this task is instead of using a pointer to the current node, a pointer to the pointer to the current node gets used instead. The entire task becomes laughably trivial: only one loop, and one if statement that takes care of all possibilities: the list is empty; the node to delete is the first node in the list; ot the last node in the list; or anywhere in the middle of it.
void delete_value_0()
{
node **p= &head;
while (*p)
{
if ((*p)->data == 0)
{
node *nextptr=*p;
*p=(*p)->next;
delete nextptr;
}
else
{
p= &(*p)->next;
}
}
}
The naive solution is something like this:
void delete_value_0()
{
while (head && head->data == 0)
delete_first_node();
if (head == nullptr)
return;
node *cur = head->next;
node *pre = head;
while (cur)
{
if (cur->data == 0)
{
pre->next = cur->next;
delete cur;
cur = pre->next;
}
else
{
pre = cur;
cur = cur->next;
}
}
}
The key point is that you need to have a pointer to both the element you are inspecting and to the previous element in the list. This allows you to pull the current element out if it has data == 0.
The issue with this is that you have to treat the first element special (since it has no previous element).
My suggestion is to study this solution until you understand how it works, then move on to the (much better) solution by #Sam Varshavchik and study that - it does basically the same, but uses a pointer to pointer in a clever way to make the special cases here irrelevant.
I've put comment on those lines because if I don't and the condition it's met it doesn't execute the rest of the code...
OK why there the sketchy iteration is in else for if (last->data == 0)? Your input seems to have 0 as last item so in this case it would never be triggered. Also, if you want to have first/last items as special case, instead of
if (head->data == 0)
delete_first_node();
you would want something like
while (head && head->data == 0)
delete_first_node();
That being said, the real WTF is treating first/last item specially instead of using just single iteration. Also, you don't really check whether the pointers are non-null before trying to access the contents. With C (or C++ in the case you try it at some point) you need to take care with memory access when dealing with pointers.
Some random pieces of help:
You need to break from last item when it's 0 to exit loop simply because you don't assign a to the next item in this case.
If this is your schoolwork this might not be your fault, reading amount of items from the input file (assuming it was given part of the assignment) before actual items is huge WTF as you're reading into a linked list. There is no need to loop for any n items when you can be simply reading a line of input at the time until the file runs out.
Arguments and return values. You should learn those.
#include <iostream>
struct Node {
int data;
Node* next;
};
// Function to delete nodes with the value 0 in a singly linked list
void deleteNodes(Node** head) {
// Edge case: empty list
if (*head == nullptr) {
return;
}
// Delete all nodes with the value 0 at the beginning of the list
while (*head != nullptr && (*head)->data == 0) {
Node* temp = *head;
*head = (*head)->next;
delete temp;
}
// Edge case: list with only one node
if (*head == nullptr) {
return;
}
// Delete nodes with the value 0 in the rest of the list
Node* current = *head;
while (current->next != nullptr) {
if (current->next->data == 0) {
Node* temp = current->next;
current->next = temp->next;
delete temp;
} else {
current = current->next;
}
}
}
int main() {
// Create a singly linked list: 1 -> 0 -> 2 -> 0 -> 3 -> 0 -> 4
Node* head = new Node{1, new Node{0, new Node{2, new Node{0, new Node{3, new Node{0, new Node{4, nullptr}}}}}};
// Delete nodes with the value 0
deleteNodes(&head);
// Print the resulting list: 1 -> 2 -> 3 -> 4
Node* current = head;
while (current != nullptr) {
std::cout << current->data << " ";
current = current->next;
}
std::cout << std::endl;
return 0;
}
hope it help
I'm working on a linked list program that takes an input for the data of each node like:
Sample Input:
2 18 24 3 5 7 9 6 12
Then it takes each group of even numbers like "2, 18, and 24" and reverses it to be "24, 18, and 2."
It seems to work on a larger scale according to these unit tests, but this particular one outputs:
2 3 5 7 9 12 6
Instead of:
24 18 2 3 5 7 9 12 6
So it just seems to delete the 24 and the 18 and I'm not sure why. Thanks in advance.
Here's my code:
#include <iostream>
using namespace std;
struct node {
int data;
node *next;
node *prev;
node *curr;
};
class linked_list {
private:
node *head,*tail;
public:
linked_list() {
head = NULL;
tail = NULL;
}
void add_node(int n) {
node *tmp = new node;
tmp->data = n;
tmp->next = NULL;
if(head == NULL) {
head = tmp;
tail = tmp;
}
else {
tail->next = tmp;
tmp->prev = tail;
tail = tail->next;
}
}
node* getHead() {
return head;
}
void print_List() {
node *tmp;
tmp = head;
while (tmp != NULL) {
cout << tmp->data << " ";
tmp = tmp->next;
}
}
node* reverse_Groups(node* head, node* prev) {
if (head == NULL) {
return NULL;
}
node *tmp;
node *curr;
curr = head;
while (curr != NULL && curr->data % 2 == 0) {
tmp = curr-> next;
curr->next = prev;
prev = curr;
curr = tmp;
}
if (curr != head) {
head->next = curr;
curr = reverse_Groups(curr, NULL);
return prev;
}
else {
head->next = reverse_Groups(head->next, head);
return head;
}
}
};
int main() {
linked_list a;
int numNodes, i, tempNode;
cin >> numNodes;
for (i = 0; i < numNodes; ++i) {
cin >> tempNode;
a.add_node(tempNode);
}
//a.print_List();
a.reverse_Groups(a.getHead(), NULL);
a.print_List();
return 0;
}
So I figured out it was a minor oversight on my end.
The code within reverse_Groups returns head when it's done. I was printing the list from the temp variable rather than the head, so it wasn't printing the first two numbers. Once I figured this out, I added a getHead function that returns the correct head after the reverse function finishes.
I just changed the print function to have a head parameter and supply the correct head using the getHead function so that it prints from the right starting point.
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;
}
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!
I tried hard to solve this problem but only managed to partially solve it.
My problem in this method is that I need to add an element after another element:
Example: add 5 1
5 is an element in the linked list but I want to add 1 after 5.
Example: let linked list contains these elements : 2 3 7
I call method to add 1 after 3, add 3 1, so the result assume to be 2 3 1 7, but with my method the result is 2 1 3 7, which is my problem.
Second problem is that I can't deal with the first element:
Example: add 2 1
It acts as if the first element does not exist:
void addNodeAtPos(link *head, int pos,int addelement)
{
link prev=NULL;
link curr =*head;
link newNode = (link)malloc(sizeof(node));
newNode->data = addelement;
while(curr->next != NULL )
{
prev = curr;
curr = curr->next;
if(curr->data == pos)
{
newNode->next = curr;
prev->next = newNode;
break;
}
}
}
My problem here is that I can't remove the first element:
void deletenode(link *head,int s){
bool found = false;
node *curr = *head, *prev=NULL;
while(curr != NULL){
// match found, delete
if(curr->data == s){
found = true;
// found at top
if(prev == NULL){
link temp = *head;
curr->next= prev;
delete(temp);
// found in list - not top
}else{
prev->next = curr->next;
delete(curr);
} }
// not found, advance pointers
if(!found){
prev = curr;
curr = curr->next; }
// found, exit loop
else curr = NULL; }
}
Here's the solution to the first problem
if(curr->data == pos)
{
// tempNode = curr->next;
// improvement as suggested by #Rerito
newNode->next = curr->next;
curr->next = newNode;
break;
}
It appears you are using non-circular doubly linked lists. Thus, both ends of the list are marked with NULL. Now, it seems to me that you use C++ in a very C-esque fashion ... (NULL would'nt be used in C++, there is the nullptr keyword).
I will deal with your issues assuming you are using C instead of C++.
// Note that I pass a link **ptr, NOT a link *ptr ...
void addNodeAtPos(link **head, int pos, int addelement) {
// I am assuming head will be a valid pointer, if not, please add the appropriate checks.
link *newNode = NULL, *cur = *head;
if (NULL == (newNode = malloc(sizeof(link)))
return;
newNode->data = addelement;
while (cur != NULL) {
if (cur->data == pos || NULL == cur->next) {
newNode->next = cur->next;
newNode->prev = cur; // remove this line if there is no prev pointer.
cur->next = newNode;
if (NULL != newNode->next) { // remove this if clause if there is no prev pointer
newNode->next->prev = newNode;
}
break;
}
cur = cur->next;
}
}
You did not specify what you should do if the "position" is not found, I assumed that you just add the element at the end of the list in that case.
Now, considering your issue removing the first element :
void deleteNode(link **head, int el)
{
// I assume you wont pass a `NULL` ptr as #head
link *cur = *head, *prev = NULL;
while (cur != NULL) {
if (cur->data == el) {
next = cur->next;
prev = cur->prev;
free(cur);
if (NULL != next)
next->prev = prev;
if (NULL != prev)
prev->next = next;
else
*head = next;
break;
}
cur = cur->next;
}
}
Why do you need to pass a link **head instead of a link *head ? Because when you are removing the head of the list, you must make sure it won't be accessed anymore and thus you need to update the head pointer you use elsewhere. This is what is made in the *head = next; statement in the above function.
If you are using singly linked list (only a pointer to the next element, not the previous), the solution becomes the following :
void deleteNode(link **head, int el)
{
// I assume you wont pass a `NULL` ptr as #head
link *cur = *head, *prev = NULL, *next = NULL;
while (cur != NULL) {
if (cur->data == el) {
if (NULL != prev)
prev->next = cur->next;
else
*head = cur->next;
free(cur);
break;
}
prev = cur;
cur = cur->next;
}
}