I have implemented a fairly simple idea of a double linked list. I don't know what am I doing wrong!
I have tried making the member variables of the node as public but doesn't help. Friend class doesn't help either. What is the nonclass type here?
d_list.h
#include "node.h"
#ifndef NODE_H
#define NODE_H
template<class T>
class d_list{
private:
int list_size;
T* head;
T* tail;
public:
//parametrized Default constructor
d_list(T* h=nullptr, T* t=nullptr):head(h),tail(t){}
//get Head of the List
T* gethead(){return this->head;}
T* gettail(){return this->tail;}
void addnodeastail(T* new_node){
if(this->head==nullptr){
this->head=new_node;//this->head will point towards new_node
this->tail=this->head;
this->list_size=list_size+1;
}
else{
this->tail= new_node;
this->tail->next=new_node->previous;
}
}
};
#endif
'''
node.h
template<class T>
class Node{
private:
Node* next;
Node* previous;
T data;
public:
Node()=default;
Node(T dta):data(dta){}
~Node(){}
};
main.cpp
#include<iostream>
#include"d_list.h"
using namespace std;
int main(){
d_list<int> d1;
cout<<d1.gethead()<<endl;
cout<<d1.gettail()<<endl;
int var=20;
int* n1= &var;
int var2 =40;
int* n2= &var2;
d1.addnodeastail(n1);
d1.addnodeastail(n2);
cout<<d1.gethead()<<endl;
cout<<d1.gettail()<<endl;
return 0;
}
Error which I am receiving is something like
In file included from main.cpp:2:
d_list.h: In instantiation of 'void d_list<T>::addnodeastail(T*) [with T = int]':
main.cpp:14:24: required from here
d_list.h:28:29: error: request for member 'next' in '*((d_list<int>*)this)->d_list<int>::tail', which is of non-class type 'int'
28 | this->tail->next=new_node->previous;
| ~~~~~~~~~~~~^~~~
d_list.h:28:44: error: request for member 'previous' in '* new_node', which is of non-class type 'int'
28 | this->tail->next=new_node->previous;
| ~~~~~~~~~~^~~~~~~~
With
template<class T>
class d_list{
private:
int list_size;
T* head;
T* tail;
you declare that head and tail are pointers to the template type T.
That means for d_list<int> you effectively have
int* head;
int* tail;
That makes no sense, your head and tail pointers should be pointers to the first and last nodes in the list:
Node<T>* head;
Node<T>* tail;
And when adding elements to the list, you need to create new Node<T> instances to hold the data, and add the nodes to the list.
The thing is that head and tail shouldn't be T, but rather node<T>:
Node<T>* head;
Node<T>* tail;
Remember, T is the type of object you want to hold in your list. It has no link associated with it. So if you do a d_list<int> currently as written, the templated code will look something like this:
int* head;
int* tail;
These are not linked to each other, this is just a pointer to an int (or a list of ints if you used something like new). To create a link, you need to use Node so o matter where in memory they are stored, they will have a logical connection. That way, d_list<int> would look something like this instead:
Node<int>* head;
Node<int>* tail;
This will let you use nodes to develop a logically connected list of ints, which is exactly what you want for a linked list.
Related
I have linked list class that implements a node structure, like this:
template<class T>
class LinkedList
{
public:
struct Node {
T value;
Node *next;
};
int Length;
Node *head;
Node *tail;
LinkedList() {
Length = 0;
Node* head = nullptr;
Node* tail = nullptr;
}
};
I tried accessing the node Node structure from the driver file like so:
#include "LinkedList.h"
template<class T>
void foo(LinkedList<T> list) {
LinkedList<T>::Node* a = list.head; // does not work
LinkedList<int>::Node* b = list.head; // works (if T is int of course)
}
Using a template T does not work (it gives me "identifier not found" error message), while directly specifying the correct datatype works. Why is that? Is there a way to avoid the error?
Use typename LinkedList<T>::Node* a = ...
The problem is that not knowing what exactly T is, the compiler can’t be sure LinkedList<T>::Node is indeed a type (LinkedList could be specialized for T so the definition doesn’t help). You need to instruct it to treat it that way.
I was trying to implement generic linked list of objects in C++. But when I fetch the same object twice it gives me different results. I feel it is due to misuse of pointers. Please help me debug.
Here is the Node implementation. I have used pointers for templates since linked list shall contain user defined objects.
template <class T> class Node{
private:
T* value;
Node<T>* next;
public:
Node(T* v){value = v; next = NULL;}
Node(T* v, Node<T>* n){value = v; next = n;}
T* getElement(){return value;}
Node<T>* getNext(){return next;}
};
Here is the implementation for generic linked list.
template <class T> class LinkedList{
public:
Node<T>* head = NULL;
LinkedList(){}
LinkedList(T* value){
Node<T> node(value);
head = &node;
}
Node<T>* getHead(){
return head;
}
void add(T* value){
Node<T> node(value,head);
head = &node;
}
};
Main function:
When I call head of linked list, it gives me 2 different answers. In this code, Complex is a simple class to hold complex objects.
int main(){
Complex c1(1,2); Complex c2(3,4); Complex c3(5,6);
LinkedList<Complex> list(&c1);
list.add(&c2);
cout<<list.head->getElement()->i<<" "<<list.getHead()->getElement()->j<<endl;
cout<<list.head->getElement()->i<<" "<<list.getHead()->getElement()->j<<endl;
return 0;
}
Thanks in advance!!
In LinkedList(T* value) and void add(T* value), you are taking the address of a temporary with head = &node;. As soon as you are out of the scope of that function, head becomes a dangling pointer.
You need to create a new node on the heap so that its lifetime will extend beyond the scope of that function.
Node<T> node = new Node<T>(value);
Don't forget to delete all the nodes you have created in the destructor to avoid memory leaks, or even better, switch to smart pointers instead of raw pointers so the cleanup is done for you.
This is my first time working with any kind of tree. I created a tnode class for my tree and now I'm trying to create the class for the tree itself. However I've gotten a couple errors I can't figure out.
#ifndef Tree_Ntree_h
#define Tree_Ntree_h
// SIZE reprsents the max number of children a node can have
#define SIZE 10
// SEPERATE will allow the program to distinguish when a subtree no longer has children
#define SEPERATOR '#'
#include <iostream>
#include <fstream>
template <typename T>
class tnode{
public:
T value;
tnode *child[SIZE];
tnode() {};
tnode<T> *addChild(T data){
tnode*temp = new tnode;
temp -> value = data;
for (int i=0; i<SIZE; i++)
temp -> child[i] = NULL;
return temp;
}
};
template <typename T>
class Ntree{
private:
tnode<T> *root;
T data;
std::string filename;
public:
Ntree(){ root= NULL;}
Ntree( T data){ *root = data;}
inline T getRoot(){return root;}
My errors are in the last three lines.
In the last line of my code (getRoot), this is the error:
No viable conversion from 'tnode > *' to
'std::__1::basic_string'
In the second to last line and the third to last line (*root = data) (root = NULL) this is the error:
No viable overloaded '='
I don't understand why it is necessary to overload the = operator in this situation.
root is a tnode<T> * and getRoot is returning a T object. The compiler doesn't know how to convert one to the other. You probably just want to return root->value
However, you haven't allocated any space for root and it might be NULL, so you need to determine what to do when it is NULL.
In this line:
Ntree( T data){ *root = data;}
This time you are assigning a T to a tnode<T>, which the compiler doesn't know how to do. You also haven't allocated any memory for root. Instead you probably want todo something like:
Ntree( T data){ root = new T; root->value = data;}
Or better still have a tnode constructor that takes a value.
I've made a basic linked list, the list had originally held integers, I'm trying to change the list to a template class.
My node class is called TLLNode,
TLLNODE.h
#pragma once
template<class T>
class TLLNode{
friend class TLL;
public:
TLLNode(T data);typedef TLLNode<T>* TLLPtr;
private:
TLLNode<T> data;
TLLNode *next;
};
template<class T>
TLLNode<T>::TLLNode(T dataIn) : data(dataIn){
}
template<class T>
using TLLNode<T>* TLLPtr;
and my list class to initialize and implement my functions is called TLL
TLL.h
#pragma once
#include <iostream>
#include"TLLNode.h"
using std::cout;
using std::endl;
template<class T>
class TLL{
public:
TLL();
TLL(const TLL&);
void insert(T);
void display();
~TLL();
private:
TLLPtr head;
TLLPtr newNode;
TLLPtr curr;
int size;
};
template<class T>
TLL<T>::TLL() : head(NULL), size(0){
}
// Not implemented yet
template<class T>
TLL<T>::TLL(const TLL& obj){
}
template<class T>
void TLL<T>::insert(T data){
if (head == NULL)
head = new TLLNode(data);
else{
newNode = new TLLNode(data);
newNode->next = head;
head = newNode;
}
}
template<class T>
void TLL<T>::display(){
curr = head;
while (curr != NULL){
cout << curr->data << endl;
curr = curr->next;
}
}
template<class T>
TLL<T>::~TLL(){
while (head != NULL){
curr = head;
head = head->next;
delete curr;
}
}
I had been using typedef TLLNode* TLLPtr; when the list was of type int, but typedef for templates seems to be illegal.
I've tried a few different ways to get this to work and can't get any solution to work, I came across this post
using, I've tried to use this solution without success, the code seems identical to what I want to do, bar the use of pointers.
I haven't tried the older solution in that post yet, using a struct.
Are either solutions going to work for me and if not is there an alternative?
I realize there's probably mistakes in my code other than the issue I'm discussing, I'd like to try to figure out my own mistakes, so if it's not related to my issue or directly preventing me from proceeding, I'll figure it out when I get to it.
You should define TLLPtr as follows:
template<class T>
using TLLPtr = TLLNode<T>*;
And everywhere in the definition of TLL use TLLPtr<T> instead of just TLLPtr (and also change TLLNode to TLLNode<T>).
Update: I've also noticed that you have TLLNode<T> data; in TLLNode. You can't define a member of the class having the type of class itself, you probably meant T data;.
I'm working on implementing linked list using c++. I created a struct Node inside my LinkedList.h, and try to overload operator in node. But when I compiled, I got this error
Code:
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
class LinkedList{
typedef struct Node{
int data;
Node* next;
} * nodePtr;
//Returns true if the current Node object value is
//less than the parameter Node object value
bool operator < (const Node& node) const {
return this->data < node->data; <--- Unable to resolve identifier data.
};
#endif /* LINKEDLIST_H */
I don't know what I did wrong. Can someone tell me please?!
Thanks!
Although I would do this differently, the problem is that you don't define any place in your class to hold a Node structure. I'm not sure if you were trying for this or not:
class LinkedList{
typedef struct Node{
int data;
Node* next;
} * nodePtr;
Node node; // Added this
//Returns true if the current Node object value is
//less than the parameter Node object value
bool operator < (const Node& node) const {
return this->node.data < node.data;
}
};
It looks like you're trying to access something that doesn't exist. Your LinkedList implementation doesn't have a variable named data.
The simplest fix is to change your operator body:
return this->nodePtr->data < node->data;
However, I would suggest refactoring to have a full separate class for Node; you can put the operator overload in that class.
You pass node as reference so you should use node.data
Remove also the keyword typedef because it makes you only define the type and your list definitively needs a pointer to the first node !
Then you have to update your return to:
return this->nodePtr->data < node.data;