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);
}
}
Related
Trying to make a B inary S earch T ree (BST for short) using a template.
When I try to create a new instance of my BST I get an unexpected error. I hope the solution does not involve pointers since I would like to keep them at a minimum.
For now I have:
template <typename Type>
class BST { // The binary search tree containing nodes
private:
BSTNode<Type> *root; // Has reference to root node
public:
BST ();
bool add (int, Type);
};
And the Node type:
EDIT: When I cut out code to un-encumber text, I forgot the constructor, now it's been added
template <typename Type>
class BSTNode { // Binary Search Tree nodes
private:
int key; // we search by key, no matter what type of data we have
Type data;
BSTNode *left;
BSTNode *right;
public:
BSTNode (int, Type&);
bool add (int, Type);
};
EDIT2: Here is the actual constructor
template <typename Type>
BSTNode<Type>::BSTNode (int initKey, Type &initData) {
this->key = initKey;
this->data = initData;
this->left = NULL;
this->right = NULL;
}
I want to try and test if anything works / doesn't work
BSTNode<int> data = new BSTNode (key, 10);
And I get: Expected type specifier before BSTNode. I have no idea what I'm doing wrong, but one thing I do hope is I don't have to use data as a pointer.
BSTNode<int> data = new BSTNode<int> (key, 10);
Also does not work, seems it believes < int > is < & int> and it doesn't match
First, you need to fully specify the type on the RHS of the assignment, and, since you are instantiating a dynamically allocated node with new, the LHS should be a pointer:
BSTNode<int>* data = new BSTNode<int> (key, 10);
^ ^
If you don't need a node pointer, then use
BSTNode<int> data(key, 10);
Second, your BSTNode<T> class doesn't have a constructor taking an int and a Type, so you need to provide that too.
template <typename Type>
class BSTNode {
public:
BSTNode(int k, const Type& val) : key(k), data(val), left(0), right(0) { .... }
};
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.
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();
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
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> >.