I'm trying to build a nested linked list in C++ (pretty new to C++).
The node in the list could be an integer value or another linked list that has all integer values.
I have gone through other posts on SO, and I understand I should use a union for multiple data types for the node data type.
This is what I have until now.
class linkedList {
private:
struct node {
union data {
int val;
linkedList* list;
};
data currData;
node* next; // a pointer which will point to the next node
}*p;
My question is how do I start allocating the list pointer within the node struct.
For val, I know I can do p->currData->val =5, for example.
I wouldn't use a union. I would just keep a value for each and a typefield of some sort so you know what it is.
class LinkedList {
public:
class Node {
LinkedList * list = nulptr;
int value = 0;
Node * next = nullptr;
};
};
In this case, if list is nullptr, then it's not a node pointing to a new list. Or you could explicitly add a type, but for something this simple, I probably wouldn't.
p->value = 5;
Related
here i simply wanted to print the elements of the linked list i created but it is printing the list in REVERSE order. looks like there is a mistake in the code.help me solve it
push function adds node to linked list every time we input element to be inserted in linked list.I've passed reference of head and data. A node gets dynamically created every time push fuction called. I am using c++ here.
#include<iostream>
using namespace std;
class node{
public:
int data;
node* next;
};
//creating linked list
void push(node** head_ref,int new_data) //passing address of head and data to put in list
{
node* new_node=new node(); //new node created
new_node->data=new_data; //data inserted
new_node->next=*(head_ref);
*(head_ref)=new_node;
}
int main()
{
node* head=NULL;
int n;
cin>>n; //number of elements in linked list
for(int i=0;i<n;i++)
{
int val;
cin>>val;
push(&head,val); //push function which creates a linked list
}
//while loop for printing elements of linked list
while(head!=NULL)
{
cout<<head->data;
head=head->next;
}
return 0;
}
What you currently do is assigning each node to be the predecessor of the current head, so in the end your head will be the latest element you added , its successor the second last element, its successor the third last element etc. and thus resulting to a reversed list.
You should assign the new node as successor of the current "head", like this:
void push(node** tail_ref,int new_data) //passing address of tail and data to put in list
{
node* new_node=new node(); //new node created
new_node->data=new_data; //data inserted
(*tail_ref)->next= new_node;
*(tail_ref)=new_node;
}
Note that I renamed head_ref to tail_ref in the snippet above, which better describes what the pointer actually represents: a pointer to the current last element of the list, hence the tail of the list.
Of course, you will need to save the pointer to the first element. Otherwise you won't be able to iterate through your linked list.
Extension to Simon's answer, which is correct so far:
You already have a class 'node' – why not create a class 'list' or 'linked_list' as well:
class LinkedList
{
node* m_head = nullptr;
node* m_tail = nullptr;
};
Now you always have head and tail combined and don't need to store them separately. Note that in above example, they are both private. That's actually how you should design your class. If you don't, then you allow a user to break the list implementation from outside (someone might, for instance, just set one of these pointers to nullptr, producing a memory leak in case of head).
However, now you will have to provide appropriate means to access and modify the list:
class LinkedList
{
public:
void append(int new_data); // as Simon proposed
void prepend(int new_data); // your implementation
int head();
int tail();
void dropHead();
//void dropTail(); // is an O(n) operation with singly linked list, though!
private:
node* m_head = nullptr;
node* m_tail = nullptr;
};
The node class is very closely linked to your list, you might consider not letting it be a stand-alone class, but making it a nested class instead. There's yet quite a bit to add (e. g. how to iterate over the list). To get some hints I recommend to peek a bit into STL and get familiar with the concept of iterators.
Finally: Stop re-inventing the wheel. STL already provides fully implemented doubly (std::list) and singly (std::forward_list) linked lists. It's fine to experiment with an own implementation to get to know how the winds blow, but once you know, switch back to STL.
So as a novice programming I am trying to learn data structures and a question came in my mind while I was working on Binary trees. So the code/function to add a node to binary tree is:
//binary tree node addition
struct tree* addnode(int rdata)
{
struct tree* temp = new tree();
temp->data = rdata;
temp->right = NULL;
temp->left = NULL;
return temp;
}
Here we can see that there is only one parameter required in the addition of node i.e. we don't pass the root address in the function. But in addition of linked list the addition of node is at any place (Beginning, ending or after k nodes) has two parameters which are a headref pointer of linked list and the data value. Like code for adding a node in the starting of the linked list is :
void addatstartLL(struct LL** headref, int rdata) {
struct LL* temp = new LL();
temp->data = rdata;
temp->next = (*headref);
(*headref) = temp;
}
The above two codes are applied like this :
#include<iostream>
using namespace std;
struct LL {
int data;
struct LL* next;
};
struct tree {
int data;
struct tree* left;
struct tree* right;
};
int main()
{
struct tree* root = new tree();
root->data = 1;
root->left=addnode(2);
struct LL* head = NULL;
addatstartLL(&head, 2);
}
So, my question here why do we need only one parameter in binary tree (only data and not the root address cause) and two parameters in linked list i.e. headref and data? Why don't we write the same kind of function for both of the data structures? Thank you in advanced.
TLDR They are badly written functions.
Those functions are what you make them to be. If you make one take one argument and the other take 2 arguments then that's what it is. They are not standard functions and they are not well written functions either (in terms of both interface and implementation).
There are many problems with the code you have:
addnode doesn't actually add a node to a list. It just creates a node. That's why it takes one argument.
LL structure doesn't represent a linked list. It represents a node.
You use owning raw pointers everywhere so there is no clear owner of the memory allocated by new. You code will leak at the first exception, even if you explicitly delete the nodes. That's why you need to religiously follow RAII concept in C++.
struct tree* root = new tree(); There is absolutely no reason to dynamically allocate tree there in main. tree root{} would suffice.
structures are used in the most minimalist way possible, just the bare C capable way. In C++ - true C++ - you would use constructors, encapsulation, methods and so on.
This is by far not idiomatic, correct C++ code. It's C code (sprinkled with C++ IO) and compiled with a C++ compiler. If that's what your teacher requires then by all means write this for him/her to make them happy, but be aware that it's definitely not how you write correct, clean, idiomatic, modern C++ code. If you lean this from a tutorial or book then ditch it immediately and learn from a good C++ resource.
Your first function doesn't add a node to a tree. It creates a new tree of one node.
It can be used by a function that adds a node to a tree, once the location to add it is determined.
Your second function is adding a node to a list at a specific position. Comparable tree functions would be
void addnodebefore(tree** root, int rdata)
{
tree* temp = new tree();
temp->data = rdata;
temp->right = *root;
temp->left = nullptr;
*root = temp;
}
void addnodeafter(tree** root, int rdata)
{
tree* temp = new tree();
temp->data = rdata;
temp->right = nullptr;
temp->left = *root;
*root = temp;
}
There are STL containters similar to what you have, std::set is usually implemented as some type of sorted tree, while std::list is usually implemented as a circular doubly linked list with a dummy node used for the head and tail of the list.
To add a new element to std::set, std::set::insert(value) can be used, and it is a single parameter call.
To add a new element to std::list, std::list::push_front(value) or std::list::push_back(value) can be used, and they are single parameter calls.
Although these are single parameter calls, the container itself could be considered to be similar to having a second parameter. In other words, you could create static functions (not tied to a specific instance of a container) for insert, push_front, or push_back, that would take an instance of the container as one the parameters.
I'm trying to pass in a head node to a function that recursively deletes everything from the LLL. But I'm not very good with classes. I've got one class for the LLL data called Node, and another called NodeList which manages all of the nodes.
The problem is that I can't access the private fields and I don't know how to get them in there. Because I don't want them public like a struct.
C++ Having trouble with syntax, so a class can pass data to other classes I've checked this link which said to make sure to have in the NodeList class Node * head, but I already have that.
C++ passing private data to other private functions in a class And I checked this one, but it was way over my head for the little C++ I know. Also I think this was just a pass by refrence issue.
This isn't the whole thing by the way, just the classes and the one function.
class NodeList
{
public:
NodeList();
~NodeList();
//this should delete the whole list
void delList(NodeList * head);
private:
//head
NodeList * head;
};
//this is the nodestructkindathing
class Node
{
public:
Node();
~Node();
private:
//next pointer
Node * next;
int data;
};
void NodeList::delList(NodeList * head)
{
if (!head)
return;
delList(head->next);
delete head;
}
NOTE: I changed delList and Node * head in the class to become NodeList * head and now I only recieve one error.
error: ‘class NodeList’ has no member named ‘next’
As suggested by Some programmer dude, make NodeList a friend of Node. When class A declares class B to be a friend, B can see and interact with the private members of A. Note that the reverse is not true. friendship is one way. A cannot see the private members of B unless B declares A to be a friend.
This one change will solve all of the problems asked in the question.
The rest of this code dump is to make writing a linked list a little easier for you. Linked lists are best considered a rite of passage for programmers. You'll find you rarely use them in real life programming, but they serve as a notorious weeder of CS students. Practically no one gets them right the first time or two. They require a moderate amount of care and attention to book keeping. Pen and paper step-by-step drawings of the list and the interactions you wish to perform on the list are highly recommended to help visualize and debug a linked list.
You may also find delving into pointers to pointers extremely helpful. For example, see the Alternative Using Pointer To Pointer section of this linked answer.
Comments embedded where needed.
#include <iostream>
class Node
{
friend class NodeList; // NodeList, and no one else, can now see the private
// members of Node
public:
// Node must be given a value and it not given a next, it's automatically NULL
// this makes it almost impossible to not point link at something useful,
// eliminating the most common of the trivial linked list bugs
Node(int value, Node * link = nullptr);
~Node(); //if it doesn't do anything. Get rid of it. See the Rule of Zero
private:
//next pointer
Node * next;
int data;
};
class NodeList
{
public:
NodeList();
~NodeList();
//this should delete the whole list
void delList(Node * head);
private:
//head
Node * head;
};
Node::Node(int value, Node * link) : next(link), data(value)
{
// test code
std::cout << "Node data = " << data << " next = " << next << '\n';
}
Node::~Node()
{
// test code
std::cout << "~Node data = " << data << '\n';
}
NodeList::NodeList()
{
// test code to give delList something to delete
head = new Node(1,new Node(2,new Node(3)));
}
NodeList::~NodeList()
{
delList(head);
}
//this is the nodestructkindathing
void NodeList::delList(Node * head) // watch out! Parameter head shadows member head!
{
// Warning: This function is recursive and a potential stack-killer if given a
// long list. Prefer iteration here unless given a reason to do otherwise
// and guarantees on maximum list length
if (!head)
return;
delList(head->next);
delete head;
}
int main()
{
NodeList test;
}
Expected output:
Node data = 3 next = 0
Node data = 2 next = 0x2ec6cc0
Node data = 1 next = 0x2ec6ce0
~Node data = 3
~Node data = 2
~Node data = 1
A discussion of the Rules of Three, Five and Zero. Understanding these rules is a must if you want a stable linked list or to program non-trivial systems in C++.
Documentation on friend.
Normally, I would just input head = new Node in main, which would set everything up, but the stipulation is that I do not have permission to mess with global variables. This is an assignment where I only have access to main, and due to other backend features, I have to leave the global variables intact so I can't overwrite it with head = new Node.
The point is just to add characters to a linked list. I just hardcoded inserting one just as an example, but I still can't avoid the error.
Is there a correct way to add them?
struct Node{
char key;
Node *next;
};
Node *head = NULL;
int main(){
char x = 'a';
cout<<x<<endl;
head->key=x;
}
assignment:
Find all nodes in a BST that are between a given range of values. Then build a linked list of the values and the list should be in ascending order.
NOTE: the head of the linked list is declared globally in the back end and its initial value is NULL. Just add the nodes to the linked list using head. The printing of the linked list will also be done in the backend. Helper functions can be used.
void RangeSearch(TreeNode *node, char m, char n);
Head is just a pointer, pointing to NULL. There is no real object / memory allocated for Node. You have first to allocate memory for it.
In your assignment, you can and should (as far as i understand it) add nodes to linked list, so you will have to allocate new nodes .
struct Node {
char key;
Node *next;
};
Node *head = NULL;
int main() {
char x = 'a';
head = new Node();
cout << x << endl;
head->key = x;
delete head;
return 0;
}
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.