I am following the "Data Structures" book by Michael T. Goodrich. I have no problems following him in the book, but it doesn't teach how to print/show the contents of a list.
I populate my list with objects, all the methods work, but I have no idea how to print/show them on the screen.
//list.h
class DLinkedList { // doubly linked list
public:
DLinkedList(); // constructor
~DLinkedList(); // destructor
bool empty() const; // is list empty?
const Elem& front() const; // get front element
const Elem& back() const; // get back element
void addFront(const Elem& e); // add to front of list
void addBack(const Elem& e); // add to back of list
void removeFront(); // remove from front
void removeBack(); // remove from back
private: // local type definitions
DNode* header; // list sentinels
DNode* trailer;
protected: // local utilities
void add(DNode* v, const Elem& e); // insert new node before v
void remove(DNode* v); // remove node v
};
Related
In summary, my problem is that I want to find a way to get an access to the element to which iterator is pointing from a derived class. The details are at the below.
I am implementing a sequence with a doubly linked list, referring to the book "Data Structures & Algorithms in C++" (written by Goodrich, Tamassia, Mount), page 255. The book defines class NodeSequence as a derived class of doubly linked list.
Here is the code. Firstly, I made a doubly linked list class with struct Node and class Iterator inside. (This is saved as "DList.h")
typedef int E;
class DList {
private:
struct Node {
E element;
Node* prev;
Node* next;
};
public:
class Iterator {
public:
E& operator*();//reference to the element
bool operator==(const Iterator& p) const;
bool operator!=(const Iterator& p) const;
Iterator& operator++();
Iterator& operator--();
friend class DList; //gives access to the DList
private:
Node* v; //pointer to the node
Iterator(Node* u); //create from Node
};
public:
DList();
int size() const;
bool empty() const;
Iterator begin() const;
Iterator end() const;
void insertFront(const E& e);
void insertBack(const E& e);
void insert(const Iterator& p, const E& e);
void eraseFront();
void eraseBack();
void erase(const Iterator& p);
void printList();
private:
int n;
Node* header;
Node* trailer;
};
Next, I made a derived class of DList named "NodeSequence", which is defined as the following
#include "DList.h"
class NodeSequence : public DList{ //NodeSequence class inherits DList class
public:
Iterator atIndex(int i) const ; //get position from index
int indexOf(const Iterator& p) const; //get index from position
};
Finally, I wanted to test my code, so I demonstrated as the following.
int main() {
NodeSequence test;
test.insertBack(5);
test.insertBack(4);
test.insertBack(3);
test.insertBack(2);
test.insertBack(1);
NodeSequence::Iterator p= test.atIndex(1);
cout << (p.v)->element() << endl;
// I expected 4, but it gives compile error, it says I can't access to p.v because it is a private member
}
Is there any way I can get an access to the private element (which is a pointer) of the iterator? I do not want to change Node* v from private to public.
I am trying to define this operator overload function. However, I am getting this error from the compiler:
List.hpp:62:1: error: invalid use of template-name ‘cop4530::List’ without an argument list
List& List<T>::operator=(List&& rhs) // move assingment operator
This is whole class that I am working on it. It is a class that implements a doubly linked list:
template <typename T>
class List {
private:
struct Node {
T data;
Node *prev;
Node *next;
Node(const T & d = T{}, Node *p = nullptr, Node *n = nullptr)
: data{d}, prev{p}, next{n} {}
Node(T && d, Node *p = nullptr, Node *n = nullptr)
: data{std::move(d)}, prev{p}, next{n} {}
};
public:
//nested const_iterator class
class const_iterator {
public:
const_iterator(); // default zero parameter constructor
const T & operator*() const; // operator*() to return element
// increment/decrement operators
const_iterator & operator++();
const_iterator operator++(int);
const_iterator & operator--();
const_iterator operator--(int);
// comparison operators
bool operator==(const const_iterator &rhs) const;
bool operator!=(const const_iterator &rhs) const;
protected:
Node *current; // pointer to node in List
T & retrieve() const; // retrieve the element refers to
const_iterator(Node *p); // protected constructor
friend class List<T>;
};
// nested iterator class
class iterator : public const_iterator {
public:
iterator();
T & operator*();
const T & operator*() const;
// increment/decrement operators
iterator & operator++();
iterator operator++(int);
iterator & operator--();
iterator operator--(int);
protected:
iterator(Node *p);
friend class List<T>;
};
public:
// constructor, desctructor, copy constructor
List(); // default zero parameter constructor
List(const List &rhs); // copy constructor
List(List && rhs); // move constructor
// num elements with value of val
explicit List(int num, const T& val = T{});
// constructs with elements [start, end)
List(const_iterator start, const_iterator end);
// constructs with a copy of each of the elements in the initalizer_list
List (std::initializer_list<T> iList);
~List(); // destructor
// copy assignment operator
const List& operator=(const List &rhs);
// move assignment operator
List & operator=(List && rhs);
// sets list to the elements of the initializer_list
List& operator= (std::initializer_list<T> iList);
// member functions
int size() const; // number of elements
bool empty() const; // check if list is empty
void clear(); // delete all elements
void reverse(); // reverse the order of the elements
T& front(); // reference to the first element
const T& front() const;
T& back(); // reference to the last element
const T& back() const;
void push_front(const T & val); // insert to the beginning
void push_front(T && val); // move version of insert
void push_back(const T & val); // insert to the end
void push_back(T && val); // move version of insert
void pop_front(); // delete first element
void pop_back(); // delete last element
void remove(const T &val); // remove all elements with value = val
template <typename PREDICATE>
void remove_if(PREDICATE pred); // remove all elements for which Predicate pred
// returns true. pred can take in a function object
// print out all elements. ofc is deliminitor
void print(std::ostream& os, char ofc = ' ') const;
iterator begin(); // iterator to first element
const_iterator begin() const;
iterator end(); // end marker iterator
const_iterator end() const;
iterator insert(iterator itr, const T& val); // insert val ahead of itr
iterator insert(iterator itr, T && val); // move version of insert
iterator erase(iterator itr); // erase one element
iterator erase(iterator start, iterator end); // erase [start, end)
private:
int theSize; // number of elements
Node *head; // head node
Node *tail; // tail node
void init(); // initialization
};
The function that I am trying to define is this one:
template < typename T>
List& List<T>::operator=(List&& rhs)
{
std::swap( theSize, rhs.theSize);
std::swap( head, rhs.head);
std::swap( tail, rhs.tail);
return *this;
}
You forgot to add <T>:
template <typenameT>
List<T>& List<T>::operator=(List<T>&& rhs)
// ^^^ ^^^
// ^ this one is optional but I prefer it
{
//...
}
/*
The below code is only printing the adresss and not the actual data.
I could not figure out where i am missing something.
Also, i was wondering how do i insert data next the existing node. It only lets me add data to the front not the back.
*/
include
using namespace std;
typedef string Elem; // list element type
class DNode { // doubly linked list node
private:
Elem elem; // node element value
DNode* prev; // previous node in list
DNode* next; // next node in list
friend class DLinkedList; // allow DLinkedList access
};
class DLinkedList { // doubly linked list
public:
DLinkedList(); // constructor
//~DLinkedList(); // destructor
bool empty() const; // is list empty?
const Elem& front() const; // get front element
const Elem& back() const; // get back element
void addFront(const Elem &e); // add to front of list
void addBack(const Elem& e); // add to back of list
void removeFront(); // remove from front
void removeBack(); // remove from back
void print() const;
private: // local type definitions
DNode* header; // list sentinels
DNode* trailer;
protected: // local utilities
void add(DNode* v, const Elem &e); // insert new node before v
void remove(DNode* v); // remove node v
};
DLinkedList::DLinkedList() { // constructor
header = new DNode; // create sentinels
trailer = new DNode;
header->next = trailer; // have them point to each other
trailer->prev = header;
}
//DLinkedList::~DLinkedList() { // destructor
// while (!empty()) removeFront(); // remove all but sentinels
// delete header; // remove the sentinels
// delete trailer;
//}
void DLinkedList::addFront(const Elem &e) // add to front of list
{ add(header->next, e); }
void DLinkedList::addBack(const Elem& e) // add to back of list
{ add(trailer, e); }
bool DLinkedList::empty() const // is list empty?
{ return (header->next == trailer); }
const Elem& DLinkedList::front() const // get front element
{ return header->next->elem; }
const Elem& DLinkedList::back() const // get back element
{ return trailer->prev->elem; }
//// insert new node before v
void DLinkedList::add(DNode* v, const Elem &e) {
DNode* u = new DNode; u->elem = e; // create a new node for e
u->next = v; // link u in between v
u->prev = v->prev; // ...and v->prev
v->prev->next = v->prev = u;
}
void DLinkedList::print() const
{
DNode * nodePtr;
nodePtr = header;
while (nodePtr) {
cout<<nodePtr->prev<<endl;
nodePtr = nodePtr -> next;
}
}
int main()
{
DLinkedList list;
list.addFront("2334");
list.addFront("apple");
list.print();
return 0;
}
Its printing adress because you are printing the address. Change your cout statement in print() function
while (nodePtr) {
cout<<nodePtr->prev->elem<<endl;
nodePtr = nodePtr -> next;
}
Also any reason to typedef sting to Elem ?
I have the following List class:
typedef int Elem; // list base element type
class NodeList { // node-based list
private:
struct Node { // a node of the list
Elem elem; // element value
Node* prev; // previous in list
Node* next; // next in list
};
public:
class Iterator { // an iterator for the list
public:
Elem& operator*(); // reference to the element
bool operator==(const Iterator& p) const; // compare positions
bool operator!=(const Iterator& p) const;
Iterator& operator++(); // move to next position
Iterator& operator--(); // move to previous position
friend class NodeList; // give NodeList access
private:
Node* v; // pointer to the node
Iterator(Node* u); // create from node
};
public:
NodeList(); // default constructor
int size() const; // list size
bool empty() const; // is the list empty?
Iterator begin() const; // beginning position
Iterator end() const; // (just beyond) last position
void insertFront(const Elem& e); // insert at front
void insertBack(const Elem& e); // insert at rear
void insert(const Iterator& p, const Elem& e); // insert e before p
void eraseFront(); // remove first
void eraseBack(); // remove last
void erase(const Iterator& p); // remove p
private: // data members
int n; // number of items
Node* header; // head-of-list sentinel
Node* trailer; // tail-of-list sentinel
};
My code does not do any checking to determine whether a given position (iterator object) is actually a member of a particular list. For example, if p is a position in list S and I call T.insert(p,e) on a different list T, then I'd actually be adding the element to S just before p. How can I change my NodeList implementation to disallow such a misuse?
It would mean a bit of memory overhead but if you store the head of each list in all nodes you can check if the heads are the same, then it's probably the same list.
Or if you prefer cpu overhead over memory overhead, loop through the prev-links to find the head of both lists and compare them as above.
So it depends on which kind of overhead you prefer.
I am trying to create an avl tree then using boost to check if what I created is working. However, in all my boost test cases I don't have a main(which I thought is the issue causing the problem). This is my avl .hpp
I'm somewhat new to c++.
template <typename T>
class avlTreeNode
{
public:
// data in the node
T nodeValue;
// pointers to the left and right children of the node
avlTreeNode<T> *left;
avlTreeNode<T> *right;
int balanceFactor;
// CONSTRUCTOR
avlTreeNode (const T& item, avlTreeNode<T> *lptr = NULL,
avlTreeNode<T> *rptr = NULL, int bal = 0):
nodeValue(item), left(lptr), right(rptr), balanceFactor(bal)
{
}
};
const int leftheavy = -1;
const int balanced = 0;
const int rightheavy = 1;
template <typename T>
class avlTree
{
public:
// CONSTRUCTORS, DESTRUCTOR, ASSIGNMENT
// constructor. initialize root to NULL and size to 0
avlTree();
~avlTree();
typedef T* iterator;
typedef T const* const_iterator;
// constructor. insert n elements from range of T* pointers4
avlTree(T *first, T *last);
// search for item. if found, return an iterator pointing
// at it in the tree; otherwise, return end()
iterator find(const T& item);
// search for item. if found, return an iterator pointing
// at it in the tree; otherwise, return end()
const_iterator find(const T& item) const;
// indicate whether the tree is empty
int empty() const;
// return the number of data items in the tree
int size() const;
// give a vertical display of the tree .
void displayTree(int maxCharacters) const;
// insert item into the tree
//std::pair<iterator, bool> insert(const T& item);
// insert a new node using the basic List operation and format
//std::pair<iterator, bool> insert(const T& item);
// delete all the nodes in the tree
void clear();
// constant versions
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
///////////////////////////////////////////////////////////
//when I created this it started giving me the lnk 1561 error
std::pair<iterator,bool> insert(const T& item)
{
avlTree<T>::iterator iter;
// quietly return if item is already in the tree
if ((iter = find(item)) != end() )
return std::pair<iterator,bool>(iter,false);
// declare AVL tree node pointers.
avlTreeNode<T> *treeNode = root,*newNode;
// flag used by AVLInsert to rebalance nodes
bool reviseBalanceFactor = false;
// get a new AVL tree node with empty pointer fields
newNode = getavlTreeNode(item,NULL,NULL);
// call recursive routine to actually insert the element
avlInsert(treeNode, newNode, reviseBalanceFactor);
// assign new values to data members root, size and current
root = treeNode;
treeSize++;
return std::pair<iterator, bool> (iterator(newNode), true);
}
private:
// pointer to tree root
avlTreeNode<T> *root;
// number of elements in the tree
int treeSize;
// allocate a new tree node and return a pointer to it
avlTreeNode<T> *getavlTreeNode(const T& item,
avlTreeNode<T> *lptr,avlTreeNode<T> *rptr);
// used by copy constructor and assignment operator
avlTreeNode<T> *copyTree(avlTreeNode<T> *t);
// delete the storage occupied by a tree node
void freeavlTreeNode(avlTreeNode<T> *p);
// used by destructor, assignment operator and clear()
void deleteTree(avlTreeNode<T> *t);
// locate a node item and its parent in tree. used by find()
avlTreeNode<T> *findNode(const T& item,
avlTreeNode<T>* & parent) const;
// member functions to insert and erase a node
void singleRotateLeft (avlTreeNode<T>* &p);
void singleRotateRight (avlTreeNode<T>* &p);
void doubleRotateLeft (avlTreeNode<T>* &p);
void doubleRotateRight (avlTreeNode<T>* &p);
void updateLeftTree (avlTreeNode<T>* &tree,
bool &reviseBalanceFactor);
void updateRightTree (avlTreeNode<T>* &tree,
bool &reviseBalanceFactor);
};
On the top of your cpp file, define BOOST_TEST_MAIN. It is used to automatically generate main function by the unit testing library.
For example:
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
#include "avl.hpp"
BOOST_AUTO_TEST_CASE( test )
{
// ...
}