C++ Illegal Indirection with Nodes - c++

I've been trying to get a way to sort my Nodes (doubly linked) based on their "Priority" value/variable. However I keep getting stuck at an "Illegal Indirection" error, and not sure what it means (despite looking around).
Any help would be greatly appreciated, here is the code, it was taken from another answered question similar to mine on stackOverflow, so it may be implemented wrongly, but I've supplied part of my Node Class, and the function that uses the Sorting function (within a 'Queue Class');
I've highlighted the error (well pointed it out) in the "Sorting Function" block, any help is appreciated.
NODE CLASS
class Node
{
public:
Node *next; //Pointer to the next node
Node *prev; //Pointer to the previous node
Node(N i, int s, Node *nextptr, Node *prevptr = NULL, int currentPriority = 0, int currentId = 0) //Defines the components that make up the Node Class/Objects
{
val = i; //Value/Data input by the user upon creation of the Node.
priority = currentPriority; //Priority setting of the Node set by the user
processId = currentId; //Unique ID of the Node differentiating it from all other nodes
size = s; //Total number of Nodes.
next = nextptr; //Pointer to the Next Node (Down the Queue)
prev = prevptr; //Pointer to the previous Node (Up the Queue)
}
private:
N val; //Template variable of a value input by the user
int size; //Size variable of the total number of nodes
int priority; //Variable input by the user to determine where in the queue the node is placed
int processId; //Variable automatically set when the node is created. Unique to each Node.
};
Function that Calls it
void Queue::Display(void)
{
bubbleSort(front);
cout << '\n';
}
SORTING FUNCTION
void bubbleSort(Node<T> *&start)
{
int size = back->getProcessId();
int i = 0;
Node<T> *lastSwapped = NULL;
while (size--)
{
Node<T>
*current = start,
*prev = NULL,
*currentSwapped = NULL;
while (current->getPrev() != NULL)
{
Node<T> *after = current->getPrev();
ERROR IS HERE >>> if (*current->getPriority() > *after->getPriority())
{
current->next = after->next;
after->next = current;
if (prev == NULL)
start = after;
else
prev->next = after;
prev = after;
currentSwapped = current;
}
else
{
prev = current;
current = current->getPrev();
}
}
if (currentSwapped == NULL)
break;
else
lastSwapped = currentSwapped;
}
}

Related

Problem with my doubly linked list insert function

I am trying to finish up a assignment for my data structures c++ class. I have to define a double linked list of functions(like insert() size() remove() ) that was provided by my instructor. The instructor also includes the main file which runs tests on my code to see if it works.
I'm receiving his error message:
* Starting dlist tests *
Checking empty list...
FAILED: size of empty list is != 0.
I tried to rewrite the definition of the size() and insert() function and Im not understanding why im getting his error.
my instructors test code:
bool test_empty() {
std::cout << "Checking empty list...\n";
dlist e;
if(!verify(e))
return false;
if(e.size() != 0) {
std::cout << "FAILED: size of empty list is != 0.\n";
return false;
}
if(!e.empty()) {
std::cout << "FAILED: empty list is not .empty().\n";
return false;
}
return true;
}
my code for implementations:
void insert(node *previous, int value){
if(previous == nullptr){
node* n = new node;
n->value = value;
n->prev = previous;
n->next = nullptr;
return;
}
node* n = _head; //made a pointer to start at the head
while( n!= previous )//make n go down the list until it hits previous
{n = n->next;}
node* store_next = n->next; //store the address of the prev pointer of the next node
node* a = new node;//create the node that will be inserted
a->value = value;
n->next = a;// the pointer n points to the new node
a->prev = n; //the prev in the new node points to the previous
a->next = store_next; //the next in the new node points to the next node
store_next->prev = a; //the next node's prev points to the new inserted node
}
int size() const{
node* n = _head;
int size = 0;
while(n != nullptr){
size++;
n = n -> next;
}
return size;
}
Heres my default constructor and double linked list struct that my professor requires I use
class dlist {
public:
dlist() {
}
struct node {
int value;
node* next;
node* prev;
};

Error "Abort signal from abort(3) (sigabrt) " for linked list in C++

The following code is for a basic circular linked list, but when one inputs a large value for n(e.g 8 digits) it throws the "abort signal from abort(3) (sigabrt)" error. I'm not sure what it means and would love some guidance about fixing this with regard to my code.
Thank you!
#include<bits/stdc++.h>
using namespace std;
//First I created a structure for a node in a circular linked list
struct Node
{
int data;
struct Node *next;
};
// function to create a new node
Node *newNode(int data)
{
Node *temporary = new Node;
temporary->next = temporary;
temporary->data = data;
return temporary;
}
// This function finds the last man standing in
//the game of elimination
void gameOfElimination(int m, int n)
{
//first I created a circular linked list of the size which the user inputted
Node *head = newNode(1);
Node *prev = head;
//this loop links the previous node to the next node, and so on.
for (int index = 2; index <= n; index++)
{
prev->next = newNode(index);
prev = prev->next;
}
prev->next = head; //This connects the last and first nodes in our linked list together.
//when only one node is left, which is our answer:
Node *ptr1 = head, *ptr2 = head;
while (ptr1->next != ptr1)
{
int count = 1;
while (count != m)
{
ptr2 = ptr1;
ptr1 = ptr1->next;
count++;
}
/* Remove the m-th node */
ptr2->next = ptr1->next;
ptr1 = ptr2->next;
}
printf ("%d\n ",
ptr1->data);
}
//main program which takes in values and calls the function:
int main()
{
int n, p;
cin>>n>>p;
int m=p+1;
gameOfElimination(m, n);
return 0;
}
SIGABRT is generally issued when there are memory issues (heap corruption being quite common). In your code, I see only the new() operator being called, but you aren't deleting any unused nodes from your linked list! Seems like you're exhausting the memory allocated to your process.
You might be running out of memory. Check your ram usage during the execution of your program, that might lead to something.
enter code here
#include<bits/stdc++.h>
using namespace std;
class Node{
public:
int data;
Node *next;
};
void traverse(Node *head)
{
while (head != NULL)
{
/* code */
cout<<head->data<<"->";
head = head->next;
}
cout<<"NULL"
}
int main()
{
Node *head = new Node();
Node *second = new Node();;
Node *third = new Node();;
Node *fourth = new Node();;
head->data = 5;
head->next = second;
//cout<<head->data;
second->data=10;
second->next=third;
third->data = 15;
third->next = fourth;
fourth->data = 20;
fourth->next= NULL;
traverse(head);
return 0;
}```

Counting occurrence in singly linked list by nodes

I am writing a simple app that gets a list and saves the objects as nodes in a singly linked list and we can add(), remove(), copy(), etc. each node depending on the given data set. each node has a char value which is our data and an int count which counts the occurrence of the related char.
e.g. for a list like
a, a, b, b, c, a
there would be three nodes (since there are three different characters) which are:
[a,3,*next] -> [b,2,*next] -> [c,1,*next] -> nullptr
bool isAvailable() checks if the data is already in the list or not.
Q: When inserting a data there are two options:
The data has not been entered: so we have to create a newNodewith the given data, count=1and *next=NULL.
The data is already entered: so we have to count++ the node that has the same data.
I know if the given data is available or not, but how can I point to the node with same data?
Here's the code:
#include "stdafx.h"
#include<iostream>
using namespace std;
class Snode
{
public:
char data;
int count;
Snode *next;
Snode(char d, int c)
{
data = d;
count = c;
next = NULL;
}
};
class set
{
private:
Snode *head;
public:
set()
{
head = NULL;
tail = NULL;
}
~set();
void insert(char value);
bool isAvailable(char value);
};
set::~set()
{
Snode *t = head;
while (t != NULL)
{
head = head->next;
delete t;
}
}
bool set::isAvailable(char value)
{
Snode *floatingNode = new Snode(char d, int c);
while(floatingNode != NULL)
{
return (value == floatingNode);
floatingNode->next = floatingNode;
}
}
void set::insert(char value)
{
Snode *newNode = new Snode(char d, int c);
data = value;
if (head == NULL)
{
newNode->next = NULL;
head = newNode;
newNode->count++;
}
else
{
if(isAvailable)
{
//IDK what should i do here +_+
}
else
{
tail->next= newNode;
newNode->next = NULL;
tail = newNode;
}
}
}
I know if the given data is available or not, but how can I point to the node with same data?
You'll need to start at the head of the list and iterate along the list by following the next pointers until you find the node with the same data value. Once you've done that, you have your pointer to the node with the same data.
Some other notes for you:
bool set::isAvailable(char value)
{
Snode *floatingNode = new Snode(char d, int c);
while(floatingNode != NULL)
{
return (value == floatingNode);
floatingNode->next = floatingNode;
}
}
Why is this function allocating a new Snode? There's no reason for it to do that, just initialize the floatingNode pointer to point to head instead.
This function always returns after looking at only the first node in the linked list -- which is not the behavior you want. Instead, it should return true only if (value == floatingNode); otherwise it should stay inside the while-loop so that it can go on to look at the subsequent nodes as well. Only after it drops out of the while-loop (because floatingNode finally becomes NULL) should it return false.
If you were to modify isAvailable() slightly so that instead of returning true or false, it returned either floatingPointer or NULL, you'd have your mechanism for finding a pointer to the node with the matching data.
e.g.:
// Should return either a pointer to the Snode with data==value,
// or NULL if no such Snode is present in the list
Snode * set::getNodeWithValueOrNullIfNotFound(char value) const
{
[...]
}
void set::insert(char value)
{
Snode * theNode = getNodeWithValueOrNullIfNotFound(value);
if (theNode != NULL)
{
theNode->count++;
}
else
{
[create a new Snode and insert it]
}
}
You had a lot of problems in your code, lets see what are they:
First of all, Snode doesn't need to be a class, rather you can go with a simple strcut; since we need everything public.(not a mistake, but good practice)
You could simple initialize count = 1 and next = nullptr, so that no need of initializing them throw constructor. The only element that need to be initialized through constructor is Snod's data.
Since c++11 you can use keyword nullptr instead of NULL, which denotes the pointer literal.
Member function bool set::isAvailable(char value) will not work as you think. Here you have unnecessarily created a new Snode and cheacking whether it points to nullptr which doesn't allow you to even enter the loop. BTW what you have written in the loop also wrong. What do you mean by return (value == floatingNode); ? floatingNode is a Snode by type; not a char.
Hear is the correct implementation. Since we don't wanna overwrite the head, will create a Node* pointer and assign head to it. Then iterate through list until you find a match. If not found, we will reach the end of the isAvailable() and return false.
inline bool isAvailable(const char& value)
{
Node *findPos = head;
while(findPos != nullptr)
{
if(findPos -> data == value) return true;
else findPos = findPos->next_node;
}
return false;
}
In void set::insert(char value), your logic is correct, but implementation is wrong. Following is the correct implementation.(Hope the comments will help you to understand.
void insert(const char& value)
{
if(head == nullptr) // first case
{
Node *newNode = new Node(value);
newNode->next_node = head;
head = newNode;
}
else if(isAvailable(value)) // if node available
{
Node *temp = head;
while(temp->data != value) // find the node
temp = temp->next_node;
temp->count += 1; // and count it by 1
}
else // all new nodes
{
Node *temp = head;
while(temp->next_node != nullptr) // to find the null point (end of list)
temp = temp->next_node;
temp = temp->next_node = new Node(value); // create a node and assign there
}
}
Your destructor will not delete all what you created. It will be UB, since your are deleting newly created Snode t ( i.e, Snode *t = head;). The correct implementation is as bellow.(un-comment the debugging msg to understand.)
~set()
{
Node* temp = head;
while( temp != nullptr )
{
Node* next = temp->next_node;
//std::cout << "deleting \t" << temp->data << std::endl;
delete temp;
temp = next;
}
head = nullptr;
}
Last but not least, the naming (set) what you have here and what the code exactly doing are both different. This looks more like a simple linked list with no duplicates. This is however okay, in order to play around with pointers and list.
To make the code or iteration more efficient, you could do something like follows. In the isAvailable(), in case of value match/ if you found a node, you could simply increment its count as well. Then in insert(), you can think of, if node is not available part.
Hope this was helpful. See a DEMO
#include <iostream>
// since you wanna have all of Node in public, declare as struct
struct Node
{
char data;
int count = 1;
Node* next_node = nullptr;
Node(const char& a) // create a constrcor which will initilize data
: data(a) {} // at the time of Node creation
};
class set
{
private:
Node *head; // need only head, if it's a simple list
public:
set() :head(nullptr) {} // constructor set it to nullptr
~set()
{
Node* temp = head;
while( temp != nullptr )
{
Node* next = temp->next_node;
//std::cout << "deleting \t" << temp->data << std::endl;
delete temp;
temp = next;
}
head = nullptr;
}
inline bool isAvailable(const char& value)
{
Node *findPos = head;
while(findPos != nullptr)
{
if(findPos -> data == value) return true;
else findPos = findPos->next_node;
}
return false;
}
void insert(const char& value)
{
if(head == nullptr) // first case
{
Node *newNode = new Node(value);
newNode->next_node = head;
head = newNode;
}
else if(isAvailable(value)) // if node available
{
Node *temp = head;
while(temp->data != value) // find the node
temp = temp->next_node;
temp->count += 1; // and count it by 1
}
else // all new nodes
{
Node *temp = head;
while(temp->next_node != nullptr) // to find the null point (end of list)
temp = temp->next_node;
temp = temp->next_node = new Node(value);
}
}
void print() const // just to print
{
Node *temp = head;
while(temp != nullptr)
{
std::cout << temp->data << " " << temp->count << "\n";
temp = temp->next_node;
}
}
};
int main()
{
::set mySet;
mySet.insert('a');
mySet.insert('a');
mySet.insert('b');
mySet.insert('b');
mySet.insert('c');
mySet.insert('a');
mySet.print();
return 0;
}

LinkedList creating nodes

I tried to implement C++ singly linked. I have created a method which creates a node and add a value and points to another node but i have to remember index.
How to improve the code and create nodes without remembering index? (I want to maintain order = first created node points to another etc.)
Class method:
void LinkedList::addValue ( int val )
{
if ( ! index )
{
n = new Node();
head = n;
n->value = val;
n->next = NULL;
}
else
{
n->next = new Node( );
n = n->next;
n->value = val;
}
++index;
}
I guess, you already have two member variables: head which is the root node and n which is the last node. You should initialize both of them with NULL (nullptr for c++11) in constructor. Then you can just check if n==NULL when you add a new value to the list.
LinkedList::LinkedList():head(NULL),n(NULL)
{}
void LinkedList::addValue ( int val )
{
if (n==NULL)
{
n = new Node();
head = n;
n->value = val;
n->next = NULL;
}
else
{
n->next = new Node( );
n = n->next;
n->value = val;
}
}
The index variable, however, can be useful if you want to find the list size in one fast read operation without iterating over all its nodes.
You can create another pointer called Tail to point to the last element. That way you can add value to the list without the index.
I call this method append
void append(int val){
void append(int val) {
Node* tmp = new Node(); // creating a temporary pointer to a new node
tmp -> value = val
last -> next = tmp; // connect the new node to the linked list
last = tmp; // set the last to the newly created node
listSize++; // increase the size of the list
}
You can also improve the code by making a Constructor for the node:
Class Node{
public:
int value;
Node * next;
Node(Node * nextEle = NULL) {
next = nextEle;
}
Node(int val,Node * nextEle = NULL) {
value = val;
next = nextEle;
}
}

"lvalue required as left operand of assignment" error writing a linked list

I am currently learning some C++ for a course I am taking in school. I have basic understanding of lvalues and rvalues, but I am unable to determine why I am receiving a compiler error.
I am creating a singly linked list and need to be able to reverse it. As per my assignment I have two classes. The first is the node and just holds an int as well as a pointer.
class Node {
int data;
Node *next;
public:
//Constructor
Node(int d) {
data = d;
next = NULL;}
//Set to next Node
void SetNext(Node *nextOne) {
next = nextOne;}
//Returns data value
int Data(){return data;}
//Returns next Node
Node *Next() {return next;}
};
Then I have a linked list class that has a header pointer and then a number of functions for adding, printing etc. the list.
class LinkedList {
Node *head;
public:
//Constructor
LinkedList(){head = NULL;}
void AddNode(int d) {
//Create a new Node
Node *newNode = new Node(d);
//Create a temporary pointer
Node *temp = head;
//If there are already nodes in the list
if(temp != NULL) {
//Parse through to the end of the list
while(temp->Next() != NULL) {
temp = temp->Next();}
//Point the last Node in the list to the new Node
temp->SetNext(newNode);
}
//If adding as the first Node
else{
head = newNode;}
}
void PrintList() {
//Temporary pointer
Node *temp = head;
//If there are no nodes in the list
if(temp == NULL) {
std::cout << "The list is empty" << std::endl;}
//If there is only one node in the list
if(temp->Next() == NULL) {
std::cout << temp->Data() << std::endl;}
//Parse through the list and print
else {
do {
std::cout << temp->Data();
temp = temp->Next();
}
while(temp != NULL);
}
}
//Returns the number of nodes in the list
int CountList() {
//Temporary pointer
Node *temp = head;
//Counter variable
int counter = 0;
//If the list is empty
if(temp == NULL) {
return counter;}
//Parse through Nodes counting them
else {
do {counter++;
temp = temp->Next();
}
while(temp != NULL);
}
return counter;
}
//Reverses the list
Node *ReverseList() {
//Initially set to NULL then tracks the new head
Node *marker = NULL;
//Tracks the next one in the list
Node *nextOne;
//Sets the first Node to NULL and then sets the last Node to point to
//the first one and rotates through the list pointing the last to the
//first
while(head != NULL) {
nextOne = head->Next();
head->Next() = marker;
marker = head;
head = nextOne;
}
//Setting the head back to the start again
head = marker;
}
};
One of those functions is supposed to reverse the list. The line "head->Next() = marker;" in the ReverseList function is causing a "lvalue required as left operand of assignment" error when compiling.
Any insight as to why this is occurring and how I can correct the problem?
Thank you in advance!
The return from the call to Next() is an rvalue. As you are in a class function, you don't need to call the Next function to get at the private next pointer, you can just use it directly.
head->next = marker;
Your Next() function returns a pointer, and you then do this:
head->Next() = marker;
You're changing the pointer to marker and not what it's pointing at. To solve this you need to dereference that pointer:
*head->Next() = marker;
your signature for next is:
Node *Next() {return next;}
This makes a copy of next pointer at return and hence it is treated as r-value and not l-value.
One way of overcoming this would be to use a pointer-to-pointer:.
Node **Next() {return &next;}
And then use it as:
int main()
{
Node* marker=new Node(89);
Node* nod=new Node(9);
*(nod->Next())= marker;
cout<<(nod->next)->data<<endl;
cout << "Hello World" << endl;
return 0;
}
This makes it more complicated to use.