C++ iterating nodes with respect to encapsulation - c++

I'm writing a function which iterates a Queue from within a queue class which operates off of a LinkedList/Node data structure.
I've been able to make the function work but only by getting a pointer to the head node directly from the LinkedList class which, as I understand it, is considered poor encapsulation.
This is my code:
main():
int main()
{
Queue list;
int nums[] = {60, 50, 40};
for (int i=0; i<(int)sizeof(nums)/(int)sizeof(nums[0]); i++) {list.enqueue(nums[i]);}
list.iterate();
}
Queue:
.h
#include "LinkedList.h"
class Queue
{
public:
typedef int value_type;
Queue();
void enqueue(value_type& obj);
int size() const;
void iterate();
int min();
private:
LinkedList data;
int used;
};
#include "Queue.hpp"
.hpp
Queue::Queue()
{ data = LinkedList(); used = 0; }
void Queue::enqueue(value_type& obj)
{ ++used; data.addToTail(obj); }
int Queue::size() const
{ return used; }
void Queue::iterate()
{
node * temp = data.get_head();
for (int i = 0; i < size(); i++)
{ cout << temp->get_data() << endl; temp = temp->get_next(); }
delete temp;
}
LinkedList
.h
#include "Node.h"
class LinkedList
{
public:
typedef int value_type;
LinkedList();
void addToHead(typename node::value_type& entry);
void addToTail(typename node::value_type& entry);
node * get_head();
int front();
private:
node* head;
node* tail;
node* current;
};
#include "LinkedList.hpp"
.hpp
LinkedList::LinkedList()
{ head = NULL; tail = NULL; current = NULL; }
void LinkedList::addToTail(value_type& entry)
{
if (get_head() == NULL)
{ addToHead(entry); }
else {
node* add_ptr = new node;
add_ptr->set_data(entry);
add_ptr->set_next(current->get_next());
add_ptr->set_previous(current);
current->set_next(add_ptr);
if (current == tail) {tail = current->get_next();}
current = current->get_next();
}
}
void LinkedList::addToHead(value_type& entry)
{ head = new node(entry, head); if (tail == NULL) {tail = head;} current = head; }
node * LinkedList::get_head()
{ return head; }
int LinkedList::front()
{ int rval = head->get_data();return rval; }
Node
.h
class node
{
public:
typedef int value_type;
node();
node(const value_type& data, node* link);
void set_data(const value_type& new_data);
void set_next(node* next_ptr);
void set_previous(node* last_ptr);
int get_data() const;
node* get_next() const;
node* get_previous() const;
private:
value_type data;
node* next;
node* previous;
};
#include "Node.hpp"
.hpp
node::node()
{ data = 0; next = 0; previous = 0; }
node::node(const value_type& data, node* link)
{ this->data = data; this->next = link; this->previous = NULL; }
void node::set_data(const value_type& new_data) {data = new_data;}
void node::set_next(node* next_ptr) {next = next_ptr;}
void node::set_previous(node* last_ptr) {previous = last_ptr;}
int node::get_data() const {return data;}
node* node::get_next() const {return next;}
node* node::get_previous() const {return previous;}
Is it possible to iterate the LinkedList without directly retrieving a pointer node? And is this bad practice?

You do not expose the (internal) data structures of the linked list within the interface of the Queue-class (i.e. in the header file). You're just using these data structures in the implementation. Hence, I'd say that you do not "violate encapsulation".
But of course, you may adapt the interface of your LinkedList, such that it does not make use of the internal data structures directly. The standard library with its iterators shows how such a concept is realized. An iterator is an object that represents the position of an element in the container, (and it offers access to the respective element).

The encapsulation in Queue isn't violated but in LinkedList it is, you shouldn't have get_head() function that returns a private pointer member (what if someone does something like this: list.get_head()->set_next(NULL)). You need to create an iterate function in LinkedList and than Queue::iterate would just call this function.

Related

Data insertion and deletion speed of queue in STL of c++

I have question about insertion and deletion speed of queue in c++ STL.
When i tried to slove algorithm question using Dequeue i made, i face running time out problem.
So i think my Dequeue is so slow, and i want to know what is the difference between my Dequeue and queue in c++ STL.
Here is my queue code.
Please give me some advice.
In this code, i suppose value in Node class can't have negative number.
class Node
{
private:
int value;
Node* prev;
Node* next;
public:
Node();
Node(int value);
Node(int value, Node* next);
~Node();
void setValue(int value);
void setPrev(Node* prev);
void setNext(Node* next);
int getValue();
Node* getPrev();
Node* getNext();
};
Node::Node()
: value(-1), prev(nullptr), next(nullptr)
{
}
Node::Node(int value)
: value(value), prev(nullptr), next(nullptr)
{
}
Node::Node(int value, Node* next)
: value(value), prev(nullptr), next(next)
{
}
Node::~Node()
{
}
void Node::setValue(int value)
{
this->value = value;
}
void Node::setPrev(Node* prev)
{
this->prev = prev;
}
void Node::setNext(Node* next)
{
this->next = next;
}
int Node::getValue()
{
return this->value;
}
Node* Node::getPrev()
{
return this->prev;
}
Node* Node::getNext()
{
return this->next;
}
class Dequeue
{
private:
Node* front;
Node* back;
public:
Dequeue();
~Dequeue();
void pushFront(int value);
void pushBack(int value);
void popFront();
void popBack();
int getFront();
int getBack();
int getSum();
};
Dequeue::Dequeue()
{
this->back = new Node(-1, nullptr);
this->front = new Node(-1, this->back);
this->back->setPrev(front);
}
Dequeue::~Dequeue()
{
}
void Dequeue::pushFront(int value)
{
Node* node = new Node(value, this->front->getNext());
node->setPrev(this->front);
this->front->setNext(node);
node->getNext()->setPrev(node);
}
void Dequeue::pushBack(int value)
{
Node* node = new Node(value, this->back);
node->setPrev(this->back->getPrev());
this->back->setPrev(node);
node->getPrev()->setNext(node);
}
void Dequeue::popFront()
{
if (this->front->getNext() == this->back)
return;
Node* node = this->front->getNext();
this->front->setNext(node->getNext());
node->getNext()->setPrev(this->front);
node->setNext(nullptr);
node->setPrev(nullptr);
delete node;
}
void Dequeue::popBack()
{
if (this->back->getPrev() == this->front)
return;
Node* node = this->back->getPrev();
this->back->setPrev(node->getPrev());
node->getPrev()->setNext(this->back);
node->setNext(nullptr);
node->setPrev(nullptr);
delete node;
}
int Dequeue::getFront()
{
if (this->front->getNext() == this->back)
return -1;
return this->front->getNext()->getValue();
}
int Dequeue::getBack()
{
if (this->back->getPrev() == this->front)
return -1;
return this->back->getPrev()->getValue();
}
You Dequeue is implemented via a linked list, where nodes are allocated/deallocated in each push/pop operation. std::queue is implemented via a std::deque, which is much more efficient (it allocates only once a while).
Linked lists are good if you need to insert in the middle, but this is not your case. std::deque is basically a dynamic sequence of fixed-size arrays.
Relevant questions:
Why does std::queue use std::dequeue as underlying default container?
Which STL container should I use for a FIFO?

How can I add an already created node to a linked list?

I'm trying to add an already created node to a linked list by passing a pointer to pointer as argument. I can't figure out how to make it work.
void List::add(Node* n, int pos){
if(pos > size)
pos = size;
if(pos == 0){
if (head == NULL){
head = n;
}
else{
Node* temp = head;
n->setNext(temp);
head = n;
}
}
else{
Node* temp = head;
int currPos = 0;
while(temp->getNext() != NULL && currPos != pos){
temp = temp->getNext();
currPos++;
}
if(currPos == pos){
Node* next = temp->getNext();
n->setNext(next);
}
temp->setNext(n);
}
size++;
}
I implemented a method that creates a new node for each call and it works fine, but I need to work with already created nodes.
Below you have the header files for List and Node.
#pragma once
#include "Node.hpp"
#include <iostream>
class List{
Node* head;
int size;
public:
List();
List(const Team&, Node* = NULL);
// List(const List&);
// List& operator=(const List&);
~List();
void add(const Team&, int = 0);
void add(Node*, int = 0);
void remove(const Team&);
void removeLowest(int unqualNum);
void print() const;
void printNames(ostream& o = cout) const;
int getSize() const;
Node* getHead() const;
};
#pragma once
#include "Team.hpp"
class Node{
Team value;
Node* next;
public:
Node(const Team& = Team(), Node* = NULL);
// Node(const Node&);
// operator=(const Node&);
// ~Node();
Team getValue() const;
void setValue(const Team&);
Node* getNext() const;
void setNext(Node*);
};
I have another class Stack where I want to use the method.
#pragma once
#include "Node.hpp"
#include "List.hpp"
#include <iostream>
class Stack{
Node* head;
int size;
public:
Stack();
Stack(const Team&, Node* = NULL);
// Stack(const Stack&);
// Stack& operator=(const Stack&);
~Stack();
void push(const Team&);
void pop();
void print(ostream& = cout) const;
int getSize() const;
Node* getHead() const;
void toList(List* );
};
In method toList, I try to move all the nodes of the stack to a list passed as argument.
void Stack::toList(List* l){
Node *temp = head;
while(temp){
l->add(temp->getValue(), l->getSize()); // This works similar add method that build node inside
l->add(temp, l->getSize()); // This doesn't, the method with Node as parameter
temp = temp->getNext();
}
}

Creating an new instance of a C++ class, results a duplicate

I'm new to C++. I'm trying to implement a LinkedList, for which I created two classes Node and LinkedList.
I created some test functions. One to test the Node creation and another to test the isEmpty function from LinkedList. However, when I try to test them. What's created in 'testNode()ends up being in the same Node I create insideLinkedListashead`.
This may be trivial question, however as a newcomer to C++ this concept is still no clear to me. I'd like to know why it is referring to the same instance created previously.
#include <iostream>
#include <assert.h>
using namespace std;
class Node
{
private:
int data;
int next;
public:
int getData(){return data;}
void setData(int new_data) {data = new_data;}
int getNext(){return next;}
void setNext(int new_next) {next = new_next;}
};
class LinkedList
{
Node head;
Node head2;
public:
bool isEmpty()
{
if (head.getData() == 0) {return true;}
return false;
}
};
void testNode()
{
Node aNode;
aNode.setData(15);
aNode.setNext(23);
assert (aNode.getData() == 15);
assert (aNode.getNext() == 23);
}
void testEmptyLinkedList()
{
LinkedList ll;
assert (ll.isEmpty() == true);
}
Initialize your data.
int data = 0;
int next = 0;
Live On Coliru
#include <iostream>
#include <cassert>
using namespace std;
class Node {
private:
int data = 0;
int next = 0;
public:
int getData() { return data; }
void setData(int new_data) { data = new_data; }
int getNext() { return next; }
void setNext(int new_next) { next = new_next; }
};
class LinkedList {
Node head;
Node head2;
public:
bool isEmpty() {
if (head.getData() == 0) {
return true;
}
return false;
}
};
void testNode() {
Node aNode;
aNode.setData(15);
aNode.setNext(23);
assert(aNode.getData() == 15);
assert(aNode.getNext() == 23);
}
void testEmptyLinkedList() {
LinkedList ll;
assert(ll.isEmpty() == true);
}
int main() {
testEmptyLinkedList();
}
If your intention is to implement LinkList, each node of the list should contain the address of the next one.
So "next" shoud be declared as a pointer to a Node. Same for the first node of the list.
class Node {
private:
int data;
Node *next;
....
};
class LinkedList {
private:
Node *head;
...
};

C++ Insert integer nodes into a templated singly linked list class in ascending order - Homework

I'm been having trouble with either my constructor or my insert function, I'm not sure which is the issue, but the real issue is that I get the error code mentioning I'm having an error with things getting de-referenced. All I'm trying to do is insert a node containing an integer value in the correct position.
This is the declaration:
template <class T>
class LinkedList
{
template <class T>
struct Node
{
T mData;
Node<T> *mNext;
/* Pre: None
* Post: This object is initialized using default values
* Purpose: To initialize date object
*************************************************************************/
Node()
{
mData = T();
mNext = NULL;
}
/* Pre: None
* Post: This object is initialized using specified data
* Purpose: To intialize date object
*************************************************************************/
Node(T data, Node<T>* next)
{
mData = data;
mNext = next;
}
};
private:
Node<T> *mHead;
int mCount;
public:
LinkedList();
~LinkedList();
int getCount();
T getData(int index);
void setData(int index, T data);
void clear();
void display();
bool insert(T data);
bool isEmpty();
bool isExist(T searchKey);
bool remove(T searchKey);
T removeAt(int index);
T operator[](int index);
void operator=(LinkedList<T> *list);
};
And this is the insert:
template <class T>
bool LinkedList<T>::insert(T data)
{
Node<T>* current = mHead;
if (!current)
{
if (mCount == 0)
{
current->mData = data;
}
else
{
while (current->mNext != NULL)
{
if (current->mData == data)
return false;
else if (current->mNext->mData < data)
{
Node<T>* newNode = new Node<T>();
newNode->mData = data;
newNode->mNext = current->mNext;
current->mNext = newNode;
}
current = current->mNext;
}
}
}
else
{
Node<T>* node = new Node<T>(data, NULL);
current->mNext = node;
}
mCount++;
return true;
}
Every time my program breaks, it's at this line
current->mData = data;
You shouldn't declare Node class as template, in fact you should get a compile error message like error: declaration of 'T' shadows template parameter.
Remove template<class T> from Node and change Node<T> to Node throughout the code.

Error: request for member ... in ... which is of non-class type

Just started learning c++ for a class, I can't figure out what is wrong with this code! I'm making a stack class with a helper class nested inside it called node that acts as a linked list. The error I'm getting is on line 12 and is:
Stack.cpp: In destructor ‘Stack::~Stack()’:
Stack.cpp:12:24: error: request for member ‘getNext’ in ‘((Stack*)this)->Stack::node’, which is of non-class type ‘Stack::Node*’
Here's my code:
#include "Stack.h"
Stack:: Stack ()
{
height = 0;
node = 0;
}
Stack:: ~Stack()
{
while(node != 0){
Node *next = *node.getNext();
delete node;
node = next;
}
node = 0;
}
And Here's my header file:
using namespace std;
class Stack
{
private:
int height;
class Node{
private:
int data;
Node* next;
public:
void setData(int x){
data = x;
}
void setNext(Node* x){
next = x;
}
int getData(){
return data;
}
Node* getNext(){
return next;
}
};
Node* node;
public:
Stack();
~Stack();
void push(int x);
int pop();
int peek();
int getHeight();
bool isEmpty();
};
Node *next = *node.getNext();
should be
Node *next = (*node).getNext();
Since . operator has higher precedence than * deference operator.
You can also use:
Node *next = node->getNext();