struct ll
{
int data;
ll *next;
};
void display(ll **head) {
ll *t = *head;
while(t){
cout<<t->data<<"-->";
t = t->next;
}
}
void add(ll **head, int d) {
ll *c = *head;
ll temp;
temp.data = d;
temp.next = NULL;
if(*head == NULL) {
*head = &temp;
} else {
while(c->next) {
c = c->next;
}
c->next = &temp;
}
}
int main() {
ll *head = NULL;
add(&head,1);
add(&head,2);
//add(&head,3);
//add(&head,4);
//add(&head,10);
//display(&head);
getchar();
}
why does using ll temp in add() not work. if i convert this to ll *temp= new ll; all w
Your Add() function creates a local ll struct.
Accessing it leads to undefined behavior.
You need to allocate your nodes at the heap section of the memory.
void add(ll **head, int d) {
ll *c = *head;
ll *temp = new ll;
temp->data = d;
temp->next = NULL;
if(*head == NULL) {
*head = temp;
} else {
while(c->next) {
c = c->next;
}
c->next = temp;
}
}
You created a local struct in your function which goes out of scope (all memory is released at the end of the function). However, as you pointed your node to it: *head = &temp;, it will cause undefined behaviour as it will point to destroyed memory at the end of the function (once temp has gone out of scope), which is unsafe to dereference.
However, if temp is allocated with new, it means that the temp's will not be destroyed until you call the delete keyword, allowing it to be safe to effectively point to a variable created in the function.
Try this:
struct ll
{
int data;
ll *next;
};
void display(ll** head)
{
ll* cur = *head;
while(cur != NULL){
cout<< cur->data << "-->";
cur = cur->next;
}
}
void add(ll** head, int d)
{
ll* cur = *head, *temp = new ll;
temp->data = d;
temp->next = NULL;
if(*head == NULL) {
*head = temp;
}
else {
while(cur->next != NULL) {
cur = cur->next;
}
c->next = temp;
}
}
void free_list(ll** head)
{
ll* cur = *head, *next = NULL;
while(cur != NULL){
next = cur->next;
delete cur;
cur = next;
}
}
int main()
{
ll *head = NULL;
add(&head,1);
add(&head,2);
display(&head);
free_list(&head);
getchar();
}
Related
I am really new to data structures. I am trying to figure out why my insertback() function doesn't work. The first print does 3,2,1 but the second doesn't print anything. I think it has something to do with head, but I'm not really sure. Please help.
#include <iostream>
using namespace std;
struct Node
{
int data;
Node* next;
};
class lst
{
public:
void Insertfron(int x);
void Print();
void Insertback(int x);
private:
Node* head;
};
void lst::Insertfron(int x)
{
Node* temp = new Node;
temp->data = x;
temp->next = head;
head = temp;
}
void lst::Print()
{
Node* temp = head;
while(temp->next!=NULL)
{
cout<<temp->data<<' ';
temp=temp->next;
}
cout<< endl;
}
void lst::Insertback(int x)
{
Node* backinst = new Node;
backinst->data = x;
backinst->next = NULL;
Node* temp = head;
while(temp->next!=NULL)
{
temp = temp->next;
}
temp->next = backinst;
}
int main()
{
lst listt;
listt.Insertfron(1);
listt.Insertfron(2);
listt.Insertfron(3);
listt.Print();
listt.Insertback(4);
listt.Print();
return 0;
}
You are not initializing head to NULL to indicate an empty list, so ``head` will have a random garbage value, and thus all of your methods exhibit undefined behavior.
Once that is fixed, your while loops in both Print() and Insertback() are buggy, as they are not account for head being NULL when the list is empty.
Also, you are leaking every node you create. You need to add a destructor to free the nodes when you are done using the list.
With that said, try something more like this instead:
#include <iostream>
using namespace std;
struct Node
{
int data;
Node* next;
};
class lst
{
public:
lst();
~lst();
void Insertfron(int x);
void Print();
void Insertback(int x);
private:
Node* head;
};
lst::lst()
: head(NULL)
{
}
lst::~lst()
{
while (head != NULL)
{
Node *next = head->next;
delete head;
head = next;
}
}
void lst::Insertfron(int x)
{
Node* temp = new Node;
temp->data = x;
temp->next = head;
head = temp;
}
void lst::Print()
{
Node* temp = head;
while (temp != NULL)
{
cout << temp->data << ' ';
temp = temp->next;
}
cout << endl;
}
void lst::Insertback(int x)
{
Node* backinst = new Node;
backinst->data = x;
backinst->next = NULL;
if (head == NULL)
{
head = backinst;
}
else
{
Node* temp = head;
while (temp->next != NULL)
{
temp = temp->next;
}
temp->next = backinst;
}
}
int main()
{
lst listt;
listt.Insertfron(1);
listt.Insertfron(2);
listt.Insertfron(3);
listt.Print();
listt.Insertback(4);
listt.Print();
return 0;
}
That being said, Insertback() can be simplified to avoid the extra if by using an extra level of pointer indirection:
void lst::Insertback(int x)
{
Node **temp = &head;
while (*temp != NULL)
{
temp = &((*temp)->next);
}
Node* backinst = new Node;
backinst->data = x;
backinst->next = NULL;
*temp = backinst;
}
I have a linked list in C++, after inserting several nodes now I see that all of them are the same, although I'm using different values to add to node each time, but it's like all of them are the same, even when trying to change a node all of them are changing together or it's the same node that is always being returned, I don't know.
class node
{
public:
int ochance = 3;
string question;
string option1;
int peopleeffectop1;
int courteffectop1;
int treasuryeffectop1;
string option2;
int peopleeffectop2;
int courteffectop2;
int treasuryeffectop2;
node *next;
};
class list
{
private:
node *head, *tail;
public:
list()
{
head=NULL;
tail=NULL;
}
void createnode(int value , string q , string ans1 , int ans1ef1 , int ans1ef2, int ans1ef3 , string ans2, int ans2ef1 , int ans2ef2, int ans2ef3 )
{
node *temp = new node;
temp->ochance = value;
temp->question = q;
temp->option1 = ans1;
temp->peopleeffectop1 = ans1ef1;
temp->courteffectop1 = ans1ef2;
temp->treasuryeffectop1 = ans1ef3;
temp->option2 = ans2;
temp->peopleeffectop2 = ans2ef1;
temp->courteffectop2 = ans2ef2;
temp->treasuryeffectop2 = ans2ef3;
temp->next = NULL;
if(head == NULL)
{
head = temp;
tail = temp;
temp = NULL;
}
else
{
tail->next = temp;
tail = temp;
}
}
node getnth(int pos)
{
node* tmp = new node;
tmp = head;
int i = 0;
while(tmp!=NULL)
{
if (i=pos)
{
return *tmp;
}
i++;
tmp = tmp->next;
}
}
int getlen()
{
node* tmp = new node;
tmp = head;
int i = 0;
while(tmp!=NULL)
{
i++;
tmp = tmp->next;
}
return i;
}
void minus(int pos)
{
node* tmp = new node;
tmp = head;
int i = 0;
while(tmp!=NULL)
{
if (i=pos)
{
tmp->ochance -=1;
}
i++;
tmp = tmp->next;
}
}
void delete_first()
{
node *temp = new node;
temp = head;
head = head->next;
delete temp;
}
void delete_last()
{
node *current = new node;
node *previous = new node;
current = head;
while(current->next != NULL)
{
previous = current;
current = current->next;
}
tail = previous;
previous->next = NULL;
delete current;
}
void delete_position(int pos)
{
node *current = new node;
node *previous = new node;
current = head;
for(int i = 1; i < pos; i++)
{
previous = current;
current = current->next;
}
previous->next = current->next;
}
};
For starters many member functions has a memory leak as for example in this function
node getnth(int pos)
{
node* tmp = new node;
tmp= head;
//
At first memory was allocated and its address was stored in the pointer tmp and then the pointer is reassigned. As a result the address of the allocated memory is lost and the memory is not deleted.
These statements
node* tmp = new node;
tmp= head;
must be substituted for this one statement
node* tmp = head;
Moreover this function
node getnth(int pos)
{
node* tmp = new node;
tmp= head;
int i =0 ;
while(tmp!=NULL){
if (i=pos) {
return *tmp;
}
i++;
tmp = tmp->next;
}
}
has undefined behavior in case when pos is higher than there are nodes in the list. In this case the function returns nothing.
In the function minus there is used the assignment operator instead of the comparison operator
while(tmp!=NULL){
if (i=pos) {
^^^^^
In this function
void delete_first()
{
node *temp=new node;
temp=head;
head=head->next;
delete temp;
}
there is no check whether head is equal to NULL and tail is not adjusted if it is point to the first node.
The same problems are also in the function delete_last only that instead of the adjacent of the tail node as in the previous function you have to adjust the head node.
This function delete_position has the same drawbacks as the previous functions but also it has a bug in the loop
for(int i=1;i<pos;i++)
A node at position 1 will never be deleted.
#include <iostream>
using namespace std;
class List {
public:
struct node {
int data;
node *next;
};
node* head = NULL;
node* tail = NULL;
node* temp = NULL;
node* prev = NULL;
public:
void addNum(int num) {
temp = new node;
temp->data = num;
temp->next = NULL;
if (head == NULL) {
head = temp;
tail = temp;
}
else {
tail->next = temp;
tail = temp;
}
}
void PrintList() {
temp = head;
while (temp != NULL) {
cout << temp->data << endl;
temp = temp->next;
}
}
void DelNum(int num) {
temp = head;
while (temp != NULL) {
if (temp->data == num) {
prev->next = temp->next;
free(temp);
}
temp = prev;
temp = temp->next;
}
}
};
int main() {
List list;
list.addNum(1);
list.addNum(2);
list.addNum(3);
list.addNum(4);
list.addNum(5);
list.addNum(6);
list.DelNum(3);
list.PrintList();
return 0;
}
What is wrong with my DelNum function? When I run the program nothing pops up. Doesn't matter what number I put in.
As mss pointed out the problem is in your DelNum() function where you assign temp = prev;. In your initialization you defined that node* prev = NULL; So, prev = NULL at the point when you assigned it to temp which caused segmentation fault when you try to use it like temp = temp->next;.
Two main problems are there in DelNum function:
first, when you are in while loop
, you should assign
prev = temp;
second, when you have found your target element, after deleting it you have to break out of the loop, which isn't done in your code
below is your corrected code( also correction of some other corner case in DelNum function ):
#include <iostream>
using namespace std;
class List {
public:
struct node {
int data;
node *next;
};
node* head = NULL;
node* tail = NULL;
node* temp = NULL;
node* prev = NULL;
public:
void addNum(int num) {
temp = new node;
temp->data = num;
temp->next = NULL;
if (head == NULL) {
head = temp;
tail = temp;
}
else {
tail->next = temp;
tail = temp;
}
cout<<num<<" is added \n";
}
void PrintList() {
temp = head;
while (temp != NULL) {
cout << temp->data << endl;
temp = temp->next;
}
}
void DelNum(int num) {
if(head==NULL)//empty
{
cout<<"empty linked list, can't be deleted\n";
return;
}
if(head->next==NULL)//means only one element is left
{
if(head->data==num)
{
node * fordelete=head;
head=NULL;
cout<<num<<"is deleted\n";
delete(fordelete);
}
else
{
cout<<"not found , can't be deleted\n";
}
return;
}
temp = head; // when more than one element are there
prev = temp;
while (temp != NULL) {
if (temp->data == num) {
prev->next = temp->next;
free(temp);
cout<<num<<" is deleted\n";
break;
}
prev= temp;
temp = temp->next;
}
if(temp==NULL)
{
cout<<"not found, can't be deleted\n";
}
}
};
int main() {
List list;
list.addNum(1);
list.addNum(2);
list.addNum(3);
list.addNum(4);
list.addNum(5);
list.addNum(6);
list.PrintList();
list.DelNum(3);
list.DelNum(7);
list.PrintList();
return 0;
}
I hope it will help you.
I am trying to create singly-linked list. After the first push, head is still null. Why is the head not updated after the first push?
using namespace std;
typedef struct node {
int data; // will store information
node *next; // the reference to the next node
};
void push(node*,int);
void print(node*);
int main()
{
node* head = NULL; //empty linked list
push(head, 2);
if (head == NULL) {
cout << "vrvrvr";
}
push(head, 3);
push(head, 5);
push(head, 2);
//print(head);
getchar();
return 0;
}
void push(node* x, int y){
node *temp = new node();
if (x == NULL) { // check linked list is empty
temp->next = x;
temp->data = y;
x = temp;
}
else {
node *temp1 = new node();
temp1 = x;
while (temp1->next != NULL) { // go to the last node
temp1 = temp1->next;
}
temp1->next = temp;
temp->data = y;
temp->next = NULL;
delete temp1; // 'temp' node will be the last node
}
}
void print(node* x){
node *temp1 = new node();
temp1 = x;
while (temp1->next != NULL) {
cout << temp1->data << endl;
temp1 = temp1->next;
}
}
The main problem with push is that the changes made to x in the function are local to the function. It does not change the value of head in main.
You can fix that by changing the argument type to node*&.
void push(node*& x, int y) {
...
}
The other problems I see are in the block:
else {
node *temp1 = new node();
temp1 = x;
// Problem 1:
// After this, the memory returned by the previous line is lost.
// It is a memory leak.
while (temp1->next != NULL) { // go to the last node
temp1 = temp1->next;
}
temp1->next = temp;
temp->data = y;
temp->next = NULL;
delete temp1; // 'temp' node will be the last node
// Problem 2:
// You are deleting a node from the linked list.
// The linked list now has a dangling pointer.
}
You can correct those problems by using:
node *temp1 = x;
while (temp1->next != NULL) { // go to the last node
temp1 = temp1->next;
}
temp1->next = temp;
temp->data = y;
temp->next = NULL;
}
Suggested improvements
Remove typedef from definition of node. It is a dangling typedef in your posted code. Also, you can use node without a typedef in C++.
struct node {
int data;
node *next;
};
Add a constructor to node.
struct node {
node(int d) : data(d), next(nullptr) {}
int data;
node *next;
};
That will simplify your code in push.
void push(node*& x, int y){
node *temp = new node(y);
if (x == NULL) { // check linked list is empty
x = temp;
}
else {
node *temp1 = x;
while (temp1->next != NULL) { // go to the last node
temp1 = temp1->next;
}
temp1->next = temp;
}
}
My program should create a linked list and show it. My problem is when the addelemnt_end function ends, it doesn't update head and last.
I tried with debug and when my function is done, the info and next part from head and last are "unable to read memory".
struct node{
int info;
node *next;
};
node *head, *last;
void addelement_end(node *head, node *last, int element)
{if (head == NULL)
{ node *temp = new node;
temp->info = element;
temp->next = NULL;
last = temp;
head = temp;
}
else {node*temp = new node;
last->next = temp;
temp->info = element;
temp->next = NULL;
last = temp;
}
}
void show(node* head, node *last)
{
if (head==NULL)
cout << "Empty list";
else
while (head != NULL)
{
cout << head->info << " ";
head = head->next;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int x, n, i;
cout << "how many numbers";
cin >> n;
head = last = NULL;
for (i =1; i <= n; i++)
{
cin >> x;
addelement_end(head, last, x);
}
show(head, last);
return 0;
}
It's a very common error. Here is a similar illustration of the problem:
int change_a(int a) {
a = 42;
}
int main() {
int a = 10;
change_a(a);
printf("%d\n", a);
return 0;
}
This will print 10 because in the function change_a you are only modifying a copy of the value contained in the variable a.
The correct solution is passing a pointer (or using a reference since you are using C++).
int change_a(int *a) {
*a = 42;
}
int main() {
int a = 10;
change_a(&a);
printf("%d\n", a);
return 0;
}
But maybe you're going to tell me: "I'm already using a pointer!". Yes, but a pointer is just a variable. If you want to change where the pointer points, you need to pass a pointer to that pointer.
So, try this:
void addelement_end(node **head, node **last, int element)
{
if (*head == NULL)
{ node *temp = new node;
temp->info = element;
temp->next = NULL;
*last = temp;
*head = temp;
}
else {
node *temp = new node;
(*last)->next = temp;
temp->info = element;
temp->next = NULL;
*last = temp;
}
}