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;
...
};
Related
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.
First, sorry for the long code. I did my best to trim it as small as possible.
I'm getting segmentation fault when i want to add a new element (void SLList::pushBack(const Data &rDATA)) to my singly linked list (in SLList.hxx). The segmentation fault caused by 0xbaadf00d value.
........................................................................................................
IniFile.h
#include "Section.h"
class IniFile
{
public:
IniFile() :
void addSection();
private:
SLList<Section> mContent;
};
IniFile.cpp
#include "IniFile.h"
IniFile::IniFile() :
mContent() {}
void IniFile::addSection() // This is the only one method what i call
{
mContent.pushBack(Section());
}
Section.h
#include "Pair.hxx"
#include "SLList.hxx"
class Section
{
public:
Section();
private:
SLList<Pair<std::string, std::string>> mKeyValuePairs;
};
Section.cpp
#include "Section.h"
Section::Section() :
mKeyValuePairs() {}
SLList.hxx
template <typename Data>
class SLList
{
public:
class Node
{
public:
Node(const Data &rDATA, Node *const pNEXT = nullptr) :
mData(rDATA),
mNext(pNEXT) {}
Node(const Node &rRHS)
{
mData = rRHS.mData;
*mNext = *rRHS.mNext;
}
~Node()
{
delete mNext;
}
Node &operator=(const Node &rRHS)
{
if (&rRHS == this)
return *this;
mData = rRHS.mData;
*mNext = *rRHS.mNext;
return *this;
}
private:
void setNext(Node *const pNext)
{
mNext = pNext;
}
friend void SLList<Data>::pushBack(const Data &rDATA);
private:
Data mData;
Node *mNext;
};
SLList() :
mHead(nullptr),
mTail(nullptr) {}
SLList(const SLList &rRHS)
{
*mHead = *rRHS.mHead;
*mTail = *rRHS.mTail;
}
SLList &operator=(const SLList &rRHS)
{
if (&rRHS == this)
return *this;
*mHead = *rRHS.mHead;
*mTail = *rRHS.mTail;
return *this;
}
~SLList()
{
clear();
}
void clear()
{
delete mHead;
}
void pushBack(const Data &rDATA)
{
Node *pNode = new Node(rDATA, nullptr); // I get segmentation fault at this point
if (!mTail)
{
mHead = pNode;
mTail = pNode;
}
else
{
mTail->setNext(pNode);
mTail = pNode;
}
}
private:
Node *mHead;
Node *mTail;
};
Pair.hxx
template <typename T1, typename T2>
class Pair
{
public:
Pair(const T1 &rFIRST, const T2 &rSECOND) :
mFirst(rFIRST),
mSecond(rSECOND) {}
private:
T1 mFirst;
T2 mSecond;
};
SLList's copy constructor and assignment operator are wrong in terms of Node* pointer management.
Also, Node's destructor shouldn't destroy the next Node object in the list. Not only is a recursive destructor bad for long lists, but also think of in the future if you ever want to remove a single Node without clearing the whole list. Your clear() method should directly iterate the list deleting Node objects one at a time without using recursion.
Try something more like this:
#include <utility>
template <typename Data>
class SLList
{
public:
class Node
{
public:
Node(const Data &rDATA, Node *const pNEXT = nullptr)
: mData(rDATA), mNext(pNEXT)
{
}
Node(const Node &rSRC)
: mData(rSRC.mData), mNext(nullptr)
{
}
Node &operator=(const Node &rRHS)
{
if (&rRHS != this)
mData = rRHS.mData;
return *this;
}
private:
Data mData;
Node *mNext;
friend class SLList<Data>;
};
SLList()
: mHead(nullptr), mTail(nullptr)
{
}
SLList(const SLList &rSRC)
: mHead(nullptr), mTail(nullptr)
{
Node *pNode = rSRC.mHead;
while (pNode)
{
pushBack(pNode->mData);
pNode = pNode->mNext;
}
}
SLList &operator=(const SLList &rRHS)
{
if (&rRHS != this)
{
SLList temp(rRHS);
std::swap(mHead, temp.mHead);
std::swap(mTail, temp.mTail);
}
return *this;
}
~SLList()
{
clear();
}
void clear()
{
Node *pNode = mHead;
mHead = mTail = nullptr;
while (pNode)
{
Node *pNext = pNode->mNext;
delete pNode;
pNode = pNext;
}
}
void pushBack(const Data &rDATA)
{
Node *pNode = new Node(rDATA);
if (!mHead) mHead = pNode;
if (mTail) mTail->mNext = pNode;
mTail = pNode;
}
private:
Node *mHead;
Node *mTail;
};
With that said, what you really should do is use std::list (or std::forward_list) and std::pair instead. There is no benefit to "reinventing the wheel" at all:
#include "Section.h"
#include <list>
class IniFile
{
public:
void addSection();
private:
std::list<Section> mContent;
};
#include "IniFile.h"
void IniFile::addSection()
{
mContent.push_back(Section());
}
#include <pair>
#include <list>
#include <string>
class Section
{
private:
std::list<std::pair<std::string, std::string>> mKeyValuePairs;
};
#include <list>
template <typename Data>
class SLList
{
public:
void clear()
{
mList.clear();
}
void pushBack(const Data &rDATA)
{
mList.push_back(rDATA);
}
private:
std::list<Data> mList;
};
This is the code for a simple binary tree program:
#include <iostream>
using namespace std;
template <class Tree>
class node
{
public:
node()
{
this->tree=NULL;
this->leftnode=this->rightnode=NULL;
};
~node();
node(Tree* base)
{
this->tree=base;
this->leftnode=this->rightnode=NULL;
};
Tree* getnodevalue()
{
return this->tree;
};
node* getleftnode()
{
return leftnode;
};
node* getrightnode()
{
return rightnode;
};
void newleft(node* val)
{
this->leftnode=val;
};
void newright(node* val)
{
this->rightnode=val;
};
void newnode(Tree* val)
{
this->tree=val;
};
int chkleaf()
{
if(this->leftnode==NULL && this->rightnode==NULL)
return 1;
return 0;
}
void insert(node* nextnode, int* value)
{
node <int>* nodecounter= new node<int>(value);
node<int> *p, *q;
p=q=nextnode;
while(*value!=*(p->getnodevalue()) && q!=NULL)
{
p=q;
if(*value<*(p->getnodevalue()))
q=p->getleftnode();
else
q=p->getrightnode();
};
if(*value==*(p->getnodevalue()))
{
cout<<"Duplicate"<<*value<<"\n";
delete nodecounter;
}
else if(*value<*(p->getnodevalue()))
p->newleft(nodecounter);
else
p->newright(nodecounter);
};
private:
Tree* tree;
node* leftnode;
node* rightnode;
};
int main(int argc, char* argv[])
{
int newtree[5]={0,45,67,34,24};
node<int>* node1= new node<int>();
node1->newnode(&newtree[0]);
for(int i=1; newtree[i]>0; i++)
{
node1->insert(node1, &newtree[i]);
};
return 0;
}
I can't understand what the issue is, I've never had this error before. Is it a coding problem, or something else? Would really appreciate some insight
Linker complains about missing destructor definition.
Change
node();
to
~node() {}
or, if you are using c++11
~node() = default;
You also need to release used memory in destructor using delete statement.
We have an assignment to create a Binary Search Tree with some basic functions. I feel I'd be capable of scraping by if it weren't for the files included with the assignment that we need to adhere to in order for the graders to implement our code with their grading program. Students are given a file called "Factory.cpp" which has a function that attempts to return an object of "BinarySearchTree" (return new BinarySearchTree();). However, VS 2013 gives me the error seen in the title. After some research, I can't find any infomration I can implement into my own problem to get rid of the error. Template classes are obviously more abstract and I can't find out what to include/leave out, etc to make things work.
The following is my incomplete code I have so far in my BinarySearchTree.h:
#pragma once
#include "BSTInterface.h"
#include "NodeInterface.h"
#ifndef BINARY_SEARCH_TREE_H
#define BINARY_SEARCH_TREE_H
struct BTNode :public NodeInterface{
// Data Fields
int data;
BTNode* left;
BTNode* right;
// Constructor
BTNode(const int& the_data,
BTNode* left_val = NULL,
BTNode* right_val = NULL) :
data(the_data), left(left_val), right(right_val) {}
// Destructor (to avoid warning message)
virtual ~BTNode() {}
// Interface Functions
int getData(){
return data;
}
NodeInterface* getLeftChild(){
return left;
}
NodeInterface* getRightChild(){
return right;
}
}; // End BTNode
#include <sstream>
template<class T>
class BinarySearchTree:public BSTInterface
{
public:
BTNode* root;
// BST Constructor / Deconstructor
BinarySearchTree() : root(NULL){}
//BinarySearchTree(const int& the_data,
// const BinarySearchTree& left_child = BinarySearchTree(),
// const BinarySearchTree& right_child = BinarySearchTree()) :
// root(new BTNode(the_data, left_child.root, right_child.root)){}
virtual ~BinarySearchTree(){}
// Interface Functions ----------------------
NodeInterface* getRootNode(){
return root;
}
bool add(int data){
return addRec(root, data);
}
bool addRec(BTNode* &x, int data){
if (x == NULL){
if (Search(root, data) == true){
return false;
}
else{
root = GetNewNode(data);
return true;
}
}
if (data == x->data){
return false;
}
if (x != NULL){
if (data < x->data){
return addRec(x->left, data);
}
if (data > x->data){
return addRec(x->right, data);
}
}
}
bool remove(int data){
return false;
}
bool removeRec(BTNode* &x, int data){
return false;
}
void clear(){
}
// ------------------------------------------
// My Functions -----------------------------
BTNode* GetNewNode(int data){
BTNode* newNode = new BTNode();
newNode->data = data;
newNode->left = newNode->right = NULL;
return newNode;
}
bool Search(BTNode* root, int data) {
if (root == NULL) {
return false;
}
else if (root->data == data) {
return true;
}
else if (data < root->data) { // had <= instead
return Search(root->left, data);
}
else if (data > root->data) { // had no "if"
return Search(root->right, data);
}
}
// ------------------------------------------
};
#endif
Which is derived from the following 2 "Interface" files:
NodeInterface.h:
//YOU MAY NOT MODIFY THIS DOCUMENT
#pragma once
#include <iostream>
class NodeInterface {
public:
NodeInterface() {}
virtual ~NodeInterface() {}
/*Returns the data that is stored in this node*/
virtual int getData() = 0;
/*Returns the left child of this node or null if it doesn't have one.*/
virtual NodeInterface * getLeftChild() = 0;
/*Returns the right child of this node or null if it doesn't have one.*/
virtual NodeInterface * getRightChild() = 0;
};
BSTInterface.h
//YOU MAY NOT MODIFY THIS DOCUMENT
#pragma once
#include "NodeInterface.h"
using namespace std;
class BSTInterface {
public:
BSTInterface() {}
virtual ~BSTInterface() {}
//Please note that the class that implements this interface must be made
//of objects which implement the NodeInterface
/*Returns the root node for this tree*/
virtual NodeInterface * getRootNode() = 0;
/*Attempts to add the given int to the BST tree*/
virtual bool add(int data) = 0;
/*Attempts to remove the given int from the BST tree*/
virtual bool remove(int data) = 0;
/*Removes all nodes from the tree, resulting in an empty tree.*/
virtual void clear() = 0;
};
Then they give us "Factory.h" and "Factory.cpp," which I believe they use to grab our BinarySearchTree from in order to grade using their grading program:
Factory.h:
#include "BSTInterface.h"
using namespace std;
/*
WARNING: It is expressly forbidden to modify any part of this document, including its name
*/
class Factory
{
public:
static BSTInterface * getBST();
};
Factory.cpp:
#include "Factory.h"
#include "BinarySearchTree.h"
//You may add #include statements here
/*
You will MODIFY THIS DOCUMENT.
getBST()
Creates and returns an object whose class extends BSTInterface.
This should be an object of a class you have created.
Example: If you made a class called "BinarySearchTree", you might say, "return new BinarySearchTree();".
*/
BSTInterface * Factory::getBST()
{
return new BinarySearchTree();//Modify this line
}
In "Factory.cpp", BinarySearchTree is marked as an error in VS with the message "argument list for class template is missing." How do I fix this? Along with any other errors you see.
Also, how would I declare a new BinarySearchTree object in a main() and call its functions in order to test it?
For that error, in these lines:
template<class T>
class BinarySearchTree:public BSTInterface
{
just get rid of the first line. That line is telling the compiler that you BinarySearchTree class is a template class. But since your class uses an int for data it would seem that is not needed.
I haven't looked at your other code so I won't comment on anything else.
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();