I have this C++ class with an array of Node objects called adj (I guess you don't need to see the implementation of my Node class)
class Graph {
public:
Node *adj;
bool *marked;
int nVertex, p;
int *distance;
void graph(int quantity);
bool is_marked();
void cleaner();
void newVertex(int value);
};
And I have this method which creates a node nod and tries to store it in the p-th position in adj:
void Graph::newVertex(int value)
{
Node *nod = new Node(value);
adj[p++] = nod;
}
When I try to compile this code I get the following error message:
invalid conversion from 'Node*' to 'int'
I can't see what I have done wrong in my code. The array initialization looks right to me and the object assignment too. Please help me answer this question.
UPDATE: the code for the Node class:
class Node {
public:
int value, cost;
Node *next;
Node() {}
Node(int val) {
value = val;
next = NULL;
cost = 0;
}
};
UPDATE: I can't use C++ vector here. I'd love to but it's for a homework thing. Before anyone thinks I am cheating or something, please note that I'm not asking for a solution to my specific assigned problem, but instead to a problem that I am having for compiling the code.
The type of adj[p++] is clearly Node& and you try to assign a Node* to it. I guess, your Node type has a constructor taking an int and the compiler tries but fails to convert the Node* to an int.
You probably meant to declare adj as
std::vector<Node*> adj;
... and then add new nodes using, e.g.:
adj.push_back(nod);
(note, that you still need to make sure the allocated objects get released at the appropriate point in time).
adj is of type Node*. adj[someIndex] is then of type Node. You are trying to assign Node* to Node. My educated guess is, you have Node::operator=(int), so the compiler tries to interpret your code that way - but that doesn't work out either, producing the error message you observe.
After you have created your new Node:
Node *nod = new Node(value);
you need to hook it up to your linked list. A linked list looks like:
[HEAD] => [value|next] => [value|next] => NULL
where HEAD in your case would be adj.
Therefore, you need to update the next of your new node to point to the current head node, then update the head node to point to the new node.
That is, you should end up with something like:
adj => [value|next] => [value|next] => ... => NULL
^ ^
nod adj'
where adj' is the old value of adj.
It helps to create diagrams of what the data structure looks like and how the values are being updated.
You then need to work out how to traverse the nodes in the list.
Also, don't forget to clean up the nodes in the Graph destructor (and be careful how you do that).
OK, with the definition of the Node class in hand I think I can see what you're trying to do. If I'm correct, you want to have Graph::adj point to a linked list of Node elements, with each Node then pointing to the next Node in the list. If that's correct the implementation of new_vertex needs to look something like:
void Graph::newVertex(int value)
{
Node *nod = new Node(value);
nod->next = adj;
adj = nod;
}
No need to have an index (p) - you'd just walk the linked list of Node elements with code similar to
Node *n = adj;
while(n != NULL)
{
// do something useful with n
n = n->next;
}
If you really insist upon using array syntax to access elements of the linked list (bad idea in my mind, as it just adds to the potential confusion, but YMMV) you could add something like
Node *operator[](int n); // 0-based index into Node list
to Graph with an implementation similar to
Node *operator[](int ndx)
{
Node *n = adj;
for( ; n != NULL, ndx > 0 ; ndx--)
n = n->next;
return n;
}
Share and enjoy,.
Related
I am trying to create a maze that consists of Nodes objects. Each Node object has a member variable Node *attachedNodes[4] that essentially contains all of the attached Nodes that will later tell the program the options it has when it is doing a breadth first search. Every time I think that I understand pointers, another issue like this comes up, and I feel lost all over again. Especially since it was working fine (as far as I knew) until I changed something that I thought was unrelated. Anyways, here is where the issues are:
My Node object looks like this
class Node {
public:
...
void attachNewNode(Node *newNode, int index);
...
private:
...
Node *attachedNodes[4];
...
};
My function to attach the Nodes looks like this:
void Node::attachNewNode(Node *newNode, int index) {
*attachedNodes[index] = *newNode;
}
And then lastly, the part of the other function that is calling the attachNewNode function looks like this:
int mazeIndex = 0;
while (inStream.peek() != EOF) {
int count = 0;
Node n;
Node m;
...
if (System::isNode(name2)) {
m = System::findNode(name2);
}
else {
m = Node(name2);
maze[mazeIndex] = m;
mazeIndex++;
}
Node *temp;
*temp = m;
n.attachNewNode(temp, count); //The error usually happens here, but I added the rest of the code because through debugging it is only consistently in this whole area.
count++;
}
n.setNumberUsed(count);
}
Sorry that this got a little lengthy, but I've been searching all over this portion that I have provided trying to figure out what is wrong, but it would be nice to have someone that knows a little more about pointers give their input on the matter. The Node class was given to me, but everything else I made, so basically any of that could be changed. Thanks in advance for the help.
Your class contains a property:
Node *attachedNodes[4];
The above says that attachedNodes is an array that contains 4 pointers to Nodes. In your attachNewNode function, you do:
*attachedNodes[index] = *newNode;
This means that you are trying to assign value of newNode (as * dereferences the pointer) to the value of the element under attachedNodes[index]. What you probably want is:
attachedNodes[index] = newNode;
This means that you just want to store the address (as pointer is just an address to some place in memory) in the array of addresses.
There is also another error here:
Node *temp;
*temp = m;
n.attachNewNode(temp, count);
Again, you are interested in storing the address of node m. In order to do that, you need to get the said address:
Node *temp;
temp = &m;
n.attachNewNode(temp, count);
These are the most obvious problems with the above code, but there might be more.
I am trying to implement a Linked ArrayList in C++ for instruction purposes, I've hit a snag though and I'm unsure how to unsnag it. My pointer array doesn't seem to be composed of pointers, but of actual objects.
Keeping my code as brief as possible.
//arraylist.h//
class classArrayList {
private:
class Node {
Node();
//accessors
};
Node* classArray;
public:
classArrayList();
};
//arraylist.cpp//
classArrayList::classArrayList() {
Node* node = new Node();
this->setHead(node);
this->setMaxSize(5);
classArray = new Node[5];
this->classArray[0] = *node;
this->setSize(1);
}
void classArrayList::deleteNode( int index ) {
Node* my_current = &this->classArray[index];
//blahblah
}
But when I go to delete a node, "my_current" doesn't link to whatever would be next or prev in this list. Trying to delete at position zero, no next.
So there's definately a node with data but it doesn't have its links, but checking the debugger my linked list is fine and works, so its whatever the array is pointing to that's screwing up.
So instead of pointing to the list, its pointing to unique instances, how can I fix this?
My code to add something new to the array is: this->classArray[some_index] = *new_node;
To clarify, I wanna be able to have an array that points sequencially to each object in my linked list. And then when I ask for one at any n in my arraylist, reference it to a pointer and then do thins to the object in my list through its position in the array, rather than increment through the list until I find the nth one I want.
Make your classArray a double pointer and create a Node pointer array. Node* classArray; Copy the address of head of your list to each array.
classArray = new Node*[5];
In your code by your statement this->classArray[0] = *node; you are not storing the address of the newly created, instead content of newly created node. And by deleting you are not removing the dynamically created list head.
For copying the address of newly created list you should use
this->classArray[0] = node;
The code works as it should. When you delete a node from your linked list, you delete the data under the pointer. As you set my_current to the address of the deleted node, you actually don't point to anything. The problem doesn't lie in the code, but in your understanding of the subject.
In order to really make a working linked list, every node should consist of a pointer to the next node. That way, when you delete a node, you'll first be able to retrieve the next node from the pointer, and set your my_current to a valid address.
In order to solve your problem, you should actually read a bit about the subject.
If you want to access the elements in "array style", overload the operator [].
Node& classArrayList::operator [](unsigned int index)
{
Node *node = head;
for(unsigned int i=0;i<index;i++)
if(node->next()) node = node->next();
else break;
return *node;
}
I am done with insertion, search in circular linked list but for removal I am getting compiler errors...
Following is my structure for nodes.
struct node
{
int p_data;
struct node* p_next;
node(node* head, int data)
{
p_next = head;
p_data = data;
}
explicit node(int data)
{
p_next = nullptr;
p_data = data;
}
};
node* remove_circular(node* head, node* target)
{
if (head == target->p_next)
{
delete head;
return nullptr;
}
auto next_pointer = target->p_next;
target->p_data = next_pointer->p_data;
target->p_next = next_pointer->p_next;
delete target->p_next;
return target;
}
and in main function I call
head = remove_circular(head, head);
head = remove_circular(head, temp);
this is to remove head element and another element that temp points to.
But I am getting errors
Anybody has any idea to remove one element from circular list??
I changed it to delete target->p_next;
but now it deletes everything in the list.
Any idea???
This is how a circular linked list works:
Each node points to the next in line, and the tail of the list points to the header node. That's the difference from a circular linked list to a regular linked list (which, in the case above, would make 37 point to a terminator null).
In the case of your list having only one object, then it should look something like this:
So, as you can see, there is no object pointing to null anywhere, yet it happens on your code with your explicit constructor (which will run if I write node n = node(12)).
I suggest you take a look at this link to have a better understanding of how your algorithm should look like.
Once you resolve your compiler error, you are still going to have algorithmic issues. I suggest you draw a circular list on paper and think about the steps required to remove an element. Consider all the cases, for example: empty list, list of 1 item, element not in the list, etc.
You need to consider several things.
1.) the case of an empty list
if(head == nullptr){//Empty list case
return nullptr;
}
2.) The target to be removed is the head node and this is the only node in the list.
if (head == target && target->p_next == head){
create a temp node with the data value of target
target = nullptr;//Since nothing points to target now it is for all intents and purposes deleted from the list but the data is still there so you can do something with it. I assume this is necessary because you return a node *.
return the temp node
}
3.) Create a loop that iterates through the entire list. You have something that would only delete the next node which works if you have a two item list and target was the second item.
auto next_pointer = head->p_next;//could not be target->p_next as this assumed
while (next_pointer->p_next != target){//This while loop traverses the list rather than just deleting the next entry.
4.)Inside you loop add a check to see if the list has been traversed and target was never found.
if (next_pointer->p_next == head){
return nullptr;
}//end IF
5.) Inside the loop add the else case which means target was in an arbitrary location in the list. Since I gave you the rest I'll leave you to get this part. It's not hard just a few lines longer than the statements above.
I have a basic linked list problem that I have attempted to solve below. I would appreciate any inputs on my approach, correctness of the algorithm (and even coding style). The problem calls for a function that deletes all occurrences of an int in a circular linked list and returns any node from the list or NULL (when the list is null).
Here's some C++ code that I have so far:
struct Node{
Node* next;
int data;
};
Node* deleteNode(Node* &node, int num){
if(!node){
return NULL;
}
Node* given = node;
Node* del;
while(node->next != given){
if(node->next->data == num){
del = node->next;
node->next = node->next->next;
delete del;
}
node = node->next;
}
//Check if the first node needs to be deleted, with variable node pointing to last element
if(given->data == num){
node->next = given->next;
delete given;
}
return node;
}
The delete node; should be delete del;.
Also, use Node* node as parameter, instead of Node* &node which will prevent non-lvalues from passing in.
p.s. Forgot a semicolon after struct definition? :)
Without following all your logic I can see at a glance this code cannot work.
You are checking for the input list being empty and that's the only case in which your code returns NULL. But what happens if you are passed a list in which all elements must be deleted?
This problem also has a subtlety in it. To check if you completed a circular list you need to compare to the first address to see if you got linked back to the start. However if this element has been deleted then by C++ standard you're not even allowed to use its address in a comparison.
To avoid making two passes over the elements to be deleted one possible trick is to "break the loop" when starting iteration so you can check for NULL instead of checking for the address of the starting node.
Which of these is a more correct way to store the first object in a linked list?
Or could someone please point out the advantages/disadvantages of each. Thanks.
class Node
{
int var;
Node *next;
static Node *first;
Node()
{
if (first == NULL)
{
first = this;
next = NULL;
}
else
//next code here
}
}
}
Node* Node::first = NULL;
new Node();
-- OR --
class Node
{
int var;
Node *next;
Node()
{
//next code here
}
}
Node* first = new Node();
The latter is definitely preferable. By making the first node pointer a static class member, you are basically saying that there will only be a single linked list in your whole program.
The second example lets you create several lists.
The first example has the definite drawback of only being able to create a single linked list in your entire program, so I wouldn't do that.
The second works fine, but doesn't shield the user of the class from how the linked list works. It would be better to add a second class, for example named LinkedList, that stores the 'first' pointer and performs list management.
Even better, you could use std::list instead.
It's most usual to have a separate List class and a separate Node class. Node is usually very simple. List holds a pointer to the first Node and implements the various list operations (add, remove, find and so on).
Something like the following
class List
{
public:
List()
{
first = new Node();
}
void insert(int val);
void remove(int val);
// ... and so on
~List()
{
// ... clean up
}
private:
struct Node
{
int val;
Node* next;
Node(int val_ = 0, Node* next_ = 0)
: val(val_), next(next_)
{}
};
Node* first;
};
Note that you can place Node outside List if you want to, but this usually doesn't make much sense.
Presumably you may have more than one list? In which case, the static option is a non-starter.
You definitely don't want the "first" to be a static. This implies there's only one linked list in your entire program. static means that every Node in every linked list in your entire program has the same beginning.
That being said you want your Node to have the fewest responsibilities-- It make sense for it to store its value and be able to get to the next Node. It adds complexity to add the job of1 maintaining the "first" pointer. For example what happens when you insert a new element at the beginning? Then you'd have to update everyone's "first" pointer. Given the two choices above I'd chose the second choice.
I would furthermore add a third choice. Add a "linked list" wrapper that gave you easy access to "first", "last" and allow you to easily insert into and iterate through the list. Something like:
class LinkedList
{
Node* First;
Node* Last;
public:
Node* GetFirst() {return First;}
Node* GetLast() {return Last;}
// insert after "where"
void Insert(Node* where, Node* newNode);
...
}
Not uselessly limiting your code to a single list instance is one very good argument for code variant 2.
However, just from superficially looking at the two examples, the sheer number of lines of code also gives a good indication that variant 2 has merits over variant 1 by being significantly shorter.