#include <iostream>
#include <string.h>
namespace forward_circular_linked_list {
typedef struct Node {
std::string data;
Node *nextNode;
}Node;
class ForwardCircularLinkedList {
private:
Node *head;
public:
ForwardCircularLinkedList() : head(nullptr) {}
void AddItem(std::string data) {
Node * newNode = new Node();
newNode->data = data;
if(head == nullptr)
{
head = newNode;
newNode->nextNode = head;
} else{
Node * copyOfHead = head;
while(copyOfHead->nextNode != head)
{
copyOfHead = copyOfHead->nextNode;
}
copyOfHead->nextNode = newNode;// process last node
newNode->nextNode = head;
}
}
void print()
{
Node * copyOfHead = head;
do
{
std::cout<<copyOfHead->data;
copyOfHead = copyOfHead->nextNode;
}while(copyOfHead != head);
}
public:
static void Test() {
ForwardCircularLinkedList list;
list.AddItem("Hello");
list.AddItem(" ");
list.AddItem("World");
list.AddItem("!");
list.print();
}
};
}
here, a do-while is being used to print the elements of the list.
At the current setup, Can I use a while or for loop to print the list?
Note: I am considering do-while
and while
as different looping structures.
Yes, you can use do-while
or a for
loop.
But do-while
is more natural because it checks the condition after the body of code.
You have a circular data structure and (presumably) you want to print each element once.
Doing only one round of circling.
do{...move circulator}while(compare with head)
has the right logic.
CGAL implements "circulators" and does exactly that, it starts from "head" does something and increments the circulator until it is head once again. See https://doc.cgal.org/latest/Circulator/classCirculator.html (scroll to Example).
Note the example also checks for emptyness at start, but probably you want. (In my mind a circular buffer is never empty, but I accept other opinions.)
With while
you have:
Node * copyOfHead = head;
do
{
std::cout<<copyOfHead->data;
copyOfHead = copyOfHead->nextNode;
}while(copyOfHead != head);
With for
you can have
Node * copyOfHead = head;
for(;;){
std::cout<<copyOfHead->data;
copyOfHead = copyOfHead->nextNode;
if(copyOfHead == head) break;
}
or
for(Node * copyOfHead = head;;){
std::cout<<copyOfHead->data;
copyOfHead = copyOfHead->nextNode;
if(copyOfHead == head) break;
}
or
for(Node * copyOfHead = head; ; copyOfHead = copyOfHead->nextNode){
std::cout<<copyOfHead->data;
if(copyOfHead->nextNode == head) break;
}
or (exploiting that the body of the loop evaluates to bool:true)
for(
Node * copyOfHead = head;
std::cout<<copyOfHead->data;
copyOfHead = copyOfHead->nextNode
) if(copyOfHead->nextNode == head) break;
The main advantage of for
is the initialization, but still it is not worth it.
You can of course do the step outside the loop but then you have repeated code, etc.
(NOT RECOMMENDED, it may even have a bug)
Node * copyOfHead = head;
std::cout<<copyOfHead->data;
copyOfHead = copyOfHead->nextNode;
for(; copyOfHead != head ;copyOfHead = copyOfHead->nextNode){
std::cout<<copyOfHead->data;
}
So, there you have, do-while
is exactly what you want for this kind of data structure! and for
(or while-only
) is exactly what you don't want.