C++ reversePrint Linked List Recursively - c++

Here's the reversePrint function:
void SinglyLinkedList::reversePrint(Node* p)
{
if (p == NULL) {
return;
} else {
reversePrint(p->next);
cout << p->data << " ";
}
}
(i.e: list = 1 -> 2 -> 3 -> 4, print out = 4 3 2 1 )
It will only work if *p initially points to what *head points to, namely the first node 1. However, Node* head is a private member of SinglyLinkedList class thus can't be accessed outside the class. How can I pass a pointer that points to head from main ?
Here's what I'm talking about:
int main() {
SinglyLinkedList *list = new SinglyLinkedList();
list->addNode(1);
list->addNode(2);
list->addNode(3);
list->addNode(4);
Node* p = head; // <---- Xcode says: Use of undeclared identifier 'head'
list->reversePrint(p);
return 0;
}
I tried to point *p to what *head points to from inside the reversePrint method. But, it disrupted the recursion
class SinglyLinkedList {
public:
// constructor
SinglyLinkedList();
// destructor
~SinglyLinkedList();
// public APIs
void print();
void addNode(int number);
void reversePrint(Node* p);
private:
Node* head;
};

Move the member function that works with a Node* to the private section.
Create a public member function that does not take any input. Implement it using the private member function.
void SinglyLinkedList::reversePrint()
{
this->reversePrint(this->head);
}
Call the public member function without the Node* in calling function.
list->reversePrint();

You can define one public method without parameters and another private method with a parameter that is called from the public method. For example
public:
void reversePrint() const { reversePrint( head ); }
private:
void reversePrint(Node* p) const { /*...*/ }

Make void SinglyLinkedList::reversePrint(const Node* p) const private,
and add a public overload void SinglyLinkedList::reversePrint() const which calls reversePrint(head).
Alternatively, you may add getter to head.

Related

Function as argument with default value

I want to create class for binary trees:
struct TreeNode {
explicit TreeNode(int _value) : value(_value) {}
int value = 0;
TreeNode* left = nullptr;
TreeNode* right = nullptr;
};
class BTree {
public:
void Add(int value);
void PrintPostOrder(void (*func)() = print_current);
~BTree();
private:
TreeNode* root = nullptr;
void print_current();
void delete_node();
};
BTree::~BTree() {
PrintPostOrder(delete_node);
}
My idea - for destructor and for Printing I need to do binary tree traversal. So I want to create function Traversal and use function as parameter in it:
if I need to print func = print and for destructor func = delete_node.
Error is here:
void PrintPostOrder(void (*func)() = print_current);
the default argument of type "void (BTree :: ) ()" is incompatible
with the parameter of type "void () ()"
I don't know how to set default value for parameter when parameter is a function.
print_current and delete_node are member functions, so you need a member function pointer:
class BTree {
public:
void PostOrder(void (BTree::*fn)() = &BTree::print_current) {
std::invoke(fn, this);
}
~BTree() {
PostOrder(&BTree::delete_node);
}
private:
void print_current();
void delete_node();
};
For more flexibility you can make PostOrder a template:
struct TreeNode {};
class BTree {
public:
template<class Fn>
void PostOrder(Fn fn) {
std::invoke(fn);
}
void PostOrder() {
PostOrder([this] { print_current(); });
}
~BTree() {
TreeNode* node;
PostOrder([this, node] { delete_node(node); });
}
private:
void print_current();
void delete_node(TreeNode*);
};
In principle you set a default parameter for a function the way you did. The problem is that a member function is of different type than a free function.
This is a free function pointer void (*func)(), while print_current is a member function of type void (BTree :: ) ().
Either fix the parameter type or use a free function as default parameter.
Also do not forget that member functions are fundamentally different from free functions, because you need an instance to call them.

Hash Table in C++ Through Custom Struct and Linked List Classes

I'm trying to create a spell checking program in C++ by reading in a dictionary from a .txt file. I've got the read in function working perfectly fine, the issue I'm coming across is when I try to navigate and add to my linked list.
When I try to set the pointer of the newest node to add, to the value of the head pointer, I'm getting an error stating No viable conversion from 'Node' to 'Node *'.
What is the best way to perform this conversion.
I've already tried turning my 'Node Head;' inside of my linked list class to a pointer but receive the same error.
To start I created my Node struct (Declared in a header file)
struct Node
{
private:
std::string word;
Node *nextNode;
public:
//Default constructor
Node();
~Node();
//My Setters and getters for the class
void setWord(std::string _word) { word = _word; }
std::string getWord() { return word; }
void setNode(Node *_nextNode) { nextNode = _nextNode; }
Node getNode() { return *nextNode; }
};
Followed by my LinkedList Class (Also declared in a Header file)
class LinkedList
{
private:
Node head;
int listSize;
public:
LinkedList();
~LinkedList();
void setListSize(int _listSize) { listSize = _listSize; }
int getListSize() { return listSize; }
void setHead(Node _head) { head = _head; }
Node getHead() { return head; }
//Function that adds the next node to the head
void addToHead(LinkedList &myList, Node &myNode);
};
Heres my Function
void LinkedList::addToHead(LinkedList &myList, Node &myNode)
{
myNode.setNode(myList.getHead().getNode());
//Here is where I'm getting my error
//"No viable conversion from 'Node' to 'Node *'
myList.setHead(myNode);
}
The LinkedList class shouldn't own the first Node.
The member head should be a Node* width default value nullptr (the list is empty).
listSize should also have a default value assigned.
LinkedList() head(nullptr), listSize(0) {};
Edit
Personally I would avoid to force the external code to manage the single nodes.
Keep an implementation independent interface.
class LinkedList
{
private:
Node *head_;
int size_;
public:
LinkedList();
~LinkedList();
int size() const { return listSize; }
// insert after the i-th element
void insert(std::size index, std::string const& word);
// return the i-th element
std::string &at(std::size index);
std::string const &at(std::size index) const;
// removes the i-th element
void remove(size::size index);
};
In this way you centralize all list manipulation code into the LinkedList class.
You should also consider problems related to copying a LinkedList object.

C++ Is it possible to create a private link between objects?

As far as I can understand, linked list can only implemented with an outsider class. Because a class can't have a member varable of it's own type and a node list need that type. The problem is, if the link is intented to be used by a specific class. If, the link class created outside, it will be available to be created as a standalone object.
It's okay if the link class/struct is a pure link object because it can be used for linking another object type. But, in case I need a link that has a functionallity that only related to a certain object, the public availability of it will be pointless. And I think it's better to be created as a private.
Let's take a look at this declaration:
#include <unordered_map>
using namespace std;
template<class T>
class Node
{
public:
Node();
Node(const T& item, Node<T>* ptrnext = NULL);
T data;
// access to the next node
Node<T>* NextNode();
// list modification methods
void InsertAfter(Node<T>* p);
Node<T>* DeleteAfter();
Node<T> * GetNode(const T& item, Node<T>* nextptr = NULL);
private:
Node<T> * next;
unordered_map<string, T*> nodeList;
};
The unordred_map<string,T*> member can only have meaning with a certain object. So, it will be pointless for Node class to be available outside.
Is it possible? Or maybe is it a bad idea to add a non-generic funtionallity for link class?
class A {
A* m_pnext = nullptr;
public:
inline A* next() { return m_pnext; }
inline void set_next(A*ptr) { m_pnext = ptr; }
}
template <class type>
class LinkedList {
type *m_pfirst = nullptr;
public:
void add(type * ptr) {
if ( nullptr == m_pfirst ) {
m_pfirst = ptr;
} else {
type * n = m_pfirst, p = m_pfirst->next;
while (nullptr != p) {
n = p;
p = n->next();
}
n->set_next(ptr);
}
}
};
Plenty of room for improvement, of course. I'll let you exercise your mind.

Virtual function call from inside a base class function [duplicate]

This question already has answers here:
What is object slicing?
(18 answers)
Closed 8 years ago.
I have two classes, Object and Ball. Ball is derived from Object. Object has a virtual function "move" and a non virtual function "moveFast" that calls move. Class Ball redefines the move function from it's parent class.
#include <iostream>
struct Object
{
virtual void move(int dist)
{
std::cout<<"Moving "<<dist<<std::endl;
}
void moveFast(int multiplier)
{
move(10*multiplier);
}
};
struct Ball : public Object
{
void move(int dist)
{
std::cout<<"Rolling "<<dist<<std::endl;
}
};
class List
{
struct Node
{
Node* next;
Object ele;
Node(Object e, Node* n=NULL) : ele(e), next(n){}
};
Node* head;
public:
List() : head(NULL){}
void addObj(Object o)
{
if(head==NULL)
{
head = new Node(o);
return;
}
Node* current = head;
while(current->next!=NULL)
{
current=current->next;
}
Node* obj = new Node(o);
current->next=obj;
}
void doStuff()
{
Node* current = head;
while(current!= NULL)
{
current->ele.moveFast(10);
current=current->next;
}
}
};
int main()
{
Object a,b,c;
Ball d;
List list;
list.addObj(a);
list.addObj(b);
list.addObj(c);
list.addObj(d);
list.doStuff();
}
The List class takes in Objects and calls their moveFast function. Because a,b, and c are just Objects I would expect the first 3 lines of output to be "Moving 100".
d however, is an instance of the Ball class. So I would expect the 4th line of output to say "Rolling 100", because Ball redefined the move function.
Right now all the output prints
Moving 100
Moving 100
Moving 100
Moving 100
Is there a way to get Ball's definition of move called from List?
The problem is that you store your Objects in the list by value. virtual functions will only work on pointers. the moment you try to add an object to the list through list::void addObj(Object o). The argument is passed by value. This means that it is copied and if you copy a base class only the base class functionality will be copied it's called the slicing problem (like dyp mentioned). you should change your nodes to hold a pointer to the object and redo your add object function to take a pointer to the element to prevent copying and slicing.
like this
class List
{
struct Node
{
Node* next;
Object* ele;
Node(Object* e, Node* n=nullptr) : ele(e), next(n){}
};
Node* head;
public:
List() : head(nullptr){}
void addObj(Object* o)
{
if(head==nullptr)
{
head = new Node(o);
return;
}
Node* current = head;
while(current->next!=nullptr)
{
current=current->next;
}
Node* obj = new Node(o);
current->next=obj;
}
void doStuff()
{
Node* current = head;
while(current!= nullptr)
{
current->ele->moveFast(10);
current=current->next;
}
}
};
int main()
{
Object a,b,c;
Ball d;
List list;
list.addObj(&a);
list.addObj(&b);
list.addObj(&c);
list.addObj(&d);
list.doStuff();
return 0;
}
which outputs:
Moving 100
Moving 100
Moving 100
Rolling 100
Like many have said, there was a slicing problem in List.
List::Node stored an actual Object, so when an instance of Ball was passed into addObj(Object o), the additional functionality of Ball was "sliced", and only the parts stored by it's base class "Object" remained.
Changing the Node class to store an Object pointer instead of an Object instance fixed this problem. This change also requires the addObj function to be altered to take in a pointer. The List class now looks like this:
class List
{
struct Node
{
Node* next;
Object* ele;//<-- This is the Big change
Node(Object* e, Node* n=NULL) : ele(e), next(n){}
};
Node* head;
public:
List() : head(NULL){}
void addObj(Object* o)
{
if(head==NULL)
{
head = new Node(o);
return;
}
Node* current = head;
while(current->next!=NULL)
{
current=current->next;
}
Node* obj = new Node(o);
current->next=obj;
}
void doStuff()
{
Node* current = head;
while(current!= NULL)
{
current->ele->moveFast(10);
current=current->next;
}
}
};
changing int main() to provide the altered inputs results in the expected output.
int main()
{
Object *a,*b,*c;
b=c=a=new Object();
Ball* d = new Ball();
List list;
list.addObj(a);
list.addObj(b);
list.addObj(c);
list.addObj(d);
list.doStuff();
}

'<<name of method>>' was not declared in this scope

I want to independently overload operator+ to concatenate 2 double chained lists. My idea is to obtain the address of the first element from the first list and the address of the first element from the second list.
In DoubleChainedList class, except the constructor, destructor and the next 4 methods which are working fine, I made a method called get_prim which is supposed to get me the address of the first element from the specified list. Then, using the method get_current I want to move through the first list until it ends while adding in the third list the elements, and then apply the same principle to the second list.
But I have a problem, I get
'get_prim' was not declared in this scope
and
'get_current' was not declared in this scope
at the bolded tagged lines (see the code below) when I compile. What am I missing?
#include <iostream>
#include <stdlib.h>
using namespace std;
//Create node class
class Node
{
private:
float value;
Node *back;
Node *next;
public:
Node *set_value (Node *x, float element) { x->value=element; return x; }
float get_value (Node *x) { return x->value; }
Node *set_back (Node *x) { return x->back; }
Node *set_next (Node *x) { return x->next; }
Node *set_back_nod (Node *x, Node *y) { x->back=y; return x; }
Node *set_next_nod (Node *x, Node *y) { x->next=y; return x; }
void next_to_2next (Node *x) { x->next=x->next->next; }
void next_back_to_origins (Node *x) { x->next->back=x; }
};
//Create list class
class DoubleChainedList : public Node
{
private:
Node *prim;
Node *ultim;
public:
DoubleChainedList() { prim=NULL; ultim=prim; } //Constructor
~DoubleChainedList(); //Destructor
void insert_back(float element); //Inserts an element at the end of the list
void delete_element_from_position(int delete_position); //Deletes from the list the element whose position is equal to "delete_position"
void show_left_right(); //Shows the list from the first element to the last one
void show_right_left(); //Shows the list from the last element to the first one
Nod *get_prim (DoubleChainedList myList) { return this->prim; }; //Intended to obtain the address of the first element from "myList"
Nod *get_current (Node *x) { return set_next(x); }; //Intended to move me through the list
};
DoubleChainedList operator+ (DoubleChainedList myList1, DoubleChainedList myList2)
{
DoubleChainedList myList3;
Nod *current1,*current2;
current1=get_prim(myList1); // ERROR OVER HERE!
current2=get_prim(myList2);
cout<<get_value(current1)<<" "; // ERROR OVER HERE!
cout<<get_value(current2)<<" ";
return myList3;
}
int main()
{
int i,number_elem_myList1,number_elem_myList2,element;
DoubleChainedList myList1,myList2,myList3;
cin>>number_elem_myList1;
for (i=0;i<number_elem_myList1;i++)
{
cin>>element;
myList1.insert_back(element);
}
cin>>number_elem_myList2;
for (i=0;i<number_elem_myList2;i++)
{
cin>>element;
myList2.insert_back(element);
}
myList3=myList1+myList2;
return 0;
}
If you implement operator+= as a member function, you can have access to the other list's variables.
I would implement operator+=, then traverse the other list, appending the other list's nodes to this list.
And pass the other list as const &.
Functions called with e.g. someObject.function(...) or someObject->function(...) (where someObject is respectively either an object or a pointer to an object of some class that has a function(...) function) have direct access to the members of someObject.
So functions that are members of a class doesn't need to be passed an object of that class as parameter, unless you want to work with 2 objects in that function.
The functions of Node should probably look more like:
void set_value (float element) { value = element; }
float get_value () { return value; }
Node *set_back () { return back; }
Node *set_next () { return next; }
void set_back_nod (Node *y) { back = y; }
void set_next_nod (Node *y) { next = y; }
void next_to_2next () { next = next->next; }
void next_back_to_origins () { next->back = this; }
Also, get_prim:
Node *get_prim() { return prim; };
Which then leads to a operator+ which looks more like: (const & as Thomas suggested)
DoubleChainedList operator+ (const DoubleChainedList &myList1,
const DoubleChainedList &myList2)
{
DoubleChainedList myList3;
Node *current1, *current2;
current1 = myList1.get_prim();
current2 = myList2.get_prim();
cout << current1->get_value() << " ";
cout << current2->get_value() << " ";
// ...
return myList3;
}
Using operator+= as Thomas suggested is probably also a better idea.
Modified the program as follows, but I still have a problem. If I try to display the list outside the procedure "operator+", I get "Segmentation fault" (when I debugged the program it happened immediately after this instruction: "myList3=myList1+myList2;"). If I display it inside that procedure, everything's OK. I think that this is happening because of that "return" statement and because I return a temporary object which will no longer exists after the "operator+" procedure ends, but I don't know how to fix that.
#include <iostream>
using namespace std;
//Create node class
class Node
{
private:
float value;
Node *back;
Node *next;
public:
Node *set_value (float element) { value=element; return this; }
float get_value () { return value; }
Node *set_back () { return back; }
Node *set_next () { return next; }
Nod *set_back_node (Node *y) { back=y; return this; }
Nod *set_next_node (Node *y) { next=y; return this; }
void next_to_2next () { next=next->next; }
void next_back_to_origins () { next->back=this; }
};
//Create list class
class DoubleChainedList : public Node
{
private:
Node *prim;
Node *ultim;
public:
DoubleChainedList() { prim=NULL; ultim=prim; } //Constructor
~DoubleChainedList(); //Destructor
void insert_back(float element); //Inserts an element at the end of the list
void delete_element_from_position(int delete_position); //Deletes from the list the element whose position is equal to "delete_position"
void show_left_right(); //Shows the list from the first element to the last one
void show_right_left(); //Shows the list from the last element to the first one
Node *get_prim () { return prim; } //Intended to obtain the address of the first element from a list
};
DoubleChainedList operator+ (DoubleChainedList myList1, DoubleChainedList myList2)
{
DoubleChainedList myList3;
Node *current1,*current2,*current3;
current1=myList1.get_prim();
current2=myList2.get_prim();
while ((current1!=NULL)||(current2!=NULL))
{
if (current1!=NULL)
{
myList3.insert_back(current1->get_value());
current1=current1->set_next();
}
else
if (current2!=NULL)
{
myList3.insert_back(current2->get_value());
current2=current2->set_next();
}
}
//myList3.show_left_right();
//cout<<endl;
//myList3.show_right_left();
return myList3;
}
int main()
{
int i,number_elem_myList1,number_elem_myList2,element;
DoubleChainedList myList1,myList2,myList3;
cin>>nr_elem_lista1;
for (i=0;i<number_elem_myList1;i++)
{
cin>>element;
myList1.insert_back(element);
}
cin>>number_elem_myList2;
for (i=0;i<number_elem_myList2;i++)
{
cin>>element;
myList2.insert_back(element);
}
myList3=myList1+myList2;
myList3.show_left_right();
myList3.show_right_left();
return 0;
}
#Dukeling modified the methods of the "Node" class as you said (and of course the program where necessary) and it's OK, too.
I can post the full code if is someone interested, but it has more than 200 lines, the name of variables/dates, procedures/methods and also some comments wrote in Romanian (my natural language) and it would be harder for someone new to understand it.