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/
Related
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;
}
#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.
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.
I've been trying to delete a node if the data matches a specific value.
Here's my delete value method:
void del_value(int data)
{
Node *temp = head;
int i = 0;
while(temp!=NULL)
{
if(temp->data == data)
{
del_index(i);
i--; // Since the nodes count will be reduced after deleting, reducing the index by one.
}
i++;
temp = temp->next;
}
}
And here is my del_index method(Which is working correctly):
int getCount()
{
int i = -1;
Node *temp = head;
while(temp!=NULL)
{
temp = temp->next;
i++;
}
return i;
}
void del_index(int pos)
{
int count = getCount();
if(pos == 0)
{
del_start();
}
else if(pos == count)
{
del_last();
}
else if(pos<0 || pos>count)
{
cout<<"Out of range"<<endl;
return;
}
else
{
int i = 1;
Node *temp = head;
while(i<pos)
{
temp = temp->next;
i++;
}
Node *toDel = temp->next;
Node *forward = toDel->next;
temp->next = forward;
delete toDel;
}
}
And here is my main method:
int main()
{
Mylist l;
l.add_start(4);
l.add_start(4);
l.add_start(4);
l.del_value(4);
l.show();
}
But it stucks when it reaches del_value method inside loop. Any idea where am I missing?
Update: (Added del_first and del_last methods
void del_start()
{
if(head == NULL)
{
cout<<"List is empty"<<endl;
return;
}
else
{
Node *temp = head;
head = head->next;
delete temp;
}
}
void del_last()
{
if(head == NULL)
{
cout<<"List is empty"<<endl;
return;
}
else
{
Node *temp = head;
while(temp->next != NULL)
{
tail = temp;
temp = temp->next;
}
tail->next = NULL;
delete temp;
}
}
Your del_value method will not work because you delete the object being pointed to by 'temp' then you dereference it after (with "temp = temp->next").
For your example code, I would cache the 'next' value before your conditional, for example:
Node *next = temp->next;
if(temp->data == data)
{
del_index(i);
i--;
}
i++;
temp = next;
I am assuming you're doing this for practice purposes but I would add the following suggestions:
I wouldn't call del_index here but remove the node inline, within the del_value method. As you have the necessary pointers to be able to remove it. del_index has to traverse your list a second time.
I would also recommend using the containers within the stl instead of rolling your own to avoid encountering issues like this.
I'm having some trouble printing out the contents of a linked list. I'm using an example code that I found somewhere. I did edit it a bit, but I don't think that's why it's crashing.
class stringlist
{
struct node
{
std::string data;
node* next;
};
node* head;
node* tail;
public:
BOOLEAN append(std::string newdata)
{
if (head)
{
tail->next = new node;
if (tail->next != NULL)
{
tail=tail->next;
tail->data = newdata;
return TRUE;
}
else
return FALSE;
}
else
{
head = new node;
if (head != NULL)
{
tail = head;
head->data = newdata;
return TRUE;
}
else
return FALSE;
}
}
BOOLEAN clear(std::string deldata)
{
node* temp1 = head;
node* temp2 = NULL;
BOOLEAN result = FALSE;
while (temp1 != NULL)
{
if (temp1->data == deldata)
{
if (temp1 == head)
head=temp1->next;
if (temp1==tail)
tail = temp2;
if (temp2 != NULL)
temp2->next = temp1->next;
delete temp1;
if (temp2 == NULL)
temp1 = head;
else
temp1 = temp2->next;
result = TRUE;
}
else // temp1->data != deldata
{
temp2 = temp1;
temp1 = temp1->next;
}
}
return result;
}
BOOLEAN exists(std::string finddata)
{
node* temp = head;
BOOLEAN found = FALSE;
while (temp != NULL && !found)
{
if (temp->data == finddata)
found=true;
else
temp = temp->next;
}
return found;
}
void print()
{
node* tmp = head;
while (tmp)
{
printf("%s", tmp->data.c_str());
tmp = tmp->next;
}
}
stringlist()
{
head=NULL;
tail=NULL;
}
};
My main() function is really simple:
int main()
{
stringlist mylist;
if (mylist.append("something"))
count++;
if (mylist.append("else"))
count++;
if (mylist.append("yet"))
count++;
cout<<"Added "<<count<<" items\n";
mylist.print();
return 0;
}
For some reason in Print() tmp is never NULL
in node, add a constructor to initialize next to null
As #rmn pointed out, you're not initializing the value of node->next.
BOOLEAN append(std::string newdata)
{
if (head)
{
tail->next = new node;
if (tail->next != NULL)
{
tail=tail->next;
tail->data = newdata;
tail->next = NULL; // <- this is the part that is missing
return TRUE;
}
else
return FALSE;
}
else
{
head = new node;
if (head != NULL)
{
tail = head;
head->data = newdata;
head->next = NULL; // <- it's also missing here.
return TRUE;
}
else
return FALSE;
}
}
You could solve this by having a default constructor for node:
struct node
{
std::string data;
node* next;
node() : next(NULL) { }
};
With the default constructor you won't need to add tail->next = NULL;.
You aren't initializing head->tail appropriately in append when head==NULL initially.
Correct. That's because tail is only NULL in your code when the linked list is initially created. After you add a node, you set tail = head, and from that point in time, every time you add an element, you set tail->next = new node, and then tail = tail->next... so that tail->next always = tail.