Trying to design a simple linked list. Node declared as such:
class Node
{
public:
friend class CRevList;
Node() {m_next = 0; m_prev = 0;}
Node(const T &t) {m_payload = t; m_next = 0; m_prev = 0;}
T Data() {return m_payload;}
const T Data() const { return m_payload; }
private:
Node *m_next;
Node *m_prev;
T m_payload;
};
So m_next points to the next item in the list and m_payload holds its value. m_head is declared as this:
private:
Node m_head; // Head node
Incomplete function to put a new node at the front of the list with payload t:
void PushFront(const T &t)
{
Node *newnode = Node(t);
m_head.m_next = newnode;
}
The above should declare a new node with a payload of t, and set the m_head's next node to the new node. I'm not yet linking it to the rest of the list, just want to get at least 1 node working.
int GetFirst() //get value of first item in list.
{
Node *firstnode = m_head.m_next;
int payload = firstnode->m_payload;
return payload; //m_head.m_next->m_payload;
}
This is trying to get the first node in the list, fetch it's payload, and return... which gives a Seg Fault 11 error.
I'm pretty sure it's a problem with how I'm doing the pointers, and I have a general understanding of them, but having read documentation I'm still not sure how to approach the error.
Thanks!
Solved with the help of Jonathan Wakely:
PushFront needed to be
Node *newnode = new Node(t);
Additionally, there was an problem trying to access the private variable with
int payload = nextnode->m_payload;
I needed to use the public method
int payload = nextnode->Data();
Related
When I call the default constructor for my class LinkedList I attempt to assign values to the head node of the linked list before any other operations occur. I have isolate the error, via debugging, to the instructions in the default constructor. As soon as
head -> next = NULL;
head -> RUID = 0;
head -> studentName = "No Student in Head";
are called the program crashes. This occurs when I call the default constructor in main.
Here is my class declaration and my struct declaration along with the default constructor:
struct Node
{
string studentName;
int RUID;
Node* next;
};
class LinkedList
{
private:
// Initialize length of list
int listLength;
public:
// Head of the list, which points to no data yet
Node *head;
LinkedList();
bool insertNode(Node* newNode, int position);
int generateRUID();
};
LinkedList::LinkedList()
{
head -> next = NULL;
head -> RUID = 0;
head -> studentName = "No Student in Head";
listLength = 0;
}
I believe this all of the relevant code to this issue. If someone could shed light on this it would be much appreciated.
LinkedList::head is a Node*, not a Node and you don't initialize it, so the object (binary, in-memory) representation is undefined and is therefore dangerous to dereference.
Change your LinkedList to explicitly initialize the head member. I recommend storing it by-value (as Node) rather than as a heap-allocated value (Node*) for simplicitly, unless you know you'll need to reparent nodes.
Using Node*:
LinkedList::LinkedList() :
head( Node() ),
listLength( 0 )
{
this->head->next = nullptr;
this->head->RUID = 0;
this->head->studentName = "No Student in Head";
}
I have a question about a function that adds a creates/adds a new node to the top of the list. Here is the set up.
A head is created in the main program. We set the list to Null
IntNode* head = new IntNode(3,NULL);
My question is about the function that adds a node to the top of the list. Assumes that there is at least one node in the list.(the one we just created)
void headInsert(IntNodePtr& head, int theData)
{
head = new IntNode(theData, head);
}
I know it creates a new node and makes the pointer already declared in the main program, which is passed, point to the new node. However I am confused about he "head" part on the parameter in the constructor(not the headInsert function). I am confused about what exactly is being passed when we pass head in the IntNode constructor above. That head sets the variable link, to point to what head is pointing to correct? ******My question is, Does it first set *link(the class variable) to point to what head is pointing to, in this case the node with the number 3 whose list points to NULL, AND THEN makes head point to the new NODE? So in other words the right part of the assignment is done first? I'm just very confused as to what is being passed in when we create the new node.
class IntNode
{
public:
IntNode( ) {}
IntNode( int theData, IntNode* theLink)
: data(theData), link(theLink) {}
IntNode* getLink( ) const { return link; }
int getData( ) const { return data; }
void setData( int theData) { data = theData; }
void setLink(IntNode* pointer) { link = pointer; }
private:
int data;
IntNode *link;
};
void headInsert(IntNodePtr& head, int theData)
{
head = new IntNode(theData, head);
}
The evaluation of the sides of the assignment -
head
and
new IntNode(theData, head)
is not ordered at all, but prior to performing the assignment, both sides have been evaluated completely.
Since neither side modifies the value of head, the results are the same regardless of the order of evaluation.
I have one semestral work (own double linked list) and our teacher want this definition of class DoubleList:
template <typename T> //just part of all methods
class DoubleList {
public:
DoubleList(void); //We HAVE TO follow this definitions
void AddFirst(const T &); //const!
T &AccessActual(void);
T RemoveFirst(void);
}
My question is, how can I define a node? AddFirst have const argument and other methods haven't. Data must be set in constructor and then they can't be changed. Is this task so limited or are here other ways to complete the task?
Here is my actual Node:
template <class U>
class Node{
Node<U> * next;
Node<U> * previous;
const U * data;
public:
Node(const U *data){ //
next = NULL;
previous = NULL;
this->data = data;
}
void SetNext(Node<U> *next) {
this->next = next;
}
Node<U> *GetNext(){ return next; }
void SetPrevious(Node<U> *previous) {
this->previous = previous;
}
Node<U> *GetPrevious(){ return previous; }
const U *GetData() { return data; }
};
In containers, it's usually better to have a copy of the data so change const U * data; to U data;
The Node constructor would be easier to use if it had this signature Node(const U& data). No pointers.
The GetData would also have to change. Return a reference. U& GetData().
It is dangerous to hold addresses of data items. If the user of the lists wants that functionality he can use a list that stored pointers (e.g. U=int*)
Your node class seems fine, although i would keep using template argument T instead of U, right now it is confusing.
Your AddFirst() method should simply create a new node and assign the correct next pointer to the new node and the correct prev pointer to the "old" first node and adjust the actual object? what does that refer to?
Your interface of nodes differs from this one returning a reference instead of a pointer. I find it quite strange that the AccessActual can always return an object, while when the list is empty this can be a nullptr??
example implementation:
void AddFirst(const T &)
{
Node<T>* newNode = new Node<T>(T);
Node<T>* current = &AccessActual(); // how can there be an actual when the list can be empty or is that impossible?
{
while( current.GetPrev() != nullptr )
{
current = *current.GetPrev();
}
current.SetPrev(newnode);
newnode->SetNext(current);
}
}
I am trying to create a function that adds a node to the end of a LinkedList. I know how to do it using loops, but my professor wants it done a certain way and I don't understand why it's not working. He practically gave us all the code for it..
This is the pseudo-code he gave us:
process append(data)
if (not the end)
next->append(data);
else
next=new Node();
next->data=data;
next->data = nullptr;
And this is what I came up with:
struct Node {
int data;
Node* next;
};
struct LinkedList {
Node* head;
LinkedList() {head = nullptr;}
void prepend(int data) {
if (head == nullptr) {
Node* tmp = new Node();
tmp->data=data;
tmp->next=nullptr;
}
else {
Node* tmp = new Node();
tmp->data=data;
tmp->next=head;
head=tmp;
}
}
void append(int data) {
Node* tmp = head;
if (tmp->next != nullptr) {
tmp=tmp->next->append(data);
}
else {
tmp->next = new Node();
tmp->next->data = data;
tmp->next->next = nullptr;
}
}
};
int main()
{
LinkedList LL = LinkedList();
LL.prepend(7);
LL.append(6);
std::cout << LL.head->data << std::endl;
}
My prepend (to add to the beginning of the LinkedList) works fine, but when I try this code, I get
main.cpp:48:20: error: 'struct Node' has no member named 'append'
tmp->next->append(data);
So I'm pretty sure that there's something wrong with saying next->append(data), which from what I understood, is supposed to be recursively calling back the append function until it reaches a nullpointer. I'm thinking maybe there's some sort of way to write it, but people in my class are telling me that the next->append(data) thing SHOULD work, so I guess I'm not exactly sure why this isn't doing anything. I tried instead writing the append function in the Node struct, but then it says that head wasn't declared in the scope and I really just don't know how to work with this. I'm also sort of new to classes/structs in C++ so I'm assuming it's something about that that I'm not understanding.
The class Node has not any method named append so you get that error message:
tmp->next->append(data);
^^^^^^^^^^^^^
struct Node {
int data;
Node* next;
};
To append a node to a linked-list, you don't need an append method within Node. Remove that. Correct the append process in LinkedList::append:
void append(int data) {
Node* tmp = head;
while (tmp->next)
tmp = tmp->next;
tmp->next = new Node();
tmp->next->data = data;
tmp->next->next = nullptr;
}
I did't test, but you need something like above code. At first, it tries to access to the end of list. Then it appends a node.
Recursive implementation:
void append(int data) {
append(data, head);
}
void append(int data, Node *node) {
if (node->next)
append(data, node->next);
else {
tmp->next = new Node();
tmp->next->data = data;
tmp->next->next = nullptr;
}
}
Your append method isn't defined on the Struct Node. Instead it's defined on the LinkedList class so you need to invoke it accordingly. You can redefine the append method to take a node as a parameter or add an append method to the Struct Node itself. Also there's no need to assign the result of append to tmp =
Your append method is void.
tmp->next is a Node, so to call append function, you must declare it in Node struct
Like this
struct Node
{
void append(int data)
{
if (next)
next->append(data);
else
{
next = new Node();
next->data = data;
next->next= nullptr;
}
}
int data;
Node* next;
};
it's clear from the pseudo code next->append(data); that append is meant to be a member of Node.
Here's how you might use Node::append from LinkedList::append
class LinkedList {
void append(int data) {
if (head == nullptr) {
head = new Node();
head->data=data;
head->next=nullptr;
}
else {
head->append(data);
}
}
}
The node structure does not contain any append method.
Moreover, you are splitting work that can be done in one methos to two methods, writing more code.
See my answer to another question here with working code I wrote
https://stackoverflow.com/a/37358192/6341507
As you can see, I solve all in method
AddItem(int i)
I start seeing that creating linked list i kindof har for many people here, so I will further edit my answer there to provide additional information.
Good luck!
Here is code in which I am trying to implement a queue using linked list:
#include <iostream>
#include <cstdlib>
using namespace std;
template <class Item>
class Queue{
public:
struct node{
Item item;node *next;
node (Item x){
item=x; next=0;
}
};
typedef node* link;
link head, tail;
public:
Queue(int){ head=0;}
int empty() const { return head==0; }
void put(Item x){
node* t=tail;
tail=new node(x);
if (head==0) head=tail;
else t->next=tail;
}
Item get(){
Item v=head->item;link t=head->next;
delete head; head=tail return v;
}
};
int main(){
return 0;
}
but I have problems with pointers. For example, when I write Item v = head-> it should show me option to choose item but it does not show. Also in other place of code after -> this sign code does not give me possibility to choose item or next. Please help.
ON: The -> operator can be overloaded so the development environment cannot be sure what to do with it. You can do the following (temporarily or permanently) if you really want to have auto-completion.
// IMPORTANT. Make sure "head" is not null before you do it!
Node &headNode(*head); // Create a reference
headNode.next = tail; // Use TAB or CTRL+SPACE or whatever here after dot
OFF: I reviewed your code and made some corrections
template <class Item>
class Queue {
public:
Queue()
: head(0)
, tail(0)
{ }
bool empty() const { return head==0; }
void put(const Item& x)
{
Node* t = tail;
tail = new Node(x);
if (head==0)
head = tail;
else
t->next = tail;
}
Item get()
{
Item v = head->item;
Link t = head->next;
delete head;
head = t;
if(head==0)
tail = 0;
return v;
}
private:
struct Node {
Item item;
Node *next;
Node(const Item& x)
: item(x)
, next(0)
{}
};
typedef Node* Link;
Link head,tail;
};
Removed int typed nameless parameter from Queue constructor
Renamed node to Node and link to Link because Item is Item, not item. Just to make it somewhat standardized
Initializing tail at the constructor of Queue.
Using initializer list instead of code where possible.
Fixing Queue::get(), setting tail to zero if the queue become empty.
Using constant reference in parameter lists of Queue::put() and Queue::Node::Node()
Node, Link, head and tail is private from now.
Queue::empty() returns bool instead of int from now.
You would probably be better off reusing an existing container.
The STL explicitly contains, for example, a queue Container Adapter (based on deque by default, which is the most efficient choice).
If you don't need polymorphic behavior, a std::queue<Item> is what you're looking for, it's both extremely efficient (more than your custom list-based queue) and you will avoid memory management issues.
If you need polymorphic behavior, then use a std::queue< std::unique_ptr<Item> >.