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);
Related
Hi Currently i have been honing my skill in the data structure so that i can become a good Game Developer, i am Learning Linked list and made a Linked list Program with Insertion ,Deletion and Recursive insertion and Reversing a Linked list Can you Guys tell me am i here Clearing the assigned memory Created with the new Operator Correctly, I am getting the Desired Output but i am worried about memory leak. ... please be gentle aim Still learning.
class Node
{
int data;
Node *Next;
public:
int GetData()
{
return data;
}
void SetData(int Data)
{
data = Data;
}
Node *GetNext()
{
return Next;
}
void SetNext(Node *next)
{
Next = next;
}
};
void Insert(Node **Head, int x)
{
Node *temp = new Node();
temp->SetData(x);
temp->SetNext(*Head);
*Head = temp;
}
void InsertAt(Node **Head, int x, int n)
{
if (n == 0)
{
std::cout << "The Given data at 'n' cannot be assigned to null\n";
}
Node *temp = new Node();
temp->SetData(x);
if (n == 1)
{
temp->SetNext(nullptr);
*Head = temp;
return;
}
Node *temp2 = *Head;
if (Head == nullptr)
{
std::cout << "The Given data cannot be assigned to null\n";
}
for (int i = 0; i < n - 2; i++)
{
temp2 = temp2->GetNext();
}
temp->SetNext(temp2->GetNext());
temp2->SetNext(temp);
}
void AppendList(Node **Head, int Data)
{
Node *temp = new Node();
Node *LastNode = *Head;
temp->SetData(Data);
temp->SetNext(nullptr);
if (*Head == nullptr)
{
*Head = temp;
return;
}
// else Traverse till last node.
while (LastNode->GetNext() != nullptr)
{
LastNode = LastNode->GetNext();
}
LastNode->SetNext(temp);
}
void DeleteNode(Node **Head, int n)
{
Node *temp = *Head;
if (n == 1)
{
*Head = temp->GetNext();
std::cout << "\nAfter Deletion of Head Node\n";
return;
}
for (int i = 0; i < n - 2; i++)
{
temp = temp->GetNext();
}
Node *temp2 = temp->GetNext();
temp->SetNext(temp2->GetNext());
std::cout << "After Deletion of Node\n";
}
Node *ReverseList(Node *Head)
{
Node *Current, *Prev, *next;
Current = Head;
Prev = nullptr;
while (Current != nullptr)
{
next = Current->GetNext();
Current->SetNext(Prev);
Prev = Current;
Current = next;
}
Head = Prev;
return Head;
}
int LinkedList_Count(Node *Head)
{
int count = 0;
Node *Current = Head;
while (Current != nullptr)
{
count++;
Current = Current->GetNext();
}
std::cout << "Number of Elements: " << count;
return count;
}
void PrintList(Node *Head)
{
std::cout << "Data list : ";
while (Head != nullptr)
{
std::cout << " " << Head->GetData();
Head = Head->GetNext();
}
std::cout << "\n";
}
//Print Listed using Recursion
void Recursion_Print(Node *Head)
{
if (Head == nullptr)
{
return;
}
std::cout << ' ' << Head->GetData(); //comment to Do Reverse the Linked list
Recursion_Print(Head->GetNext());
//std::cout << ' ' << Head->GetData();//unComment to Reverse the linked List recursively
}
Node *RecursiveRevList(Node *Head)
{
Node *temp;
if (Head->GetNext() == nullptr)
{
temp = Head;
return temp;
}
temp = RecursiveRevList(Head->GetNext());
Head->GetNext()->SetNext(Head);
Head->SetNext(nullptr);
return temp;
}
void RunList()
{
Node *Head = NULL;
//AppendList(&Head, 16);
Insert(&Head, 6);
Insert(&Head, 7);
Insert(&Head, 8);
InsertAt(&Head, 18, 2);
std::cout << "Data list : \n";
Recursion_Print(Head);
std::cout << '\n';
LinkedList_Count(Head);
DeleteNode(&Head, 1);
//Head = ReverseList(Head);
Head = RecursiveRevList(Head);
PrintList(Head);
LinkedList_Count(Head);
delete Head;
}
You're writing C-style code; in C++, you should avoid explicit calls to new. Your example is far too long to rewrite, but here is a very small start:
#include <memory>
class Node
{
int data;
std::shared_ptr<Node> Next;
// ...
void Insert(std::shared_ptr<Node>& Head, int x)
{
auto temp = std::make_shared<Node>();
// ...
}
(Note that std::unique_ptr is probably a better choice than std::shared_ptr, but that incurs complications with copying Node of which you're "blissfully" unaware right now.)
And, in practice, you should really use std::list (in your case, std::list<int>) rather than writing your own. Once you're proficient using std::list (and friends like std::vector), you'll be better able to "roll your own."
As pointed out in the comments by many learned people, you have a memory leak in your program. When you are deleting the nodes, you're not actually freeing the allocated memory locations. The correct way? Use delete to deallocate the memory from the program.
I would recommend you to learn it as a rule of thumb, when programming in C or C++, if you're allocating dynamic memory somewhere in your program, then in all certainty you'd have some deletion method where you should use free() or delete to deallocate the memory from the heap.
Here are some resources which might help you.
https://www.geeksforgeeks.org/g-fact-30/
https://www.geeksforgeeks.org/delete-in-c/
https://en.cppreference.com/w/cpp/language/delete (might be a little hard if you're a beginner)
I am trying to remove a node from a linked list, when given the value of the node to remove.
Here is my code:
virtual void remove(T value) {
cout << "In remove" << endl;
if(value == my_list) {
Node *current = my_list;
my_list = my_list->next;
delete current;
}
else {
Node *ptr = my_list;
while (ptr != NULL) {
if(ptr == value) {
Node *current = ptr->next;
ptr->next = ptr->next->next;
delete current;
num_items--;
}
else{
ptr = ptr->next;
}
}
}
};
I keep receiving the error:
LinkedList.h:106:15: error: ISO C++ forbids comparison between pointer and integer [-fpermissive]
if(value == my_list) {
~~~~~~^~~~~~~~~~
LinkedList.h:114:21: error: ISO C++ forbids comparison between pointer and integer [-fpermissive]
if(ptr == value) {
I think my problem is "value" is the value of the node and not the position of the node, but I'm not sure how to change that.
EDITED:
Here is the declaration of all the variables:
template <class T>
class LinkedList: public LinkedListInterface<T>
{
private:
struct Node {
T data;
Node* next;
Node(const T& the_data, Node* next_val = NULL) :
data(the_data) {next = next_val;}
};
Node *my_list;
int num_items;
public:
LinkedList(void) {
my_list = NULL;
num_items = 0;
cout << "In constructor" << endl;
};
virtual ~LinkedList(void) {
cout << "In deconstructor" << endl;
while(my_list != NULL) {
Node *current = my_list;
my_list = my_list->next;
delete current;
};
};
unfortunately I don't have full insight of what "Node" contains.
If node contains "value" field then your code should look like this:
virtual void remove(T value) {
cout << "In remove" << endl;
// my_list replaced with my_list -> value
if(value == my_list->value) {
Node *current = my_list;
my_list = my_list->next;
delete current;
}
else {
Node *ptr = my_list;
while (ptr != NULL) {
// ptr replaced with ptr-> value
if(ptr->value == value) {
Node *current = ptr->next;
ptr->next = ptr->next->next;
delete current;
num_items--;
}
else{
ptr = ptr->next;
}
}
}
};
What you did wrong is, you compared address of node element with integer value.
I suppose something like that (but it's difficult because your code is not complete : what is the accessor for value exactly ?) :
virtual void remove(T value) {
cout << "In remove" << endl;
if(value == my_list->data) {
Node *current = my_list;
my_list = my_list->next;
delete current;
}
else {
Node *ptr = my_list;
while (ptr != NULL) {
if(ptr->data == value) {
Node *current = ptr->next;
ptr->next = ptr->next->next;
delete current;
num_items--;
}
else{
ptr = ptr->next;
}
}
}
};
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 my own version of a linked list for learning. I have the following code. The reverseList function works correctly and if I print it inside that function it is good.
However, when I leave the function and then call the print method I get the the first value and then nothing (null). I'm guessing when I get out of the function it brings me back to the original first ([99]) element which is now actually the last element. So my print method outputs the element sees null is the next and ends.
Or I was thinking the changes I was making in the function were somehow only in that function's scope even though I passed a pointer, but that doesn't make sense because if that's the case then I should have all the original data still.
struct ListNode
{
int value;
ListNode* next = NULL;
};
void insertRecList(ListNode* list, int value)
{
if(list->next == NULL)
{
ListNode* end = new ListNode;
end->value = value;
list->next = end;
}
else
insertRecList(list->next, value);
}
void printList(ListNode* list)
{
std::cout << list->value << std::endl;
while(list->next != NULL)
{
list = list->next;
std::cout << list->value << std::endl;
}
}
void reverseList(ListNode* list)
{
ListNode* next;
ListNode* prev = NULL;
ListNode* cur = list;
while(cur != NULL)
{
if(cur->next == NULL)
{
cur->next = prev;
break;
}
else
{
next = cur->next;
cur->next = prev;
prev = cur;
cur = next;
}
}
list = cur;
std::cout << cur->value << " list:" << list->value << std::endl;
}
void testLinkedList()
{
srand(time(NULL));
ListNode nodes;
nodes.value = 99;
int val;
for(int i = 0; i < 5; i++)
{
val = rand() % 30 + 1;
insertRecList(&nodes, i);
//insertList(&nodes, val);
}
printList(&nodes);
reverseList(&nodes);
printList(&nodes);
}
int main()
{
testLinkedList();
return 0;
}
Appreciative of any help you guys can give me,
Thanks!
Update:
By passing the ListNode *list to reverseList, you create a copy of your pointer which point to the same address with nodes. Inside the function, you assign list to the updated cur pointer but the copy will be destroyed at the end. list still points to the same address as before passing to reverseList but its next has changed.
I have modified your code a little bit:
#include <cstdlib>
#include <iostream>
struct ListNode
{
int value;
ListNode* next = nullptr;
};
void insertRecList(ListNode* list, int value)
{
if(list->next == nullptr)
{
ListNode* end = new ListNode;
end->value = value;
list->next = end;
}
else
insertRecList(list->next, value);
}
void printList(ListNode* list)
{
std::cout << list->value << std::endl;
while(list->next != nullptr)
{
list = list->next;
std::cout << list->value << std::endl;
}
}
void reverseList(ListNode** list)
{
ListNode* cur = *list;
ListNode* next = cur->next;
ListNode* prev = nullptr;
while(cur != nullptr)
{
next = cur->next;
cur->next = prev;
prev = cur;
cur = next;
}
*list = prev;
}
void cleanNodes(ListNode *list) {
// clean goes here
}
void testLinkedList()
{
srand(time(nullptr));
ListNode *nodes = new ListNode();
nodes->value = 99;
int val;
for(int i = 0; i < 5; i++)
{
val = rand() % 30 + 1;
insertRecList(nodes, i);
//insertList(&nodes, val);
}
printList(nodes);
reverseList(&nodes);
printList(nodes);
cleanNodes(nodes);
}
int main()
{
testLinkedList();
return 0;
}
Try to compile with: -std=gnu++11
You don't change nodes in reverseList you're just changing list you're just changing a pointer on your struct which is a temporary object so physically nodes steel the same and pointed on the same first element which now has next attribute pointing on Null so the result of printList is correct. You need to work with pointers e.g.
#include <iostream>
#include <cstdlib>
struct ListNode
{
int value;
ListNode* next = NULL;
~ListNode(){
if(this->next)
delete this->next;
}
};
void insertRecList(ListNode* list, int value)
{
if(list->next == NULL)
{
ListNode* end = new ListNode;
end->value = value;
list->next = end;
}
else
insertRecList(list->next, value);
}
void printList(ListNode* list)
{
std::cout << list->value << std::endl;
while(list->next != NULL)
{
list = list->next;
std::cout << list->value << std::endl;
}
}
ListNode * reverseList(ListNode* list)
{
ListNode* next;
ListNode* prev = NULL;
ListNode* cur = list;
while(cur != NULL)
{
if(cur->next == NULL)
{
cur->next = prev;
break;
}
else
{
next = cur->next;
cur->next = prev;
prev = cur;
cur = next;
}
}
std::cout << cur->value << " list:" << list->value << std::endl;
return cur;
}
void testLinkedList()
{
srand(time(NULL));
ListNode * nodes = new ListNode;
nodes->value = 99;
int val;
for(int i = 0; i < 5; i++)
{
val = rand() % 30 + 1;
insertRecList(nodes, i);
//insertList(&nodes, val);
}
printList(nodes);
nodes = reverseList(nodes);
printList(nodes);
delete nodes;
}
int main()
{
testLinkedList();
return 0;
}
Also, don't forget to delete object created dynamically
Reversing a linked list is not a fundamental operation. It does not belong among the basis operations of your class. It is easier (and safer) to implement it in terms of your other operations. Roughly:
Create an empty list.
While the first list is not empty, remove a node from the front of the first list and insert it into the front of the second list.
The second list is now the reverse of the original.
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)