I am using c++ to implement a single link list of integers. My program simply asks the user to fill the list with 5 integers, the program should then delete any even integer and print the list after deletion.
Here is my code:
#include <iostream>
using namespace std;
class IntSLLNode
{
public:
IntSLLNode() { next = 0; }
IntSLLNode(int i, IntSLLNode *ptr = 0)
{
info = i;
next = ptr;
}
int info;
IntSLLNode *next;
};
class IntSLList
{
public:
IntSLList() {head = tail =0; }
void AddToTail(int);
void DeleteNode(int);
void DisplayList();
void deleteEven();
IntSLLNode * getHead()
{
return head;
}
private:
IntSLLNode *head, *tail;
};
void IntSLList::AddToTail(int el)
{
if (tail != 0) // if list not empty;
{ tail->next = new IntSLLNode(el);
tail = tail->next;
}
else
head = tail = new IntSLLNode(el);
}
void IntSLList::deleteEven()
{
IntSLLNode *current;
current=head;
int num;
while (current!=0)
{
num=current->info;
current=current->next;
if(num%2==0)
{
DeleteNode(num);
}
}
}
void IntSLList::DeleteNode(int el)
{
if(head !=0)
if(head==tail && el==head->info)
{
delete head;
head=tail=0;
}
else if(el==head->info)
{
IntSLLNode *tmp=head;
head=head->next;
delete tmp;
}
else
{
IntSLLNode *pred, *tmp;
for(pred=head, tmp=head->next;
tmp!=0 && !(tmp->info==el);
pred=pred->next, tmp=tmp->next);
if(tmp!=0)
{
pred->next=tmp->next;
if(tmp==tail)
tail=pred;
delete tmp;
}
}
}
void IntSLList::DisplayList()
{
IntSLLNode *current;
current=head;
if(current==0)
cout<<"Empty List!";
while (current!=0)
{
cout<<current->info<<" ";
current=current->next;
}
}
I got Unhandled exception at 0x002c1744 in ex4.exe: 0xC0000005: Access violation reading location 0xfeeefeee in statment int num=current->info; Can anyone suggest how to solve this?
I'm not sure about this, but I think the problem is laid here:
void IntSLList::deleteEven()
{
IntSLLNode *current;
current=head;
while (current!=0)
{
if(current->info%2==0)
DeleteNode(current->info);
current=current->next; // this line
}
}
I think there is a relation between deleted node which is preformed in the if statement and your next line. If you delete that specific pointer which points to an element in DeleteNode() then your current which it might be deleted till now will be pointing to a wrong address.
EDIT
void IntSLList::deleteEven()
{
IntSLLNode *current;
current=head;
while (current!=0)
{
if(current->info%2==0)
{
int ind = current->info;
current=current->next;
DeleteNode(ind);
}
else
{
current=current->next;
}
}
}
Related
I'm trying to implement a hash table with a linked list, but it keeps giving me a Segmentation fault. I'm not sure where I did wrong. Basically, I create a dynamic array with Node, then I use each Node as the head of the linked list. I'm struggling with this for a few days. Just couldn't figure out where it's wrong. Can anyone help, please? Here's a simple version code.
#include<iostream>
#include<string>
class HashTable
{
public:
HashTable()
: hashMap{ new Node[10] }
{
for (int i = 0; i < 10; i++)
{
hashMap[i].next = nullptr;
}
}
~HashTable()
{
delete[] hashMap;
}
unsigned int hasher(const std::string& x)
{
return x[0]%10;
}
void add(const std::string& key)
{
Node* newNode = new Node;
newNode->key = key;
newNode->next = nullptr;
if (hashMap[hasher(key)].next==nullptr)
{
hashMap[hasher(key)].next = newNode;
}
else
{
Node* current = hashMap[hasher(key)].next;
while (current->next != nullptr)
{
current = current->next;
}
current->next = newNode;
}
delete newNode;
}
void print(std::string key)
{
std::cout<<hashMap[hasher(key)].next->key<<std::endl;
}
private:
struct Node
{
std::string key;
Node* next;
};
Node* hashMap;
};
int main()
{
HashTable ht;
ht.add("Hello");
ht.print("Hello");
}
I am trying to just change the data of the Node to swap the nodes. Any help is appreciated. Maybe it's a basic mistake i am new to c++.
I know the method to SwapNodes using 4 pointer and that stuff sounds cool, but what's the problem in this?
#include <iostream>
using namespace std;
class Node
{
int data;
Node *next;
public:
Node(int val)
{
data=val;
next=NULL;
}
int Data(){return data;};
void ChangeData(int newData){data=newData;};
void setNext(Node *NEXT){next=NEXT;};
Node *Next(){return next;};
};
class LinkedList
{
Node *root;
public:
LinkedList();
void insert(int pos,int b);
void deleteNode(int a);
void outputList();
void SwapNodes(int x, int y);
void reverse();
};
LinkedList::LinkedList()
{
root=NULL;
}
void LinkedList::insert(int pos,int b)
{
Node *temp=root;
Node *newnode=new Node(b);
if(pos==0)
{
if(root==NULL)
{
root=newnode;
return;
}
newnode->setNext(root);
root=newnode;
return;
}
for (int i = 1; i <pos ; ++i)
{
temp=temp->Next();
}
newnode->setNext(temp->Next());
temp->setNext(newnode);
}
void LinkedList::deleteNode(int a)
{
Node *temp=root;
Node *agla=root->Next();
if(temp->Data()==a)
{
root=root->Next();
free(temp);
}
if(agla->Data()==a)
{
temp->setNext(agla->Next());
free(agla);
return;
}
while(agla!=NULL && agla->Data()!=a)
{
temp=agla;
agla=agla->Next();
}
if(agla==NULL)
{
cout << "key not found";
}
temp->setNext(agla->Next());
free(agla);
}
void LinkedList::SwapNodes(int x,int y)
{
Node *temp1=root;
Node *temp2=root;
if(x==y)return;
while(temp1!=NULL && (temp1)->Data()!=x)
{
(temp1)=(temp1)->Next();
}
temp1->ChangeData(y);
while(temp2!=NULL && (temp2)->Data()!=y)
{
(temp2)=(temp2)->Next();
}
if(temp1==NULL || temp2==NULL)
{
return;
}
(temp2)->ChangeData(x);
}
void LinkedList::reverse()
{
if(root == NULL) return;
Node *prev = NULL, *current = NULL, *next = NULL;
current = root;
while(current != NULL){
next = current->Next();
current->setNext(prev);
prev = current;
current = next;
}
root = prev;
}
void LinkedList::outputList()
{
Node *temp=root;
if(temp==NULL)
{
cout << "empty";
return;
}
while(temp!=NULL)
{
cout<< temp->Data()<< " ";
temp=temp->Next();
}
cout << "\n";
}
int main(int argc, char const *argv[])
{
LinkedList newList;
newList.insert(0,4);
newList.insert(1,5);
newList.insert(2,7);
newList.insert(3,9);
newList.insert(4,12);
newList.outputList();
newList.insert(2,6);
newList.outputList();
newList.deleteNode(5);
newList.outputList();
newList.SwapNodes(7,9);
newList.outputList();
newList.reverse();
newList.outputList();
return 0;
}
In
void LinkedList::SwapNodes(int x,int y)
{
Node *temp1=root;
Node *temp2=root;
if(x==y)return;
while((temp1)->Data()!=x)
{
(temp1)=(temp1)->Next();
}
temp1->ChangeData(y);
while((temp2)->Data()!=y)
{
(temp2)=(temp2)->Next();
}
(temp2)->ChangeData(x);
}
You are just undoing the work you already did.
while((temp1)->Data()!=x)
{
(temp1)=(temp1)->Next();
}
temp1->ChangeData(y);
Is going to find x and then set it to y. Then you go to do
while((temp2)->Data()!=y)
{
(temp2)=(temp2)->Next();
}
(temp2)->ChangeData(x);
Which finds that y you just created (as long as there wasn't a previous y) and sets it back to x. What you need to do is find the nodes to swap first and then swap their data. A simple refactor to
void LinkedList::SwapNodes(int x,int y)
{
Node *temp1=root;
Node *temp2=root;
if(x==y)return;
while((temp1)->Data()!=x)
{
(temp1)=(temp1)->Next();
}
while((temp2)->Data()!=y)
{
(temp2)=(temp2)->Next();
}
temp1->ChangeData(y);
(temp2)->ChangeData(x);
}
Should work. You also should add add error handling code in case x or y does no exist.
Not sure why you are using the parentheses everywhere but
(temp1)=(temp1)->Next();
Can just be written as
temp1 = temp1->Next();
while((temp1)->Data()!=x)
{
(temp1)=(temp1)->Next();
}
temp1->ChangeData(y);
Loops until it finds a link valued at x. Then overwrites the value with y. OK. But now you have two ys in the linked list, so odds are decent that
while((temp2)->Data()!=y)
{
(temp2)=(temp2)->Next();
}
(temp2)->ChangeData(x);
will simply find the Node that which was x and change it back to x.
while((temp1)->Data()!=x)
{
(temp1)=(temp1)->Next();
}
while((temp2)->Data()!=y)
{
(temp2)=(temp2)->Next();
}
temp1->ChangeData(y);
temp2->ChangeData(x);
Will prevent that by finding both x and y nodes before updating their value, but has other problems. Not the least of which is what happens when you hit the end of the list without finding x or y?
I'd rethink the linking logic because there doesn't seem to be any way to tell that you've hit the end of the list. Typical solution are to set next for the last Node to NULL or nullptr and test with something like
while(temp1 != nullptr)
I'm trying to create a basic singly-linked list using a separate Node class and LinkedList class. I barely know what I'm doing as I've just started learning C++, so any help would be greatly appreciated.
The LinkedList part of the code runs on its own, but I'm sure there are some corrections to be made there too. My main problem is that, when trying to add to the linked list, I'm getting (at line 64 of LinkedList.h):
Exception thrown: read access violation. this->head was nullptr.
I'm using Microsoft Visual Studio 2015. Here's the code:
LinkedList.h (it's inline):
#pragma once
#include <iostream>
using namespace std;
class Node
{
private:
Node *next = NULL;
int data;
public:
Node(int newData) {
data = newData;
next = NULL;
}
Node() {
}
~Node() {
if(next)
delete(next);
}
Node(int newData, Node newNext) {
data = newData;
*next = newNext;
}
void setNext(Node newNext) {
*next = newNext;
}
Node getNext() {
return *next;
}
int getData() {
return data;
}
};
class LinkedList
{
private:
Node *head;
int size;
public:
LinkedList()
{
head = NULL;
size = 0;
}
~LinkedList()
{
}
void add(int numberToAdd)
{
head = new Node(numberToAdd, *head);
++size;
}
int remove()
{
if (size == 0) {
return 0;
}
else {
*head = (*head).getNext();
--size;
return 1;
}
}
int remove(int numberToRemove)
{
if (size == 0)
return 0;
Node *currentNode = head;
for (int i = 0; i < size; i++) {
if ((*currentNode).getData() == numberToRemove) {
*currentNode = (*currentNode).getNext();
return 1;
}
}
}
void print()
{
if (size == 0) {
return;
}
else {
Node currentNode = *head;
for (int i = 0; i < size; i++) {
cout << currentNode.getData();
currentNode = currentNode.getNext();
}
cout << endl;
}
}
};
List Tester.cpp
// List Tester.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include "LinkedList.h"
using namespace std;
int main()
{
LinkedList myList;
myList.add(4);
system("pause");
}
You are making copies where you should not:
This:
Node(int newData, Node newNext) {
data = newData;
*next = newNext;
}
should be:
Node(int newData, Node* newNext) {
data = newData;
next = newNext;
}
Because now this:
head = new Node(numberToAdd, *head);
becomes this:
head = new Node(numberToAdd, head);
and will work even if head is a null pointer. You may need to adjust your other code accordingly.
Your whole implementation is full of errors. It should look more like this instead:
#pragma once
#include <iostream>
class Node
{
private:
int data;
Node *next;
public:
Node(int newData, Node *newNext = NULL)
: data(newData), next(newNext)
{}
void setNext(Node *newNext) {
next = newNext;
}
Node* getNext() {
return next;
}
int getData() {
return data;
}
};
class LinkedList
{
private:
Node *head;
int size;
public:
LinkedList()
: head(NULL), size(0)
{
}
~LinkedList()
{
Node *currentNode = head;
while (currentNode)
{
Node *nextNode = currentNode->getNext();
delete currentNode;
currentNode = nextNode;
}
}
void add(int numberToAdd)
{
head = new Node(numberToAdd, head);
++size;
}
bool remove()
{
Node *currentNode = head;
if (!currentNode)
return false;
head = currentNode->getNext();
delete currentNode;
--size;
return true;
}
bool remove(int numberToRemove)
{
Node *currentNode = head;
Node *previousNode = NULL;
while (currentNode)
{
if (currentNode->getData() == numberToRemove)
{
if (head == currentNode)
head = currentNode->getNext();
if (previousNode)
previousNode->setNext(currentNode->getNext());
delete currentNode;
return true;
}
previousNode = currentNode;
currentNode = currentNode->getNext();
}
return false;
}
void print()
{
Node *currentNode = head;
if (!currentNode) return;
do
{
std::cout << currentNode->getData();
currentNode = currentNode->getNext();
}
while (currentNode);
std::cout << std::endl;
}
};
Which can then be simplified using the std::forward_list class (if you are using C++11 or later):
#pragma once
#include <iostream>
#include <forward_list>
#include <algorithm>
class LinkedList
{
private:
std::forward_list<int> list;
public:
void add(int numberToAdd)
{
list.push_front(numberToAdd);
}
bool remove()
{
if (!list.empty())
{
list.pop_front();
return true;
}
return false;
}
bool remove(int numberToRemove)
{
std::forward_list<int>::iterator iter = list.begin();
std::forward_list<int>::iterator previous = list.before_begin();
while (iter != list.end())
{
if (*iter == numberToRemove)
{
list.erase_after(previous);
return true;
}
++previous;
++iter;
}
return false;
}
void print()
{
if (list.empty()) return;
std::for_each(list.cbegin(), list.cend(), [](int data){ std::cout << data });
std::cout << std::endl;
}
};
I am learning c++ and tried a creating a Linked-List Data structure.
Here is the program-
main.cpp
#include <iostream>
using namespace std;
class LinkedList
{
public:
int data;
LinkedList *nextNode;
void init(int value,LinkedList *root)
{
root->data=value;
root->nextNode=NULL;
}
void add(int value,LinkedList *root)
{
LinkedList *temp=new LinkedList;
if(root->nextNode==NULL)
{
//cout<<"IF ADD()"<<endl;
temp->data=value;
temp->nextNode=NULL;
root->nextNode=temp;
}
else
{
//cout<<"else ADD()"<<endl;
while(root->nextNode!=NULL)
{
root=root->nextNode;
}
temp->data=value;
temp->nextNode=NULL;
root->nextNode=temp;
}
}
void display(LinkedList *root)
{
if(root->nextNode==NULL)
{
cout<<root->data<<endl;
}
else
{
while(root->nextNode!=NULL)
{
cout<<root->data<<endl;
root=root->nextNode;
}
}
}
void free(LinkedList *root)
{
if(root->nextNode==NULL)
{
delete root;
}
else
{
while(root->nextNode!=NULL)
{
LinkedList *temp=root->nextNode;
delete root;
root=temp;
}
}
}
};
int main()
{
LinkedList *root=new LinkedList;
root->init(1,root);
root->add(2,root);
root->add(3,root);
root->add(4,root);
root->add(5,root);
root->add(6,root);
root->add(7,root);
root->add(8,root);
root->add(9,root);
root->add(10,root);
root->display(root);
root->free(root);
//root->display(root);
//delete root;
return 0;
}
Output-
1
2
3
4
5
6
7
8
9
My question is why it doesn't print the last item i.e 10.
And one more question, as you can see I am commenting in the following line
//delete root
inside my main method.
What if I don't call my free() method and uncomment this? Would it free the whole LinkedList?
Thanks
Porblem is with this function in else statement it does not go to last node because last node's next will be NULL. One more thing is you are modifying the root in display function is should be a const function. It should not modify the root.
void display(LinkedList *root)
{
if(root->nextNode==NULL)
{
cout<<root->data<<endl;
}
else
{
while(root->nextNode!=NULL)
{
cout<<root->data<<endl;
root=root->nextNode;
}
}
}
Actual implementation should be like this.
void display(LinkedList *root) const
{
LinkedList * temp = root;
while(temp!=NULL)
{
cout<<temp->data<<endl;
temp=temp->nextNode;
}
}
Regarding your second question-> It won't clear the memory. But because its a small code after application close memory will be freed. It's always best practice to free memory otherwise you will have memory leaks and if this data structure is used heavily it can take all memory and crash the application.
Also implementation of your free function is not correct. It should be like this
void free(LinkedList *root)
{
LinkedList * temp = root;
LinkedList * nodeToFree = root;
while(temp!=NULL)
{
temp=temp->nextNode;
delete nodeToFree;
nodeToFree = temp;
}
}
while(root->nextNode!=NULL)
{
cout<<root->data<<endl;
root=root->nextNode;
}
should be
while(root!=NULL)
{
cout<<root->data<<endl;
root=root->nextNode;
}
change Condition of display
#include <iostream>
using namespace std;
class LinkedList
{
public:
int data;
LinkedList *nextNode;
void init(int value,LinkedList *root)
{
root->data=value;
root->nextNode=NULL;
}
void add(int value,LinkedList *root)
{
LinkedList *temp=new LinkedList;
if(root->nextNode==NULL)
{
//cout<<"IF ADD()"<<endl;
temp->data=value;
temp->nextNode=NULL;
root->nextNode=temp;
}
else
{
//cout<<"else ADD()"<<endl;
while(root->nextNode!=NULL)
{
root=root->nextNode;
}
temp->data=value;
temp->nextNode=NULL;
root->nextNode=temp;
}
}
void display(LinkedList *root)
{
if(root->nextNode==NULL)
{
cout<<root->data<<endl;
}
else
{
while(root !=NULL) // Change this condition
{
cout<<root->data<<endl;
root=root->nextNode;
}
}
}
void free(LinkedList *root)
{
if(root->nextNode==NULL)
{
delete root;
}
else
{
while(root->nextNode!=NULL)
{
LinkedList *temp=root->nextNode;
delete root;
root=temp;
}
}
}
Here you can display it one time only as you are changing its root value so it would be better if you use temp variable to display as done by #sanjay in above case.
I was writing a C++ program to implement a linked list. On compilation it's not giving any error but in the output windows it goes blank and program ended with
list1.exe has
encountered a problem and needs to close.
Debugger response: Program received signal SIGSEGV, Segmentation fault.
Maybe it's because of memory leakage, but I'm not able to figure out the exact bug and how can we fix that. Please what's wrong in the prog and what should be fixed?
Below is the code
//Program to implement linked list
#include <iostream>
#include <cstdlib>
using namespace std;
class Node
{
int data;
Node * next;
public:
Node (){}
int getdata(){return data ;}
void setdata(int a){data=a;}
void setnext(Node* c){next=c;}
Node* getnext(){return next;}
};
class linkedlist
{
Node* head;
public:
linkedlist(){head=NULL;}
void print ();
void push_back(int data);
};
void linkedlist::push_back(int data)
{
Node* newnode= new Node();
if(newnode!=NULL)
{
newnode->setdata(data);
newnode->setnext(NULL);
}
Node* ptr= head;
if(ptr==NULL)
{head=newnode;}
while ((ptr->getnext())!=NULL)
{
ptr=ptr->getnext();
}
ptr->setnext(newnode);
}
void linkedlist::print()
{
Node* ptr=head;
if(ptr==NULL)
{cout<<"null"; return;}
while(ptr!=NULL)
{
cout<<(ptr->getdata())<<" ";
ptr=ptr->getnext();
}
}
int main()
{
linkedlist list;
list.push_back(30);
list.push_back(35);
list.print();
return 0;
}
The main issue is here:
if(ptr==NULL) {head=newnode;}
while ((ptr->getnext())!=NULL)
{
ptr=ptr->getnext();
}
ptr->setnext(newnode);
There's probably meant to be a return; in the if (ptr == NULL) part; as it stands, it sets head = newnode, but then continues to try to access ptr->getnext(), which causes the segfault.
Some answers have suggested setting ptr = head = newnode, but note that the bottom line is ptr->setnext(newnode)—this would cause head->getnext() == head. Infinite list!
For your interest, here's your code:
Formatted nice;
Cleaned up not to use using namespace std; (see the C++ FAQ on this);
Takes advantage of const-correctness;
etc.
Enjoy!
#include <iostream>
#include <stdexcept>
class Node {
int data;
Node *next;
public:
Node(): next(NULL) {}
int getdata() const {
return data;
}
void setdata(int a) {
data = a;
}
Node *getnext() const {
return next;
}
void setnext(Node *c) {
next = c;
}
};
class linkedlist {
Node* head;
public:
linkedlist(): head(NULL) {}
void print() const {
Node *ptr = head;
if (ptr == NULL) {
std::cout << "null";
return;
}
while (ptr != NULL) {
std::cout << ptr->getdata() << " ";
ptr = ptr->getnext();
}
}
void push_back(int data) {
Node *newnode = new Node();
if (newnode == NULL) {
throw std::runtime_error("out of memory!");
}
newnode->setdata(data);
Node *ptr = head;
if (ptr == NULL) {
head = newnode;
return;
}
while ((ptr->getnext()) != NULL) {
ptr = ptr->getnext();
}
ptr->setnext(newnode);
}
};
int main() {
linkedlist list;
list.push_back(30);
list.push_back(35);
list.print();
return 0;
}
In the following line: while ((ptr->getnext())!=NULL) ptr is NULL
The push_back code is incorrect, and I've seen some other parts of your code that can be improved:
#include <iostream>
#include<cstdlib>
using namespace std;
class Node
{
int data;
Node * next;
public:
Node(int d = 0) : data(d), next(NULL) {}
int getdata() { return data; }
void setdata(int a) { data = a; }
void setnext(Node* c) { next = c; }
Node* getnext() { return next; }
};
class linkedlist
{
Node* head;
public:
linkedlist() : head(NULL) {}
void print ();
void push_back(int data);
};
void linkedlist::push_back(int data)
{
Node* newnode = new Node(data);
if(head == NULL)
{
head = newnode;
}
else
{
Node* last = head;
while(last->getnext() != NULL)
last = last->getnext();
last->setnext(newnode);
}
}
void linkedlist::print()
{
Node* ptr = head;
if(!ptr)
{
cout << "null";
return;
}
while(ptr != NULL)
{
cout << ptr->getdata() << " ";
ptr=ptr->getnext();
}
}
int main()
{
linkedlist list;
list.push_back(30);
list.push_back(35);
list.print();
return 0;
}
There are still some points to be improved...