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;
Related
I'm trying to speed up a python routine by writing it in C++, then using it using ctypes or cython.
I'm brand new to c++. I'm using Microsoft Visual C++ Express as it's free.
I plan to implement an expression tree, and a method to evaluate it in postfix order.
The problem I run into right away is:
class Node {
char *cargo;
Node left;
Node right;
};
I can't declare left or right as Node types.
No, because the object would be infinitely large (because every Node has as members two other Node objects, which each have as members two other Node objects, which each... well, you get the point).
You can, however, have a pointer to the class type as a member variable:
class Node {
char *cargo;
Node* left; // I'm not a Node; I'm just a pointer to a Node
Node* right; // Same here
};
Just for completeness, note that a class can contain a static instance of itself:
class A
{
static A a;
};
This is because static members are not actually stored in the class instances, so there is no recursion.
No, but it can have a reference or a pointer to itself:
class Node
{
Node *pnode;
Node &rnode;
};
Use a pointer, & better initialized:
class Node {
char * cargo = nullptr;
Node * left = nullptr;
Node * right = nullptr;
};
Modern C++
It is a better practice to use smart-pointers (unique_ptr, shared_ptr, etc.), instead of memory allocations by 'new':
#include <string>
#include <memory> // For 'std::unique_ptr'
class Node {
public:
std::string cargo;
std::unique_ptr<Node> left;
std::unique_ptr<Node> right;
};
int main()
{
auto bt = std::make_unique<Node>();
(*bt).cargo = "Coffee";
(*bt).left = std::make_unique<Node>();
}
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.
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 have the following code snipped, which implements a Binary Search Tree with templates:
#include<iostream>
using namespace std;
template<typename T>
class Node{
public:
T data;
Node<T> *left;
Node<T> *right;
Node<T> *parent;
Node(T input_data=NULL){
data=input_data;
left=NULL;
right=NULL;
parent =NULL;
}
};
template<typename T>
class BinarySearchTree{
private:
long n;
Node<T> *root;
public:
BinarySearchTree(Node<T> *input_root=NULL, long input_size=0){
n=input_size;
root=input_root;
}
void insert(Node<T> *p=root, T data){
Node<T> *par=NULL;
while(p!=NULL){
par=p;
if(data <= p->data)
p=p->left;
else
p=p->right;
}
Node<T> *z=new Node<T>(data);
if(root==NULL){
root=z;
n=1;
return;
}
z->parent=par;
if(data<=par->data)
par->left=z;
else
par->right=z;
n+=1;
}
void inorder(Node<T> *p=root){
if(p){
inorder(p->left);
cout<<p->data<<" ";
inorder(p->right);
}
}
int main(){
BinarySearchTree<int> *t=new BinarySearchTree<int>();
t->insert(5);
t->insert(15);
t->insert(3);
t->insert(14);
t->insert(25);
t->insert(10);
t->inorder();
}
There's a compilation error on line 27, (i.e. Node *root;), and which reads: "Invalid use of non-static data member 'BinarySearchTree::root'". I think it has to do with the default arguments that I've included have in the functions 'insert' and 'inorder', because I don't get the error when I remove the default argument 'root'.
My question is, what is happening and how do I get around it? I would like to preserve the default argument of root if that's possible.
If it matters, I'm using a software called 'Quincy 2005' on Windows 8.1 to compile (for certain reasons).
A default value must be a literal, not a variable name.
Additionally, arguments with default values must come last in the argument list.
Rather use:
void insert(Node<T> *p, T data) { ... }
// overload with only one argument
void insert(T data)
{
insert(root, data)
}
In a line such as
void insert( Node<T>* p = root ,T data ) {...}
there are 2 errors.
Firstly ,you can only use default value for the arguments starting at the last parameter and backwards.
Since you didn't give data a default value ,this is an error (solution reorder parameters ,those without default must come first).
Secondly ,the value root is a member of this and there is no this at the point of declaration.
Solution if you need a default there use nullptr as the default and inside your function test for nullptr and if so use root instead.
template <class Type>
class Node
{
public:
Node ()
{
}
Node (Type x, Node* nd)
{
data = x;
next = nd;
}
Node (Type x)
{
data = x;
next = NULL;
}
~Node (void)
{
}
Node (const Node* & nd)
{
data = nd->data;
next = nd->next;
}
Node & Node::operator = (const Node* & nd)
{
data = nd->data;
next = nd->next;
}
T data;
Node* next;
};
Do I replace every Node* with
Node*<Type>
I tried replacing it and tried running something like
Node* temp = myq.head;
but it says argument list for class template "Node" is missing. I'm not really sure how to work with Templates when I need the Node class itself being part of it
Every declaration of Node will need a type in <>.
For
Node* temp = myq.head;
it depends on what myq.head is defined as. If it's defined as Node<int>* then temp also has to be defined as Node<int>* temp. You always have to have the <> with template objects.
If you wanted to have Node* without knowing the type, you could use inheritance. Have a templated TypedNode class that inherits from a non-template Node class. You would be able to pass all those TypeNode<> objects around with Node*, but you wouldn't be able to get the value of the nodes back out without knowing their type.
I don't recommend this but If you really want to make nodelists with mixed types you'll need to track the types by either
Include an enum type in the base class that defines the type stored in the node, and define typedNode for each class, setting the enum in it's constructor, or returning it from a virtual method.
RTTI, Run Time Type Information http://en.wikipedia.org/wiki/Run-time_type_information