Why the cout will change the list address? - c++

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.

Related

create linked list with for loop...why we should use l->next.....why we can just use l=t only to assigne the previous address of the node?

#include<iostream>
using std::cout;
struct node
{
int data;
node* next;
};
void Display(node* p)
{
while (p != NULL)
{
printf("%d ", p->data);
p = p->next;
}
}
int main()
{
node* t = new node{ 0 }, * head = t;
node* l = t;
for (size_t i = 1; i <= 5; i++)
{
t = new node;
t->data = i;
t->next = NULL;
l->next = t;
l = t;
}
Display(head);
return 0;
}
why we should use l->next=t ......is this a right way to fill a linked list throw a for loop or even copy items from an array or any source of data;
If you will write
l = t;
instead of
l->next = t;
l = t;
then the list will be broken because the data member next of the node pointed to by the pointer l will not point to the new node pointed to by the pointer t and will have the value NULL.
As a result you will have six separate nodes the data member next of which will be equal to NULL. So you will not have a linked list.

Destructor for circular linked list in c++?

when the destructor of 'class LL' ~LL() gets called for this circular singly linked-list, the program crashes instead of freeing up the heap space of the pointer. How can I solve this problem?
class Node {
public:
int data;
Node *next;
};
class LL {
private:
Node *head, *tail;
public:
LL() {
head = NULL;
tail = NULL;
}
// destructor
~LL() {
Node *p = head;
while (p->next != head) {
p = p->next;
}
while (p != head) {
p->next = head->next;
delete head;
head = p->next;
}
if (p == head) {
delete head;
head = nullptr;
}
}
// circular singly Linked list
void createLL() {
int n, x;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> x;
Node *t = new Node;
t->data = x;
t->next = NULL;
if (head == NULL) {
head = tail = t;
} else {
tail->next = t;
tail = t;
}
}
tail->next = head;
}
There are a few issues with the linked list.
The linked list's destructor assumes that head isn't null, when there is a possibility that it could be. Make sure to check that head isn't null before trying to clean up memory. Once that is done, it looks like your original destructor should work.
The function createLL will invoke undefined behavior if the user enters a size less than or equal to 0.
Specifically this line tail->next = head;
TreateLL is a misnomer as it doesn't actually 'create' a new list in the expected sense. The contents aren't cleared, and thus n elements are appended to the end of the current list.
Also, a circularly linked list can be created with just a single tail pointer.
However, getting your implementation of a circular linked list to work looks like this
#include <iostream>
using namespace std;
class Node {
public:
int data;
Node* next;
};
class LL {
private:
Node* head, * tail;
public:
LL() : head(nullptr),
tail(nullptr) {
}
~LL() {
if (head) {
Node* p = tail;
while (p != head) {
p->next = head->next;
delete head;
head = p->next;
}
if (p == head) {
delete head;
head = nullptr;
}
}
}
void storeUserInput() {
int n, x;
cin >> n;
if (n <= 0) {
return; //no input to retrieve.
}
for (int i = 0; i < n; i++) {
cin >> x;
Node* t = new Node;
t->data = x;
t->next = nullptr;
if (head == nullptr) {
head = tail = t;
}
else {
tail->next = t;
tail = t;
}
}
tail->next = head;
}
};
int main() {
LL l;
l.storeUserInput();
char response;
std::cin >> response;
}
It seems that you have access C++ 11 or above compiler, if so then you should be using nullptr in place of NULL as it is a definitive pointer type. See more here
You can do it in two steps:
Make the list non-circular. This has two sub-steps:
Detect the loop. There are published algorithms to do this. Edit: Your list has a tail pointer, so there is no need to search for it in your case.
Point the back referencing node to null (or sentinel)
Delete the list which is now non-circular in a loop. This is trivial.
While trying to delete in a loop your circular reference will lead to deleted memory and will have undefined behavior. So first consider breaking the circulatiry:
tail->next = 0;
Then delete in a loop
Node* p = head;
while(p)
{
Node* temp = p;
p = p->next;
delete temp;
}
By the way. tail->next will always point to the head. So you always will have both, the head and the tail in the same pointer. So you can clean the memory like this:
Node* p = tail->next; //this is head
tail->next = 0;
while(p)
{
Node* temp = p;
p = p->next;
delete temp;
}

My program stops working from a while loop when using dynamic allocated lists

I've been studying about dynamic allocated lists (the stuff we are discussing right now in class is pretty outdated tbh) and I can't seem to access the next node in a list. (I've just began learning this topic)
The problem is that the while loop that I'm using for going through the list never stops. I'm definitely missing something and I don't understand what.
struct node {
int info;
node* next;
};
int main()
{
node *p, *prim=NULL;
p = prim;
node* t;
t = new node;
p->next = t;
while (p != NULL)
{
cout << "test";
p = p -> next;
}
return 0;
}
Here is the code.
Why does my program not output anything and also tells me "it exited with code -1073741819" instead of 0?
Thanks.
////edit: I forgot to tell you that I've tried this way too
struct node {
int info;
node* next;
};
int main()
{
node *p, *prim=NULL;
p = prim;
node* t;
t = new node;
prim->next = t;
while (p != NULL)
{
cout << "test";
p = p -> next;
}
return 0;
}
Let's analyze your code:
node *p, *prim=NULL; // prim is NULL, p not yet initnialized
p = prim; // p now equal to NULL as well
node* t;
t = new node; // t is allocated
p->next = t; // NULL->next = t
So you're crashing on a null pointer when you try to dereference p->next for assignment.
It looks like you're trying to setup a basic linked list and loop through it. Your loop looks good, but you forgot the part where you actually setup the list!
That could look like:
struct node {
int info;
node* next;
//Add a quick constructor to make creating new nodes easy
node(int i) : info(i), next(nullptr) { }
};
int main()
{
//Start out with 3 itmes
// This list will look like:
// head -> 5 -> 3 -> 1
node *head = new node(5);
head->next = new node(3);
head->next->next = new node(1);
//Loop through the list and print each value
for(node *p = head; p; p = p->next) {
std::cout << p->info << std::endl;
}
//Don't forget to delete the memory you allocated to prevent a leak!
for(node *p = head; p;) {
node *temp = p->next;
delete p;
p = temp;
}
return 0;
}
See it run: https://ideone.com/WngD3b

recursively reverse a linked list without a global variable

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

c++ linked list segfault debug

I am met a segfault during implementing my own linked_list in C++. I spent hours on it but still cannot figure out the bug. Any help will be appreciated. Thank you in advance.
I think the error is in find_kth1() function, but I don't know what i do wrong. I can print the linked list just as expected.
/*
*
* find kth to last element in a singly linked list
*/
#include <iostream>
// #include "../linked_list.h"
using namespace std;
struct Node {
int data ;
struct Node *next;
};
Node* push(Node *head, int d){
// push to top
Node *n = new Node;
n->data = d;
n->next = head;
return n;
}
void print_LL( Node* head){
Node* p = head;
while(p) {
cout << p->data << ' ';
p = p->next;
}
}
int find_length( Node* head) {
int len = 0;
Node* p = head;
while(p){
len ++;
p = p->next;
}
return len;
}
Node* find_kth1( Node* head, int k){
// find length, scan twice
int len = find_length(head);
Node *p = head;
int i = 0;
while( i < len-k){
i ++ ;
p = p->next;
}
return p;
}
int main( void){
Node *head;
head = push( head, 2) ;
head = push( head, 3) ;
head = push( head, 4) ;
head = push( head, 5) ;
head = push( head, 2) ;
print_LL( head);
int k = 3;
Node *p = find_kth1( head, k);
// cout<<p->data<<endl;
}
The head pointer need to be initialized
It is used with out initialization
Normally compiler gives warning , so always heed to the warnings
Node *head=NULL;