recursively reverse a linked list without a global variable - c++

I wonder why passing the second parameter Node** fhead causes a segfault? Node has an int value and a next pointer pointing to the next Node.
Here is my code:
void reverse(Node* head, Node** fhead) {
if (!head->next)
{
fhead = &head;
return;
}
reverse(head->next, fhead);
head->next->next = head;
head->next = 0;
}
int main()
{
Node a = {1, 0};
Node b = {2, &a};
Node c = {3, &b};
Node** fhead;
reverse(&c, fhead);
}

You have a little mistake in the recurssion termination. You should set *fhead to head and not assigning it with &head (Which will just change fhead locally in the funciton):
if (!head->next)
{
*fhead = head;
return;
}

There are two very small but serious problems.
First,
fhead = &head;
assigns a value to the parameter, so that change will not be visible outside of the function.
This works exactly like
void f(int x)
{
x = 0;
}
Just like you would do when you pass e.g. a pointer to an int,
void f(int* x)
{
*x = 0;
}
you need to assign to the object that the pointer points to:
*fhead = head;
Second, you need to pass a valid pointer to a variable:
Node* fhead = 0;
reverse(&c, &fhead);
(The initialisation isn't strictly necessary, but it's a good idea to initialise variables.)
With those two changes, your code works as expected.

public ListNode reverseList(ListNode head) {
if (head == null || head.next == null)
return head;
ListNode p = reverseList(head.next);
head.next.next = head;
head.next = null;
return p;
}
One can assume ListNode definition
class ListNode{
int val;
ListNode next;
public ListNode(int val){
this.val = val;
this.next = null;
}
}

Related

insertion at the end of linked list function not working

I don't know where I am wrong, when I debugged the code I found out that the 'new node' address is 'new node' address, basically the new node is referring to itself
void insertend(struct node *parent, int item)
{
while (parent->addr != NULL)
parent = parent->addr;
struct node new_node;
new_node.a = item;
parent->addr = &new_node;
parent->addr->addr = NULL;
}
void insertend(struct node *parent, int item)
{
while (parent->addr != NULL)
parent = parent->addr;
struct node new_node;
new_node.a = item;
parent->addr = &new_node;
parent->addr->addr = NULL;
}
The lifetime of new_node is limited to the function. Once that function returns, it is no longer valid.
In order to circumvent this, it is necessary to dynamically allocate memory for new_node. Of course, as already pointed out, this means explicitly deallocating the memory eventually.
Note: as this is C++ rather than C, we do not need to add struct to the front of the type in use, and NULL is better spelled nullptr.
void insertend(node *parent, int item)
{
while (parent->addr != nullptr)
parent = parent->addr;
node *new_node = new node;
new_node.a = item;
parent->addr = new_node;
parent->addr->addr = nullptr;
}
As C++ structs are just classes with default public access, it's also worth noting we could implement this as a member function. Something like:
template <typename T>
struct Node {
T value;
Node<T> *next;
void append(T val) {
Node<T> * temp = this;
while (temp->next != nullptr) {
temp = temp->next;
}
temp->next = new Node<T>;
temp->next->value = val;
temp->next->next = nullptr;
}
};
int main() {
auto n = Node<int>();
n.value = 27;
n.append(42);
n.append(34);
for (Node<int> *t = &n; t != nullptr; t = t->next) {
std::cout << t->value << std::endl;
}
return 0;
}
The next step would be implementing a constructor and destructor.
One more thing to keep in mind is that getting to the end of a list this way is O(n) time complexity. Doing it over and over again is costly. If you have Node::append return a pointer to the new Node, then you can call append on that.
template <typename T>
struct Node {
T value;
Node<T> *next;
Node<T> *append(T val) {
Node<T> * temp = this;
while (temp->next != nullptr) {
temp = temp->next;
}
temp->next = new Node<T>;
temp->next->value = val;
temp->next->next = nullptr;
return temp->next;
}
};
int main() {
auto n = Node<int>();
n.value = 27;
auto n2 = n.append(42);
n2 = n2->append(34);
n2 = n2->append(15);
for (Node<int> *t = &n; t != nullptr; t = t->next) {
std::cout << t->value << std::endl;
}
return 0;
}
I’m not sure what the addr refers to, but I would assume it points to the next node in the linked list. In your code, there needs to be another node to use as a temporary node, because the parent node keeps being reassigned, and the previous items are lost. We also need to check that the parent node is not NULL.
void insertend(struct node **parent, int item)
{
node *new_node = new node;
new_node->a = item;
new_node->addr = NULL;
if(*parent == NULL)
{
*parent = new_node;
}
else
{
node *temp = *parent;
while (temp->addr != NULL)
temp = temp->addr;
temp->addr = new_node;
}
}
The if statement checks whether the parent node is NULL. If true, then we assign parent node to new_node. If false, then we go to the end of the list and assign the next node in the list to new_node.
As Igor correctly pointed out, your new node gets destroyed when the function finishes. So, in this context you could just allocate memory. You can use the new operator for this. However, you would need to explicitly free the memory, eventually.
void insertend(struct node *parent, int item)
{
while (parent->addr != NULL)
parent = parent->addr;
struct * new_node = new node;
new_node->a = item;
parent->addr = new_node;
parent->addr->addr = NULL;
}

C++ Linked List HEAD keeps resetting to NULL

I need help in understanding why my Linked List approach doesn't work as expected.
#include <iostream>
using namespace std;
class Node {
public:
int Data;
Node* Next;
Node(int data) {
Data = data;
Next = NULL;
}
};
void insertNodeAtEnd(Node* HEAD, int data) {
Node* it = HEAD;
if (HEAD == NULL) { HEAD = new Node(data); }
else {
while (it->Next != NULL) { it = it -> Next; }
it -> Next = new Node(data);
}
}
void printLinkedList(Node* HEAD) {
Node* it = HEAD;
while (it != NULL) {
cout << it->Data << endl;
it = it -> Next;
}
}
int main() {
Node* HEAD = NULL;
// Node* HEAD = new Node(0);
insertNodeAtEnd(HEAD, 5);
insertNodeAtEnd(HEAD, 2);
insertNodeAtEnd(HEAD, 10);
printLinkedList(HEAD);
return 0;
}
The above main() function does NOT work (ie: no output, and the HEAD keeps resetting to NULL as soon as the control leaves insertNodeAtEnd()), and I've found similar questions here on SO which explain that this is because the pointer is being passed by value, and that makes partial sense to me.
Why does it work as expected when I replace Node* HEAD = NULL; with Node* HEAD = new Node(0); in the main() function, if the pointer is being passed as value?
How are nodes getting added if I initialise HEAD like Node* HEAD = new Node(0);, but not in the case where HEAD = NULL initially? I was able to get it to work properly by using pointer to pointer but I can't understand why this approach doesn't work. I am sorry if I haven't explained my question properly, please let me know if any clarification is required.
The underlying issue can be reduced to this code:
void insertNodeAtEnd(Node* HEAD, int data) {
//...
if (HEAD == NULL) { HEAD = new Node(data); }
//...
}
int main() {
Node* HEAD = NULL;
insertNodeAtEnd(HEAD, 5);
//...
You seem to assume that assigning to HEAD inside insertNodeAtEnd would change the HEAD variable inside of main. This is not true. Your pointer is passed by value, so the address is copied for the function. Changing this copied variable will not change the value of HEAD inside of main.
To fix this you could pass a pointer to a pointer instead, like this:
void insertNodeAtEnd(Node** HEAD, int data) {
//...
if (*HEAD == NULL) { *HEAD = new Node(data); }
//...
}
int main() {
Node* HEAD = NULL;
insertNodeAtEnd(&HEAD, 5);
//...
This pointer to a pointer is still passed by value, however the pointer that it points to will be the same as the on from main.
The problem come from your first insertion. You change the value of head which is reset when you quit the function. You can only change the value behind the pointer, not the pointer itself.
A solution for this would be to pass a pointer of pointer. Something like: (not tested)
void insertNodeAtEnd(Node** HEAD, int data) {
if (*HEAD == NULL) { *HEAD = new Node(data); }
else {
Node* it = *HEAD;
while (it->Next != NULL) { it = it -> Next; }
it -> Next = new Node(data);
}
}
int main() {
Node* HEAD = NULL;
// Node* HEAD = new Node(0);
insertNodeAtEnd(&HEAD, 5);
return 0;
}
As you don't change the pointer of pointer but only the value behind it (the actuual pointer to head) the change will be keep once you exit the function.
The answer has already been given by #Brotcrunsher. I am posting to help you implement a better solution, that separates the concept of a list and an element of a list, that incapsulates the methods used and that frees the resources it uses, when it goes out of scope:
#include <iostream>
using namespace std;
class Node {
public:
int Data;
Node* Next;
Node(int data = 0) {
Data = data;
Next = nullptr;
}
};
class List {
public:
Node* Head = nullptr;
void Insert(int data) {
if (Head == nullptr)
Head = new Node(data);
else {
Node* ptr;
for (ptr = Head; ptr->Next != nullptr; ptr = ptr->Next)
;
ptr->Next = new Node(data);
}
}
void Print() {
for (Node* ptr = Head; ptr != nullptr; ptr = ptr->Next)
cout << ptr->Data << endl;
}
~List() {
Node* ptr = Head;
while (ptr != nullptr) {
Node* tmp = ptr;
ptr = ptr->Next;
delete tmp;
}
}
};
int main() {
List list;
list.Insert(5);
list.Insert(2);
list.Insert(10);
list.Print();
return 0;
}

Why the cout will change the list address?

I want to generate the list and print the val by
#include<iostream>
#include<vector>
using namespace std;
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
struct ListNode{
int val;
ListNode *next;
ListNode(int x) :val(x), next(NULL){
}
};
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
}
};
ListNode* geneate_list(vector<int> data){
ListNode *p1, *p2;
if (data.size() <= 0){
p1 = (ListNode*)malloc(sizeof(ListNode));
return p1;
}
/*ListNode *p1, *p2;*/
ListNode head(data[0]);
p2 = &head;
for (int i = 1; i < data.size(); i++){
p1 = (ListNode*)malloc(sizeof(ListNode));
p1->val = data[i];
p1->next = NULL;
p2->next = p1;
p2 = p1;
}
return &head;
}
int main(){
vector<int> data = {1,2,3,4,5,6};
ListNode* head = geneate_list(data);
ListNode * g = head;
while (head!=NULL){
cout << head->val;
head = head->next;
}
return 0;
}
then I find ,when cout ,the head's address change totally.
before
after
So,anyone can explain this?thx
The generate_list function is wrong for several reasons:
You return the address of a local variable which yields in undefined behaviour. Google return the address of a local variable for more details.
If you pass an empty vector to generate_list, the content of the head of the newly generated list is not initialized. But anyway as the list is empty, you cannot have a head anyway. What would val contain? Therefore generate_list must return NULL for an empty vector.
You are using malloc for allocating an object with a constructor. The constructor of ListNode will therefore never be called (although this constructor is not very useful here).
You want something like this:
ListNode* geneate_list(vector<int> data) {
ListNode *head = NULL;
ListNode *previous = NULL;
for (int i = 0; i < data.size(); i++) {
ListNode *p = new ListNode(0);
if (i == 0)
head = p;
p->val = data[i];
p->next = NULL;
if (previous)
previous->next = p;
previous = p;
}
return head;
}
Disclaimer: this a more or less a C function as close as possible to the original function. In C++ you would do this differently.

How pointers are passed across void and non void recursive functions in C++

I have the following function to reverse a linked list:
Node* reverseUtil(Node *head, Node *prev) {
if (head->next == NULL) {
head->next = prev;
return head;
}
Node *next = head->next;
head->next = prev;
prev = head;
head = next;
return reverseUtil(head, prev);
}
When I call this with Node* head = reverseUtil(head, NULL); it works fine and ultimately returns the head of the reversed linked list. Example for 1->2->3, it returns head with 3->2->1.
However, when I modify it to the following, the resultant head pointer only has the last node of the reversed linked list (originally the starting point of the list. Example: for original list 1->2->3, head at the end only has 1.
void reverseUtil(Node *head, Node *prev) {
if (head->next == NULL) {
head->next = prev;
return;
}
Node *next = head->next;
head->next = prev;
prev = head;
head = next; //head pointer should update here on forward path. This seems to be happening.
reverseUtil(head, prev);//after this step returns, head should stick to the last updated point and should return unchanged but this does not happen.
}
I think I am missing something basic here. I would expect that the statement head = next at each call of the function would update the head pointer. It should ultimately point to the new beginning of the reversed linked list and should remain unchanged as the recursive calls return. However it seems to be continuously getting updated on the return path.
When you pass a pointer to a function like void foo(type* bar) the address that the pointer contains is passed by value. If you need to change that address then you need to pass it by reference like void foo(type *&bar). I think that you are confused by the fact that this works
void foo(int * bar) { *bar = 10; }
int man()
{
int x = 5;
foo(&x);
// x is now 10 here
}
Here we are not changing what the pointer points to but we are changing the value of the pointed to object. We can see that changing the address of the pointer has no affect when not passed by reference with:
void foo(int * bar)
{
int foobar = 10;
bar = &foobar;
}
int main()
{
int x = 5;
foo(&x);
std::cout << x;
}
Live Example

Linked list problem

I got some problem with the linked list I've written. I dunno if it's either my insert function that the problem, or if it's my traverse function that's not correct. I hope for some input. A side note, I'm initalising the list in main now since I don't know if my initNode function is correct.
#include <iostream>
using namespace std;
typedef struct Node
{
int data;
Node *next;
};
void initNode(Node *head)
{
head = new Node;
head->next = NULL;
}
void insertNode(Node *head, int x)
{
Node *temp;
temp = new Node;
temp->data = x;
temp->next = head;
head = temp;
}
void traverse(Node *head)
{
Node *temp;
temp = head;
if(head == NULL)
{
cout << "End of list. " << endl;
}
else
{
while(temp != NULL)
{
cout << temp->data << " ";
temp = temp->next;
}
}
}
int main()
{
Node *head;
head = NULL;
insertNode(head, 5);
insertNode(head, 5);
traverse(head);
return 0;
}
Your head isn't being returned to main from insertNode. Note that even though head is a pointer, the pointer itself is a value and any changes to the pointer value are not reflected in main. The simplest solution is to pass back the updated value of head:
Node *insertNode(Node *head, int x)
{
...
return head;
}
And update it in main:
head = insertNode(head, 5);
The other common way of doing this is to pass a pointer to a pointer and update it directly:
void insertNode(Node **head, int x)
{
Node *temp;
temp = new Node;
temp->data = x;
temp->next = *head;
*head = temp;
}
And call it like this:
insertNode(&head, 5);
The way you have you initNode function written will result in memory leaks. You've passed in a pointer, but you need to pass in a reference to a pointer. (Same issue that James and casablanca mentioned for insertNode.)