Implement iterator of a circular list - c++

I'm trying to implement a class of Circular List with a nested class of iterator and I wrote like this:
template <class T>
class CircularList {
struct Item {
T data;
Item* next;
};
Item* head;
int size;
public:
CircularList() {
head = new Item();
head->next = head;
}
int sizeList() { return size; }
void push(T data) {
Item* i = new Item();
i->data = data;
i->next = head->next;
head->next = i;
size++;
}
class CircularListIterator {
Item* p;
CircularListIterator() {
p = head->next;
}
bool hasNext() {
if(p->next != head) {
return true;
}
return false;
}
T next() {
T data_temp = p->data;
p = p->next;
return data_temp;
}
};
CircularListIterator* iterator() {
return new CircularListIterator();
}
};
int main() {
CircularList<string>* letters = new CircularList<string>;
letters->push("d");
letters->push("c");
letters->push("b");
letters->push("a");
Iterator<string>* it= new Iterator<string>;
it = letters->iterator();
while (it->hasNext()) {
cout<< it->next() << "," << endl;
}
return 0;
}
But the Iterator is not working when I try to create an iterator in the main function, It said that it wasn't declared in the scope and has no member of it.

Assuming by "in the main class" you mean in the main function, the problem is quite straightforward: you're trying to construct a ::Iterator<string>, but there is no class in the global namespace (or anywhere else, in this code sample) called Iterator! You could try constructing a CircularList<string>::CircularListIterator - that's at least a class that exists - but it wouldn't work because the iterator needs to be associated with a CircularList object for it to be able to access member variables like head.
The correct thing to do here is to promote the iterator function - the one that returns a CircularListIterator* - out of the CircularListIterator class and into the CircularList class. Then, in your main function, you can call letters->iterator() and it'll return a CircularListIterator* for the letters object.
Now, CircularListIterator doesn't inherit from any other iterator classes - neither the (nonexistent-in-this-code Iterator you've typed it as, nor the C++ std::iterator or any of its variants) - so you can't assign it to it or probably even compile the code that references Iterator. To make CircularListIterator a subclass of std::iterator, you'll need to extend std::iterator<Category, T> with the appropriate category. See https://www.cplusplus.com/reference/iterator/iterator/ for more information on the std::iterator class template, including an example of implementing it.

Related

Circular double linked list with smart pointers in c++

Is it possible to create a circular doubly-linked list using smart pointers in C++
struct Node {
int val;
shared_ptr<Node> next;
weak_ptr prev;
};
shared_ptr<Node> head;
But this will have a circular reference of shared pointers and thus not deallocate correctly.
Make the circular linked list a class itself (with whatever operations you need to build it, like append). Have its destructor break the link by setting tail->next = nullptr. It should not matter which link you break, so if you're not using a head and tail, just set any one of them nullptr, and you're good.
In my testing, I made a circular linked list, and the nodes did not destruct. Then at the end, I added tail->next = nullptr before it exited, and all the destructors fired correctly.
My original posted answer was rather light on details. This one gives a proper explanation of how you can achieve a circular linked list without a memory leak and still adhere to the Rule of Zero. The answer is basically the same, using a sentinel, but the mechanism is a little more involved than I had originally let on.
The trick is to use a sentinel type that behaves just like a list node, but in fact does not really have a shared pointer to the head of the list. To achieve this, the node class should be separated into a behavior object and a state object.
class NodeState {
std::shared_ptr<Node> next_;
std::weak_ptr<Node> prev_;
int value_;
NodeState (int v) : value_(v) {}
NodeState (std::shared_ptr<Node> p) : next_(p), prev_(p) {}
//...
};
class Node {
virtual ~Node () = default;
virtual NodeState & state () = 0;
std::shared_ptr<Node> & next () { return state().next_; }
std::weak_ptr<Node> & prev () { return state().prev_; }
int & value () { return state().value_; }
void insert (const std::shared_ptr<Node> &p) {
//...
}
};
Now, you can define a node implementation and a sentinel implementation.
class NodeImplementation : public Node {
NodeState state_;
NodeState & state () { return state_; }
NodeImplementation (int v) : state_(v) {}
//...
};
class NodeSentinel : public Node {
List &list_;
NodeSentinel (List &l) : list_(l) {}
NodeState & state () { return list_.sentinel_state_; }
};
The list itself contains a NodeState used by the sentinel object. Upon initialization, the list creates a sentinel object and initializes its state.
class List {
//...
NodeState sentinel_state_;
std::shared_ptr<Node> head () { return sentinel_state_.next_; }
std::shared_ptr<Node> sentinel () {
return std::shared_ptr<Node>(head()->prev());
}
//...
public:
List () : sentinel_state_(std::make_shared<NodeSentinel>(*this)) {}
//...
void push_front (int value) {
head()->insert(std::make_shared<NodeImplementation>(value));
}
void push_back (int value) {
sentinel()->insert(std::make_shared<NodeImplementation>(value));
}
//...
};
So, what does this organization do? It avoids the issue of a circular reference by using a sentinel node to act as the break. While the tail of the list points to the sentinel object, the sentinel object itself does not point to anything. Instead, it uses the state of the list itself to determine its next and previous neighbors.
Thus, the circular shared pointers only persists as long as the list exists. Once the list is destroyed, Item A loses its reference, and via the domino effect, Sentinel itself will be destroyed.
A fundamental point is that the sentinel object itself must never be exposed to the user of the list interface directly. It should remain internal to the list object at all times. It essentially represents end() in an STL like container, and logically, it can never be removed from the list (until the list itself is destroyed). In practice, this means removal operations on the list need to exit early if the passed in iterator represents the sentinel.
Demo
Try It Online
It is also possible to define a member function next() which can select between a shared or weak pointer.
#include <iostream>
#include <memory>
using namespace std;
struct T {
int n_;
shared_ptr<T> next_;
weak_ptr<T> weaknext_;
T(shared_ptr<T> next, int n) : next_(next), n_(n) {};
auto next() {
if (next_ == nullptr)
return shared_ptr<T>(weaknext_);
return next_;
}
~T() { cout << n_ << "ok\n"; }
};
int main() {
auto p0 = make_shared<T>(nullptr, 1);
auto p1 = make_shared<T>(p0, 2);
auto p2 = make_shared<T>(p1, 3);
p0->weaknext_ = p2; //makes the list circular
auto p = p2;
for (int i = 0; i < 5; ++i) {
cout << p->n_ << "\n";
p = p->next();
}
}

How to return pointer from linked list (in Class Template)

I've stumbled upon a problem with my linked list class.
I've one abstract class Shape and multiple classes inheriting from it, like Square or Triangle etc.
I'm storing them in my List class but I don't know how to return stored object back to the pointer of Shape.
Since my explanation may seem pretty vague here is some code with expected behaviour explained.
class Shape // abstract class
{
public:
int a;
//some member virtual methods
};
class Square : public Shape
{
//using the virtual methods from Shape
};
In my main file, this is how I want to use it:
int main()
{
List<Shape*> ShapeList;
Shape *ptr;
Square a(2, 1, 1); // size, x, y coordinates
ShapeList.add(ptr);
//up to this point everything works well
// now I want my list to return a pointer to it's member
// so I can modify it
Shape *listptr;
listptr = ShapeList.findInstanceAt(0); // here's my error
listptr->a = 5; // what I want to do next
}
So as you can see I'm havingtroubles with returning proper value from my list and I don't know how to solve this.
Here's my simplified list implementation:
template <class T> class Node
{
T data;
Node *next;
public:
inline T getData()
{
return data;
}
inline Node* getNext()
{
return next;
}
};
template <class T> class List
{
Node<T> *head, *tail;
public:
List() : head(NULL), tail(NULL) { }
T* findInstanceAt(int _k)
{
if (NULL == head)
{
cout << "\nList is empty.";
return NULL;
}
else
{
Node<T> *temp = new Node<T>;
temp = head;
for (size_t k = 0; k < _k; ++k)
{
if (NULL != temp->getNext()) temp = temp->getNext();
else return NULL;
}
return temp->getData;
}
}
}
Thanks in advance for any suggestions on how to make this work.
#EDIT
Ahh I forgot to add compiler errors that I'm getting:
Error 1 error C2440: '=' : cannot convert from 'Shape **' to 'Shape *'
Do you want to store Shapes or pointers to Shapes in the list? And do you want the findInstanceAt to return the node in the list or a pointer to the node in the list? At the moment you are not consistent on these things
You store Shape* nodes in the list but the findInstanceAt returns a pointer to the node - which is a Shape** object. This is what the compiler is complaining about
You probaly need to chang
T* findInstanceAt(int _k)
to
T findInstanceAt(int _k)

Deleting all from trie tree

I always seem to get in trouble when I'm deleting all nodes from a tree. I am trying to release all the memory I allocated when creating a trie tree.
I am suppose to create a function remove_all
Is it enough to delete just the "root"
something like this:
void PrefixStringSet::remove_all(NodePtr node)
{
delete root;
}
Or do I have to delete each node with something like this:
void PrefixStringSet::remove_all(NodePtr node)
{
if(!root)
{
return;
}
remove_all(root->children);
delete root;
}
Obviously neither of these are working or I wouldn't be here :).
Other question. Do I have to call the remove_all function in my main function if my destructor is implemented like this
PrefixStringSet::~PrefixStringSet()
{
remove_all(root);
}
Or does the destructor automatically delete the trees/nodes I create?
Edit
struct TrieNode
{
TrieNode(bool present = false);
bool is_leaf();
bool present;
TrieNode* children[ALPHABET_SIZE];
};
class PrefixStringSet
{
public:
// Creates an empty prefix string set.
PrefixStringSet();
~PrefixStringSet();
bool insert(string s);
bool contains(string s);
private:
NodePtr root;
void remove_all(NodePtr node);
};
typedef TrieNode* NodePtr;
Deleting only root is not enough: when deleting a root, you should check whether its children aren't empty, and if they are not empty, recursively delete them. C++ doesn't have garbage collector to do the work for you :)
If your remove_all method is within the destructor of the wrapper object, then you don't have to call it separately.
You should write a remove method in all classes you want to delete at runtime.
So you can delete a tree with little care about garbage collection.
It's easy to use pointer in this way:
class a
{
public:
a(){}
~a(){remove();}
init(int v){
var = new int;
*var=v; }
remove(){delete var;}
private:
int *var;
};
class b
{
public:
b(){}
~b(){remove();}
init(int v){
var = new a;
var->init(v); }
remove(){
var->remove();
delete var; }
private:
a *var;
};
To answer your question: No, deleting root is not enough.
edit: sry i made a mistake at a:init(). I forgot to derefer the pointer.
In Cpp:
void deleteAll(Node* curNode) {
for (int i = 0; i < 26; i++) {
if (NULL != curNode->child[i]) {
deleteAll(curNode->child[i]);
}
}
delete curNode;
}
deleteAll(root);

C++ linked list implementation

i am working on an assignment where i am asked to implement a linked list in c++. so far everything is working great except for when i am creating a new list. in my method create_list(). after i assign content and an id number to my Field and try to call GetNext() i get an error saying: Request for member 'GetNext()' in 'Node' which is a non-class type '*Field'. I'm still new to the C++ syntax and object oriented programming. What am I doing wrong? I thought by using the line Field *Node = new Field(SIZE, EMPTY); that my variable Node would be of class type Field...?
#include <iostream>
#include <ctype.h>
using namespace std;
typedef enum { EMPTY, OCCUPIED } FIELDTYPE;
// Gameboard Size
int SIZE;
class Field {
private:
int _SquareNum;
FIELDTYPE _Content;
Field* _Next;
public:
// Constructor
Field() { }
// Overload Constructor
Field(int SquareNum, FIELDTYPE Entry) { _SquareNum = SquareNum; _Content = Entry; }
// Get the next node in the linked list
Field* GetNext() { return _Next; }
// Set the next node in the linked list
void SetNext(Field *Next) { _Next = Next; }
// Get the content within the linked list
FIELDTYPE GetContent() { return _Content; }
// Set the content in the linked list
void SetContent(FIELDTYPE Content) { _Content = Content; }
// Get square / location
int GetLocation() { return _SquareNum; }
// Print the content
void Print() {
switch (_Content) {
case OCCUPIED:
cout << "Field " << _SquareNum << ":\tOccupied\n";
break;
default:
cout << "Field " << _SquareNum << ":\tEmpty\n";
break;
}
}
}*Gameboard;
here is my create_list() method:
void create_list()
{
int Element;
cout << "Enter the size of the board: ";
cin >> SIZE;
for(Element = SIZE; Element > 0; Element--){
Field *Node = new Field(SIZE, EMPTY);
Node.GetNext() = Gameboard; // line where the error is
Gameboard = Node;
}
}
. is used for addressing members in objects and references to objects. Node, however, is a pointer to an object. So you need to turn it into a reference before you can use it with .. This means doing (*Node).GetNext(). Or you can use the shorthand: Node->GetNext() - these two are exactly equivalent.
A good mnemonic to use is that you use the pointy operator with pointers :)
No in the declaration
Field *Node = new Field(SIZE, EMPTY);
Node is of type pointer to Field.
The fix is simple if you have a pointer to a class and you want to access a member of that class use ->.
Node->GetNext() = Gameboard;
I think your code has other errors, and I don't think that even with this 'fix' it's going to work. Probably what you really want is
Node->SetNext(Gameboard);
You're calling Node.GetNext(), but Node is a pointer. You need to use the -> operator instead of the . operator, as in Node->GetNext().
The function must returns a reference value if you want to set as a l-value.
You code need some changes:
// Get the next node in the linked list
Field& GetNext() { return *_Next; }
then you can use the function as a l-value
Node->GetNext() = *Gameboard;

Mixing abstract classes and templates, a recipe for disaster?

I'm having problems with the following situation. I have three classes that are involved in this mixup. List, ListNode, City. I have a List<City *>, where the list will be made up of a set of ListNode<City *> (standard wrapper around the list nodes).
City is an abstract class, so there are several classes that inherit from it that could be placed in this list and accessed polymorphically. The List class has a getHead() method which returns a pointer to a ListNode that is the head.
Any city has a population, so to access the populations, I'd expect the following to work. It's not, thus my question. I broke it down into pieces to make it simpler along the way:
ListNode<City *> *head= country->city_list->getHead();
City *headnode = *head->getNode();
cout << "Test: " << headnode->getPopulation() << endl;
getPopulation() returns an integer. country is defined as List<City*> *city; Any help on how I could figure out my problem would be greatly appreciated.
edit adding more code for better idea of what I'm working with. First, ListNode:
template <class T>
class ListNode
{
public:
ListNode() {next = 0;node = 0;};
ListNode(T *t) {node = t; next = 0;};
ListNode(const ListNode &l)
{
//long copy constructor. snip.
};
T *getNode() const { return node; }
ListNode *getNext() const { return next; };
private:
T *node;
ListNode *next;
};
Now, here is what might relevant in the List class..
template <class T>
class List
{
public:
List()
{
head = 0;
size = 0;
};
List(ListNode<T> *t)
{
head = t;
size = 1;
};
List(T *t)
{
head = new ListNode<T>(t);
size = 1;
};
List(const List<T> &t)
{
// long copy constructor. snip.
};
//bunch of irrelevent methods.
ListNode<T> *getHead() const {return head;};
List &operator+=(T &t)
{
this->insert(&t);
size++;
return (*this);
};
private:
List &insert(T *t)
{
ListNode<T> *current = head;
if (current == 0)
{
head = new ListNode<T>(t);
}
else
{
while (current->getNext() != 0)
{
current = current->getNext();
}
current->setNext(new ListNode<T>(t));
}
return (*this);
};
ListNode<T> *head;
int size;
};
I have a hunch that the process of inserting might be the problem. I insert with the List class's += operator, shown in the List implementation above. It calls the private insert method shown above, as well. It looks like this:
City *somecity = new City(x,y,z); //some parameters. integers.
*city_list += somecity; // where city_list is a List.
I think you've got a variable scoping problem.
Your ListNode class contains a pointer to the node value. Your ListNode constructor takes in a pointer to the node value and saves it.
The problem is if that pointer is to a local variable that then goes out of scope. Your ListNode's node pointer is now pointing to an object that doesn't exist. e.g. in this example
addToList(List<int>& myList)
{
int x = 3;
myList += x; // pointer to x is in the list
}
// Out of scope; x no longer exists, but myList has a pointer to it.
// Accessing this node will result in an error.
There are a couple possible remedies:
Have your ListNode contain values rather than pointers. The drawback here is that you will be making copies of the values
Implement ListNode using a reference counted smart pointer which will manager the lifetime of the object.
Well, what you could do is:
ListNode<City *>* head = new ListNode<City*>(country->city_list->getHead());
City* headnode = head->getNode();
cout << "Test: " << headnode->getPopulation() << endl;
It will take the existing City (on the memory) and put it at the head of the List node, and so on.
and if you want to copy them, maybe you could just make this:
ListNode<City *>* head = new ListNode<City*>*(new City(country->city_list->getHead()));
City* headnode = new City(head->getNode());
cout << "Test: " << headnode->getPopulation() << endl;
Hope it will help you.