deleting a linked list node, C++ function not working - c++

#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.

Related

How to use subscript operator overloading in linklist using c++

I want to use subscript operator overloading in linklist but everytime it give me Segmentation fault (core dumped) ERROR! MY TASK IS : (Overload [] operator. Use for loop in main to display it.) I ALSO PROVIDING THE TASK LINK BELOW
//task link
[LINK OF TASK] https://anonymfile.com/r1XKK/dsa-a3.pdf
//MY CODE IS :
#include <iostream>
using namespace std;
class LinkedList
{
private:
class Node
{
public:
int data;
Node * next;
Node(int data)
{
this->data = data;
this->next = NULL;
}
};
public:
Node *head;
LinkedList(){
head = NULL;
}
//Write a copy constructor. Also copy must be deep.
LinkedList(LinkedList& S)
{
head = S.head;
}
//Overload [] operator. Use for loop in main to display it.
void operator[](int i) {
head->data = i;
}
void InsertAtEnd(int data){
if (head == NULL)
{
head = new Node(data);
return;
}
Node * temp = head;
while (temp->next != NULL)
{
temp = temp->next;
}
temp->next = new Node(data);
}
void Insert(int d1, int d2)//Add the node of data d2 after the node with data d1. If d2 is not available add it to the end.
{
if (head == NULL)
{
Node * n = new Node(d2);
n->next = head;
head = n;
return;
}
Node * temp = head;
while (temp != NULL)
{
if (temp->data == d1)
{
Node * temp1 = temp->next;
temp->next = new Node(d2);
temp->next->next = temp1;
}
temp = temp->next;
}
}
void Delete(int data){
Node * todelete;
if(head->data == data){
todelete = head;
head = head->next;
free(todelete);
return;
}
Node *temp = head;
while(temp->next != NULL){
if(temp->next->data == data){
todelete = temp->next;
temp->next = temp->next->next;
free(todelete);
break;
}
temp = temp->next;
}
} // Deletes a node with data.
int getSize(){
Node * temp = head;
int size = 0;
while(temp != NULL){
temp = temp->next;
size++;
}
return size;
} //returns the count of elements in the list
bool IsEmpty(){
if(head == NULL){
return true;
}
else{
return false;
}
} //Returns true if empty.
void Merge(Node * list){
//merge
Node * temp = head;
while(temp != NULL){
if(temp->next == NULL and list != NULL){
temp->next = list;
break;
}
temp = temp->next;
}
//DISPLAY
while(head!=NULL){
cout<<head->data<<"->";
head=head->next;
}
cout<<"NULL"<<endl;
} //Merges the to the calling class.
void Erase(){
Node * erase;
while(head!= NULL){
erase = head;
head = head->next;
head = NULL;
}
free(erase);
} //Deletes every node in an array.
void SelectiveErase(int num) //Find num and delete everything after num.
{
Node * temp = head;
Node * todelete;
while(temp != NULL){
if(temp->data == num){
Node * erase = temp->next;
while(temp->next != NULL){
erase = temp->next;
temp->next = temp->next->next;
temp->next = NULL;
}
free(erase);
break;
}
temp = temp->next;
}
}
int FindNCount(int find)//Find and return count of all occurrence.
{
int counter = 0;
bool flag = false;
Node * temp = head;
while(temp->data!= find){
temp = temp->next;
counter++;
}
return counter;
}
int RemoveDuplicate(int find)//Find and remove every duplicate element in the list. Make //elements unique.
{
Node * temp = head;
Node *temp1;
while(temp != NULL){
temp1 = temp;
while(temp1->next != NULL){
if(temp->data == temp1->next->data and temp->data == find and temp1->next->data == find){
Node *todelete = temp1->next;
temp1->next = temp1->next->next;
free(todelete);
}
else{
temp1 = temp1->next;
}
}
temp = temp->next;
}
return find;
}
void FindNReplace(int find, int data)//Find and replace all occurrence recursively.
{
Node * temp = head;
while(temp != NULL){
if(temp->data == find){
temp->data = data;
break;
}
temp = temp->next;
}
}
void Display(){
static Node * temp= head;
if(temp == NULL){ cout << "NULL" << endl; return;}
cout << temp->data<<"->";
temp = temp->next;
Display();
}
};
void Swap() // swap the contents of one list with another list of same type and size. Also write parameter
{
LinkedList L,L1;
cout<<"AFTER SWAPING THE VALUE OF FIRST LIST \n";
while(L.head != NULL && L1.head != NULL){
int temp = L.head->data;
L.head->data = L1.head->data;
L1.head->data = temp;
cout<<L.head->data<<"\n";
L.head = L.head->next;
L1.head = L1.head->next;
}
cout<<endl;
}
int main()
{
// You must call Display function after every function.
LinkedList L{};
L[23];
// LinkedList L1;
// L1.InsertAtEnd(5);
// L1.InsertAtEnd(6);
//L.Erase();
// cout<<L.FindNCount(1)<<endl;
//L.SelectiveErase(2);
//L.Display();
//L.Merge(L1.head);
//L.RemoveDuplicate(2);
//L.Display();
//Swap();
return 0;
}
Overloading the subscript operator should return something. The assignment looks a bit vague, but I hope this will fix it:
//Overload [] operator. Use for loop in main to display it.
Node* operator[](int i) {
Node* nodePtr = head;
int counter = 0;
while (nodePtr != NULL && counter != i) {
nodePtr = nodePtr->next;
counter++;
}
return nodePtr;
}

Linked list c++ insertback

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

Reversing LinkedList result in wrong links by recursion

I wrote the following code to reverse a linked list recursively for my homework. However, It's not connecting the links properly. Can please someone tell me what's wrong in the following reverse function? I have tried GDB as well. But, could not figure out what's wrong?
#include <iostream>
using namespace std;
class Node
{
public:
int data;
Node *next;
explicit Node(int data)
{
this->data = data;
next = nullptr;
}
};
void pushBack(Node * &head, Node * &tail, int data)
{
if(head == nullptr)
{
head = new Node(data);
tail = head;
}
else
{
tail->next = new Node(data);
tail = tail->next;
}
}
void printList(Node *head)
{
if(head == nullptr)
return;
cout << head->data << " ";
printList(head->next);
}
void reverseListRecursive(Node * &head)
{
if(head->next == nullptr)
{
return;
}
reverseListRecursive(head->next);
head->next->next = head;
head->next = nullptr;
}
int main()
{
int cap;
cin >> cap;
Node *head = nullptr, *tail = nullptr;
for(int i = 0; i < cap; ++i)
{
int element;
cin >> element;
pushBack(head, tail, element);
}
reverseListRecursive(head);
printList(head);
return 0;
}
Head is being passed by reference and also the infinite recursion is also not there.
The problem is that the head pointer needs to point to the last node of the linked list. Following code fixes the problem.
void reverseListRecursive(Node * &head, Node *temp = nullptr)
{
if(temp == nullptr)
temp = head;
if(temp->next == nullptr)
{
head = temp;
return;
}
reverseListRecursive(head, temp->next);
temp->next->next = temp;
temp->next = nullptr;
}

Doubly Linked List - cannot in delete the first Node

struct Node
{
int data;
Node *next;
Node *prev;
};
class DoublyLinkedList
{
ofstream cout3;
Node *head;
public:
DoublyLinkedList()
{
head = NULL;
cout3.open("task3.out");
}
void insert(int num)
{
Node *temp = new Node;
//To insert if there are no elements
if(head == NULL)
{
temp->prev = NULL;
temp->data = num;
temp->next = NULL;
head = temp;
}
//To insert if there are elements
else
{
temp->prev = NULL;
temp->data = num;
temp->next = head;
head->prev = temp;
head = temp;
}
cout3<<"inserted "<<num<<endl;
}
void dele(int num)
{
Node *temp = head;
int found_num = 0;
while(temp != NULL)
{
if(temp->data == num)
{
found_num = 1;
break;
}
else
temp = temp->next;
}
if(found_num == 0)
cout3<<"cannot delete "<<num<<endl;
//To delete first element
else if (temp->prev == NULL)
{
head = temp->next;
(temp->next)->prev == NULL;
delete temp;
cout3<<"deleted "<<num<<endl;
}
//To delete last element
else if (temp->next == NULL)
{
(temp->prev)->next = NULL;
cout3<<"deleted "<<num<<endl;
delete temp;
}
//To delete any other element
else
{
(temp->prev)->next = temp->next;
(temp->next)->prev = temp->prev;
cout3<<"deleted "<<num<<endl;
delete temp;
}
}
void search(int num)
{
Node *temp = head;
int found_num = 0;
while(temp != NULL)
{
if(temp->data == num)
{
found_num = 1;
break;
}
else
temp = temp->next;
}
if(found_num == 0)
cout3<<"not found "<<num<<endl;
else
cout3<<"found "<<num<<endl;
}
void display()
{
Node *temp = head;
while(temp != NULL)
{
cout3<<temp->data<<" ";
temp = temp->next;
}
cout3<<endl;
}
};
My implementation of Doubly Linked List.
I only insert at the beginning and delete the first occurrence of the number.
However if I want to delete the first element then it prints "deleted number" but when i display the number is still there.
Problem seems to be in my delete function but I cannot find what it is
See this line: (temp->next)->prev == NULL;
You wrote == instead of = , this seems to be the problem.
You dont show how you print the value but im guessing you move backward untill null value before you start..
Just expend the code to test it, it will give out the warning. Fix it, then the program will function as expected.
$ g++ test.cpp
test.cpp:66:30: warning: equality comparison result unused
[-Wunused-comparison]
(temp->next)->prev == NULL;
~~~~~~~~~~~~~~~~~~~^~~~~~~
test.cpp:66:30: note: use '=' to turn this equality comparison into an
assignment
(temp->next)->prev == NULL;
^~
=
1 warning generated.
test.cpp
#include <iostream>
#include <fstream>
struct Node
{
int data;
Node *next;
Node *prev;
};
class DoublyLinkedList
{
std::ofstream cout3;
Node *head;
public:
DoublyLinkedList()
{
head = NULL;
cout3.open("task3.out");
}
void insert(int num)
{
Node *temp = new Node;
//To insert if there are no elements
if(head == NULL)
{
temp->prev = NULL;
temp->data = num;
temp->next = NULL;
head = temp;
}
//To insert if there are elements
else
{
temp->prev = NULL;
temp->data = num;
temp->next = head;
head->prev = temp;
head = temp;
}
cout3<<"inserted "<<num<<std::endl;
}
void dele(int num)
{
Node *temp = head;
int found_num = 0;
while(temp != NULL)
{
if(temp->data == num)
{
found_num = 1;
break;
}
else
temp = temp->next;
}
if(found_num == 0)
cout3<<"cannot delete "<<num<<std::endl;
//To delete first element
else if (temp->prev == NULL)
{
head = temp->next;
(temp->next)->prev == NULL;
delete temp;
cout3<<"deleted "<<num<<std::endl;
}
//To delete last element
else if (temp->next == NULL)
{
(temp->prev)->next = NULL;
cout3<<"deleted "<<num<<std::endl;
delete temp;
}
//To delete any other element
else
{
(temp->prev)->next = temp->next;
(temp->next)->prev = temp->prev;
cout3<<"deleted "<<num<<std::endl;
delete temp;
}
}
void search(int num)
{
Node *temp = head;
int found_num = 0;
while(temp != NULL)
{
if(temp->data == num)
{
found_num = 1;
break;
}
else
temp = temp->next;
}
if(found_num == 0)
cout3<<"not found "<<num<<std::endl;
else
cout3<<"found "<<num<<std::endl;
}
void display()
{
Node *temp = head;
while(temp != NULL)
{
cout3<<temp->data<<" ";
temp = temp->next;
}
cout3<<std::endl;
}
};
int main()
{
DoublyLinkedList list;
list.insert(3);
list.insert(4);
list.insert(5);
list.display();
list.dele(3);
list.display();
}
In below link there is a guide to free the memory. Delete function not work mostly you can free method.
https://www.geeksforgeeks.org/write-a-function-to-delete-a-linked-list/

Memory leak in linked list class

If I run this in visual studio it tells me there are memory leaks, but I don't see anything wrong with my destructor. What did I do wrong? Is it because the memory leak function is being called before the destructor? Am I not supposed to call the memory leak function at the end?
I already posted this on codereview and they said it work fine, but I hadn't included a destructor then. I added one now but I'm not sure if it's actually working.
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
struct node {
int key;
struct node *next;
};
class linked_list {
private:
struct node *head;
struct node *tail;
public:
linked_list() {
head = nullptr;
tail = nullptr;
}
void create(int key) {
struct node *temp;
temp = new struct node;
temp->key = key;
temp->next = nullptr;
head = temp;
tail = head;
}
void insert(int key) {
if (key < head->key) {
insert_beginning(key);
}
else if ((head->next == nullptr) || (key > tail->key)) {
insert_end(key);
}
else {
insert_middle(key);
}
}
void insert_beginning(int key) {
if (head->next == nullptr) {
tail = head;
}
struct node *temp;
temp = new struct node;
temp->key = key;
temp->next = head;
head = temp;
}
void insert_end(int key) {
struct node *temp;
temp = new struct node;
temp->key = key;
temp->next = nullptr;
if (head->next == nullptr) {
head->next = temp;
tail = temp;
}
else {
tail->next = temp;
}
tail = temp;
}
void insert_middle(int key) {
struct node *temp;
temp = new struct node;
temp->key = key;
struct node *current = head;
struct node *prev = current;
while (current->key < temp->key) {
prev = current;
current = current->next;
}
prev->next = temp;
temp->next = current;
}
void delete_node(int key) {
if (head == nullptr) {
cout << "List is empty\n";
return;
}
if (head->key == key) {
if (head->next == nullptr) {
delete(head);
head = tail = nullptr;
}
struct node *temp = head;
head = head->next;
delete(temp);
}
else {
struct node *current = head;
struct node *prev = current;
while ((current->key != key) && (current->next != nullptr)) {
prev = current;
current = current->next;
}
if ((current->key != key) && (current->next == nullptr)) {
cout << "Key not found\n";
}
else if ((current->key == key) && (current->next == nullptr)) {
tail = prev;
prev->next = nullptr;
delete(current);
}
else {
prev->next = current->next;
delete(current);
}
}
}
void search_node(int key) {
if (head->key == key || tail->key == key) {
cout << "Node found\n";
return;
}
struct node *current = head;
while ((current->key != key) && (current->next != nullptr)) {
current = current->next;
}
if (current->key == key) {
cout << "Node found\n";
}
else {
cout << "Node not found\n";
}
}
void print_nodes(void) {
struct node *current = head;
while (current != nullptr) {
cout << current->key << '\n';
current = current->next;
}
}
~linked_list() {
struct node *current = head;
struct node *prev = current;
while (current->next != nullptr) {
current = current->next;
delete(prev);
prev = current;
}
delete(prev);
}
};
int main(void) {
linked_list list;
list.create(0);
for (int i = 1; i < 20; ++i) {
list.insert(i);
}
list.search_node(5);
list.search_node(0);
list.search_node(-1);
list.delete_node(19);
list.delete_node(0);
list.print_nodes();
_CrtDumpMemoryLeaks();
}
When you call _CrtDumpMemoryLeaks();, you have not yet destructed your list object.
UPDATE
Adding a set of braces so as to destruct list before doing the memory leak diagnostic.
int main(void) {
{
linked_list list;
list.create(0);
for (int i = 1; i < 20; ++i) {
list.insert(i);
}
list.search_node(5);
list.search_node(0);
list.search_node(-1);
list.delete_node(19);
list.delete_node(0);
list.print_nodes();
}
_CrtDumpMemoryLeaks();
}
The usual way to do a leak check as late as possible with MSVC is to enable the automatic dump functionality, with the following code:
_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)|_CRTDBG_LEAK_CHECK_DF);
This will do a leak check after main/WinMain has returned and global object destructors have run. And if you've ever seen an MFC dump report that is how it is enabled.