I have compiled my code and it seemed to work correctly. But out of no-where I get the error (this->tail was nullptr). I have tried changing the creation of the new node. But nothing seems to work. I cannot tell where tail is being set to nullptr and messing up the code.
How would I go about fixing this problem? Is there any way to set tail to non-nullptr without ruining every other function? I am not too familiar with exception throwing, so if you could explain the situation it would help a lot.
#ifndef MYDLL_H
#define MYDLL_H
#include <iostream>
#include <new>
using namespace std;
class MyDLL
{
struct Node
{
int i;
Node* next;
Node* prev;
};
Node* head;
Node* tail;
public:
MyDLL();
~MyDLL();
void append(int);
void remove(int);
bool find(int) const;
void clear();
void print() const;
void reverse() const;
};
MyDLL::MyDLL()
{
head = nullptr;
tail = nullptr;
}
MyDLL::~MyDLL()
{
clear();
}
void MyDLL::append(int i)
{
Node *n = new Node{ i, nullptr, nullptr };
if (head = nullptr)
{
head = n;
tail = n;
}
else
{
n->prev = tail;
tail->next = n; **<--- This is where the exception thrown error is showing up**
tail = n;
}
}
void MyDLL::remove(int i)
{
Node* p = head;
Node* q = tail;
while (p != nullptr && p->i != i)
{
q = p;
p = p->next;
}
if (p = nullptr)
{
return;
}
if (q = nullptr)
{
head = p->next;
}
else
{
q->next = p->next;
}
if (p->next = 0)
{
tail = q;
}
else
{
p->next->prev = q;
}
delete(p);
}
bool MyDLL::find(int i) const
{
Node* p = tail;
while (p != nullptr)
{
if (p->i = i)
{
return (true);
}
p = p->prev;
}
return (false);
}
void MyDLL::clear()
{
while (tail != nullptr)
{
Node* p = tail;
tail = p->prev;
delete (p);
}
head = nullptr;
}
void MyDLL::print() const
{
Node* p = head;
while (p)
{
cout << p->i << "\t";
p = p->next;
}
cout << "\n";
}
void MyDLL::reverse() const
{
Node* p = tail;
while (p)
{
cout << p->i << "\t";
p = p->prev;
}
cout << "\n";
}
#endif
int main()
{
MyDLL list;
list.append(5);
list.append(6);
list.append(7);
list.append(8);
list.print();
list.reverse();
cout << system("pause");
}
This code is exactly why you want to use nullptr = tail instead of tail = nullptr. In particular, every time you "check" for tail to be a null pointer, you are assigning nullptr to tail, and then assign operator returns a value which gets then implicitly casted to a boolean value, giving you no errors. But the error is actually there. Replace the "=" operator with "==" when performing a comparison, unless you actually have a reason for assigning and checking the return value.
Please fix = with == in your code.
void MyDLL::append(int i)
{
Node *n = new Node{ i, nullptr, nullptr };
if (head == nullptr)
It is always recommended to do like the reverse comparison (nullptr == head)
Related
I have to do XOR linked list. Now im at point that i want to proper way clear memory. I did something like this but it seems doesnt work.
Minimal code i could add to work
void deleteAll(Data* head)
{
if (head == NULL)
cout << "Empty list." << endl;
else
{
if (XOR(head, NULL) == NULL)
{
Data* tmp = NULL;
Data* next;
while (head)
{
next = XOR(head->npx, tmp);
tmp = head;
delete head;
//cout << head->liczba << endl; EDIT <<< this line is not problem
head = next;
}
}
}
}
This is the moment when i alocate data
Data* tmp = new Data;
tmp->liczba = num;
tmp->npx = XOR(*head, NULL);
if (*head != NULL)
{
(*head)->npx = XOR(XOR((*head)->npx,NULL),tmp);
}
*head = tmp;
tmp = NULL;
delete tmp;
In main function after deleting function i run printAll function, then i can see that data has not been cleared.
Edit:
#include <iostream>
using namespace std;
struct Data {
int liczba;
Data* npx;
};
struct Data* XOR(struct Data* prev, struct Data* next)
{
return (Data*)((uintptr_t)(prev) ^ (uintptr_t)(next));
}
void pushEnd(Data** head, int num)
{
Data* tmp = new Data;
tmp->liczba = num;
tmp->npx = XOR(*head, NULL);
if (*head != NULL)
{
(*head)->npx = XOR(XOR((*head)->npx,NULL),tmp);
}
*head = tmp;
tmp = NULL;
delete tmp;
}
void printBackward(Data* head)
{
if (head == NULL)
cout << "Pusta lista." << endl;
else
{
Data* next;
Data* prev = NULL;
while (head)
{
cout << head->liczba << endl;
next = XOR(head->npx, prev);
prev = head;
head = next;
}
}
}
void deleteAll(Data* head)
{
if (head == NULL)
cout << "Empty list." << endl;
else
{
if (XOR(head, NULL) == NULL)
{
Data* tmp = NULL;
Data* next;
while (head)
{
next = XOR(head->npx, tmp);
tmp = head;
delete head;
head = next;
}
}
}
}
int main()
{
Data* head = NULL;
pushEnd(&head, 5);
pushEnd(&head, 10);
pushEnd(&head, 7);
pushEnd(&head, 3);
printBackward(head);
cout << head->liczba;
cout <<endl<< "DEL" << endl;
deleteAll(head);
printBackward(head);
}
In deleteAll you have a line preventing all deletions:
if(XOR(head, NULL) == NULL) { // remove this line
Your deleteAll functions also takes a Data* and all changes you make to head will be local to the function only. A minimal change needed that should make it work is to take head as a Data*& - that is, a reference to a pointer, so that all changes to do to head in your function are actually made to the head you defined in main.
Example:
void deleteAll(Data*& head) {
if(head == nullptr)
cout << "Empty list." << endl;
else {
Data* tmp = nullptr;
Data* next;
while(head) {
next = XOR(head->npx, tmp);
tmp = head;
delete head;
head = next;
}
}
}
You still call it the same way: deleteAll(head);.
If you prefer calling it with deleteAll(&head); you could define the function like this:
void deleteAll(Data** head) {
if(*head == nullptr)
cout << "Empty list." << endl;
else {
Data* tmp = nullptr;
Data* next;
while(*head) {
next = XOR((*head)->npx, tmp);
tmp = *head;
delete *head;
*head = next;
}
}
}
I am implementing a linked list with a merge sort function for a class project. My program compiles, but when I try to run it I get segmentation fault(core dumped). I debugged my program using GDB, and found that the segfault happens with the pointer frontRef and backRef in my listSplit() function (line 98 in the code below).
Can someone please help me? For the life of me I can't figure out why I am getting a segfault. I would greatly appreciate help with this.
#include "orderedList.h"
orderedList::orderedList() {
listLength = 0;
traversalCount = 0;
head = nullptr;
tail = nullptr;
}
void orderedList::add(int n) {
listLength++;
struct node* point = new node;
point->value = n;
point->next = nullptr;
if (head == nullptr) {
head = point;
tail = point;
}
else {
point->next = head;
head = point;
}
}
void orderedList::merge(struct node** headRef) {
struct node *listHead = *headRef;
struct node *a;
struct node *b;
if ((listHead == nullptr) || (listHead->next == nullptr)) {
return;
}
listSplit(listHead, &a, &b);
merge(&a);
merge(&b);
*headRef = sortedMerge(a, b);
}
orderedList::node* orderedList::sortedMerge(struct node* a, struct node *b)
{
struct node* result = nullptr;
if (a == nullptr) {
return (b);
}
if (b == nullptr) {
return (a);
}
if (a->value <= b->value) {
result = a;
result->next = sortedMerge(a->next, b);
}
else {
result = b;
result->next = sortedMerge(a, b->next);
}
return (result);
}
void orderedList::print() {
struct node* temp = head;
while (temp != nullptr) {
std::cout << temp->value << " ";
temp = temp->next;
}
delete(temp);
}
int orderedList::search(int key) {
int traversals = 1;
struct node* current = head;
struct node* previous = nullptr;
while (current != nullptr) {
if (current->value == key) {
if (previous != nullptr) {
previous->next = current->next;
current->next = head;
head = current;
return traversals;
}
}
previous = current;
current = current->next;
traversals ++;
}
return 1;
}
void orderedList::listSplit(struct node* source, struct node** frontRef, struct node** backRef) { // <--- Line 98
struct node* current = source;
int hopCount = ((listLength - 1) / 2);
for (int i = 0; i < hopCount; i++) {
current = current->next;
}
*frontRef = source;
*backRef = current->next;
current->next = nullptr;
}
You made *backRef point to current->next and then you let current->next = nullptr. This makes *backRef pointing to a nullptr. Did you later try to do something with the returned backRef, aka a node variable in your caller code?
Alright so I am attempting to implement a LinkedList data structure but when I try to loop through my list (printNodes and insert functions) I run into an error that says: "Unhandled exception thrown: read access violation. tmpNode was 0xCDCDCDCD." I feel like it has something to do with my pointers not behaving in the manner I think they should but I am not sure. Some assistance would be very much appreciated.
#include<iostream>;
using namespace std;
struct Node {
int data;
Node* next;
Node(int el) {data = el; } //constructor
Node(int el, Node* ptr) { data = el; next = ptr; } //constructor
};
class LinkedList {
public:
Node* head = NULL, * tail = NULL;
void addToHead(int el) {
head = new Node(el, head);
}
void insert(int el) {
Node* newNode = new Node(el);
if (head == nullptr) {
head = newNode;
}
else {
Node* tmpNode = head;
while (tmpNode->next != nullptr) {
tmpNode = tmpNode->next;
}tmpNode->next = newNode;
}
}
void printNodes() {
Node* tmpNode = head;
cout << tmpNode->data;
while (tmpNode->next != nullptr) {
std::cout << tmpNode->data;
tmpNode = tmpNode->next;
}
}
};
int main() {
LinkedList myList = LinkedList();
myList.insert(10);
myList.addToHead(20);
myList.insert(10);
myList.printNodes();
}
Your iteration is correct, but there is a problem with your printNodes function. It dereference tmpNode without checking for null:
void printNodes() {
Node* tmpNode = head;
cout << tmpNode->data; // <-- here
while (tmpNode->next != nullptr) {
std::cout << tmpNode->data;
tmpNode = tmpNode->next;
}
}
I would change it to the following:
void printNodes() {
Node* tmpNode = head;
while (tmpNode != nullptr) {
std::cout << tmpNode->data << ", ";
tmpNode = tmpNode->next;
}
}
Apart from that, as said in comments, if you set next member to null in Node constructor it should work fine.
To search, it is the same thing but checking for the data:
Node* findNode(int el) {
Node* tmpNode = head;
Node* ret = nullptr;
while (tmpNode != nullptr) {
if (tmpNode->data == el) {
ret = tmpNode;
break;
}
tmpNode = tmpNode->next;
}
return ret;
}
And in main:
Node* n = myList.findNode(10);
if (n)
std::cout << "N 10: " << n->data << "\n";
n = myList.findNode(30);
if (n)
std::cout << "N 30: " << n->data << "\n";
else
std::cout << "There is no N 30\n";
There are memory leak problems also, as specified by #RikusHoney in the comments.
I'm trying to implement a function in my linked list that pushes the values of one list into a stack, and then pops off those values into another list.
The problem is, when I try to std::cout << x, the first stack's topmost element, I get this error:
c:\mingw\lib\gcc\mingw32\8.2.0\include\c++\ostream:682:5: error: no type named 'type' in 'struct std::enable_if<false, std::basic_ostream<char>&>'
#include <iostream>
#include <cstddef>
#include <string>
#include <stack>
#include <vector>
using Item = std::string;
class List {
public:
class ListNode { //Changed this to public so I could access it. If this was in private how would I accomplish this?
public:
Item item;
ListNode * next;
ListNode(Item i, ListNode *n=nullptr) {
item = i;
next = n;
}
};
ListNode * head;
ListNode * tail; //Also in private, changed to public, so I could access it. This is the bottom boundry.
class iterator {
ListNode *node;
public:
iterator(ListNode *n = nullptr) {
node = n;
}
Item& getItem() { return node->item; }
void next() { node = node->next; }
bool end() { return node==nullptr; }
friend class List;
};
public:
List() {
// list is empty
head = nullptr;
tail = nullptr;
}
List(const List &other)
{
iterator o = other.begin();
while(!o.end())
{
append(o.getItem());
o.next();
}
}
bool empty() {
return head==nullptr;
}
// Only declared, here, implemented
// in List.cpp
void append(Item a);
bool remove (Item ©);
void insertAfter(iterator, Item);
void removeAfter(iterator, Item&);
iterator begin() const {
return iterator(head);
}
};
void List::append(Item a) {
ListNode *node = new ListNode(a);
if ( head == nullptr ) {
// empty list
head = node;
tail = node;
} else {
tail->next = node;
tail = node;
}
}
bool List::remove(Item ©)
{
if (!empty()) {
copy = head->item;
ListNode *tmp = head->next;
delete head;
head = tmp;
if (head==nullptr)
tail = nullptr;
return true;
}
return false;
}
void List::insertAfter(iterator it, Item item)
{
if (it.node == nullptr)
{
// insert at head
ListNode *tmp = new ListNode(item,head);
// if list is empty, set tail to new node
if (tail==nullptr) {
tail = tmp;
}
// set head to new node
head = tmp;
}
else
{
ListNode *tmp = new ListNode(item,it.node->next);
it.node->next = tmp;
// could be a new tail, if so update tail
if (tail==it.node) {
tail = tmp;
}
}
}
void List::removeAfter(iterator it, Item& item)
{
// emtpy list or at tail, just return
if (it.node == tail) return;
if (it.node == nullptr)
{
ListNode * tmp = head;
head = head->next;
delete tmp;
if (head==nullptr)
tail = nullptr;
}
else
{
ListNode *tmp = it.node->next;
it.node->next = tmp->next;
delete tmp;
// could be that it.node is the new nullptr
if (it.node->next == nullptr)
tail = it.node;
}
}
List reverse(const List &l)
{
List::iterator iter1 = l.begin();
std::stack<List::ListNode> first;
while(!(iter1.end())) {
first.push(iter1.getItem());
iter1.next();
}
List lthe3;
int z = first.size();
for (int i=0; i < z; ++i) {
List::ListNode x = first.top();
std::cout << x;
}
return l;
}
void printList(List &l) {
List::iterator i = l.begin();
while(!i.end()) {
std::cout << i.getItem() << ", ";
i.next();
}
std::cout << std::endl;
}
int main()
{
List l;
l.append("one");
l.append("two");
l.append("three");
l.append("four");
std::cout << "List in order: ";
printList(l);
List l2 = reverse(l);
std::cout << "List in reverse order: ";
printList(l2);
return 0;
}
I have no clue what I'm doing wrong, but I'm really close to finishing this function.
Is there any way I could get some feedback?
I'm having problems with this code. I'm pretty sure it's in the swapping.
The line: curr->Data() = nextEl.Data() gives me the following error:
"expression must be a modifiable lvalue"
Any help is appreciated. Thank you in advance.
Here is the code for my bubble-sort algorithm:
class Node
{
private:
int data;
Node* next;
public:
Node() {};
void Set(int d) { data = d;};
void NextNum(Node* n) { next = n;};
int Data() {return data;};
Node* Next() {return next;};
};
class LinkedList
{
Node *head;
public:
LinkedList() {head = NULL;};
virtual ~LinkedList() {};
void Print();
void AddToTail(int data);
void SortNodes();
};
void LinkedList::SortNodes()
{
Node *curr = head;
Node *nextEl = curr ->Next();
Node *temp = NULL;
if(curr == NULL)
cout <<"There is nothing to sort..."<< endl;
else if(curr -> Next() == NULL)
cout << curr -> Data() << " - " << "NULL" << endl;
else
{
for(bool swap = true; swap;)
{
swap = false;
for(curr; curr != NULL; curr = curr ->Next())
{
if(curr ->Data() > nextEl ->Data())
{
temp = curr ->Data();
curr ->Data() = nextEl ->Data();
nextEl ->Data() = temp;
swap = true;
}
nextEl = nextEl ->Next();
}
}
}
curr = head;
do
{
cout << curr -> Data() << " - ";
curr = curr -> Next();
}
while ( curr != NULL);
cout <<"NULL"<< endl;
}
You are doing it wrong. You cannot change the value of temp variable returned by a function.
But you can make it work this way..
int& Data() {return data;};
though this is not good practise. Instead just use the setter you have..
curr->Set(nextEl->Data());
The statement
curr->Data() = nextEl.Data();
will never work, you are trying to assign something to the return value of a function. I don't know how you defined Node, but you probably meant something like
curr->Data = nextEl.Data();
i.e., assign something to a member of Node.
change
curr ->Data() = nextEl ->Data();
nextEl ->Data() = temp;
to
curr->Set(nextEl ->Data());
nextEl->Set(temp);