Doubly linked list c++ - c++

/*
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 ?

Related

How to print/show an entire list of objects?

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
};

C++ Doubly Linked List Iterator

What
am I missing here? Here are the errors that Im getting along with my code:
The Errors:
Iterator.cpp:4:11: error: 'Iterator' in 'class NodeList' does not name a type
NodeList::Iterator::Iterator(Node* u) // constructor from Node*
^
Iterator.cpp:7:19: error: 'NodeList::Iterator' has not been declared
Elem& NodeList::Iterator::operator*() // reference to the element
^
Iterator.cpp:7:39: error: 'Elem& operator*()' must have an argument of class or enumerated type
Elem& NodeList::Iterator::operator*() // reference to the element
^
Iterator.cpp:10:18: error: 'NodeList::Iterator' has not been declared
bool NodeList::Iterator::operator==(const Iterator& p) const
^
Iterator.cpp:10:58: error: non-member function 'bool operator==(const Iterator&)' cannot have cv-qualifier
bool NodeList::Iterator::operator==(const Iterator& p) const
^
Iterator.cpp:10:58: error: 'bool operator==(const Iterator&)' must take exactly two arguments
Iterator.cpp:13:18: error: 'NodeList::Iterator' has not been declared
bool NodeList::Iterator::operator!=(const Iterator& p) const
^
Iterator.cpp:13:58: error: non-member function 'bool operator!=(const Iterator&)' cannot have cv-qualifier
bool NodeList::Iterator::operator!=(const Iterator& p) const
^
Iterator.cpp:13:58: error: 'bool operator!=(const Iterator&)' must take exactly two arguments
Iterator.cpp:16:13: error: 'Iterator' in 'class NodeList' does not name a type
NodeList::Iterator& NodeList::Iterator::operator++()
^
Iterator.cpp:19:13: error: 'Iterator' in 'class NodeList' does not name a type
NodeList::Iterator& NodeList::Iterator::operator--()
^
The Code:
#ifndef NODE_H
#define NODE_H
#include <string>
using namespace std;
typedef string Elem;
struct Node
{ // a node of the list
Elem elem; // element value
Node* prev; // previous in list
Node* next; // next in list
};
#endif /* NODE_H */
#ifndef ITERATOR_H
#define ITERATOR_H
#include "Node.h"
class Iterator
{ // an iterator for the list
private:
Node* v; // pointer to the node
Iterator(Node* u); // create from node
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
friend class NodeList; // give NodeList access
};
#endif /* ITERATOR_H */
#ifndef NODELIST_H
#define NODELIST_H
#include "Node.h"
#include "Iterator.h"
typedef int Elem; // list base element type
class NodeList
{ // node-based list
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
// housekeeping functions omitted...
private: // data members
int n; // number of items
Node* header; // head-of-list sentinel
Node* trailer; // tail-of-list sentinel
};
#endif /* NODELIST_H */
#include "NodeList.h"
#include <iostream>
using namespace std;
NodeList::NodeList()
{ // constructor
n = 0; // initially empty
header = new Node; // create sentinels
trailer = new Node;
header->next = trailer; // have them point to each other
trailer->prev = header;
}
int NodeList::size() const // list size
{ return n; }
bool NodeList::empty() const // is the list empty?
{ return (n == 0); }
NodeList::Iterator NodeList::begin() const // begin position is first item
{ return Iterator(header->next); }
NodeList::Iterator NodeList::end() const // end position is just beyond last
{ return Iterator(trailer); }
void NodeList::erase(const Iterator& p)
{ // remove p
Node* v = p.v; // node to remove
Node* w = v->next; // successor
Node* u = v->prev; // predecessor
u->next = w; w->prev = u; // unlink p
delete v; // delete this node
n--; // one fewer element
}
void NodeList::eraseFront() // remove first
{ erase(begin()); }
void NodeList::eraseBack() // remove last
{ erase(--end()); }
void NodeList::insert(const NodeList::Iterator& p, const Elem& e)
{
Node* w = p.v; // p's node
Node* u = w->prev; // p's predecessor
Node* v = new Node; // new node to insert
v->elem = e;
v->next = w; w->prev = v; // link in v before w
v->prev = u; u->next = v; // link in v after u
n++;
}
void NodeList::insertFront(const Elem& e) // insert at front
{ insert(begin(), e); }
void NodeList::insertBack(const Elem& e) // insert at rear
{ insert(end(), e); }
#include "Iterator.h"
#include <iostream>
using namespace std;
NodeList::Iterator::Iterator(Node* u) // constructor from Node*
{ v = u; }
Elem& NodeList::Iterator::operator*() // reference to the element
{ return v->elem; }
// compare positions
bool NodeList::Iterator::operator==(const Iterator& p) const
{ return v == p.v; }
bool NodeList::Iterator::operator!=(const Iterator& p) const
{ return v != p.v; }
// move to next position
NodeList::Iterator& NodeList::Iterator::operator++()
{ v = v->next; return *this; }
// move to previous position
NodeList::Iterator& NodeList::Iterator::operator--()
{ v = v->prev; return *this; }
Your Iterator class is defined in the global namespace, however when you define its methods you qualify it as a nested class of NodeList: NodeList::Iterator should be just Iterator.

Source Code Inside - Using Delete on a element after insertion in Linked List implementation breaks the whole application

Linked List Class
class LinkedList
{
protected:
class Element
{
private:
Element *next;
int data;
public:
~Element() {};
Element() {};
Element(int value): next(NULL), data(value) {};
Element(Element *elem, int value): next(elem), data(value) {};
void setNext(Element *elem) {next = elem;}
void setValue(int value) {data = value;}
Element *getNext() const {return next;}
int getValue() const {return data;}
};
Element *head;
Element *tail;
public:
LinkedList(): head(NULL), tail(NULL) {};
~LinkedList() {};
Element* returnHead() {return head;};
Element* returnTail() {return tail;};
void setTail(Element *elem) {tail = elem;};
void setHead(Element *elem) {head = elem;};
// Basic functions
void print();
void printEnds();
void insertFront(int value);
void insertAfter(int afterValue, int value);
void deleteAt(int value);
void reverse();
// Question functions
void mthElemLast(int m);
void makeConnection();
bool isCyclic();
void weave();
void removeDup();
void deleteMiddle();
void partition(int value);
void palindrome();
void sumList(Element *head1, Element *head2);
void createIntersection(LinkedList *L1, LinkedList *L2, LinkedList *L3);
void getIntersection(LinkedList *L1, LinkedList *L2);
};
Insert Front Function
void LinkedList::insertFront(int value)
{
Element *newElem = new Element(value);
if (head == NULL)
{
head = newElem;
tail = newElem;
}
else
{
newElem->setNext(head);
head = newElem;
}
// delete newElem ------------> Adding this line Breaks the complete Linked List
}
Here above I have displayed my Linked List implementation using raw pointers. The problem I am facing is when I add a new element to the list in the front I create a new Element() add it to the list and make necessary adjustments to the list to make sure head is updated.
But when I delete the temporarily created element, it breaks my complete linked list and I am unable to understand why.
If I choose not to delete the temporary element, it creates memory leaks.
Help would be appreciated.
Thank You.
The is fine just as it is, without the call to delete. You say:
If I choose not to delete the temporary element
however, the object pointed to by newElem is not temporary. It is allocated on the heap and is now part of the linked list.
void LinkedList::insertFront(int value)
{
Element *newElem = new Element(value);
if (head == NULL)
{
head = newElem;
tail = newElem;
}
else
{
newElem->setNext(head);
head = newElem;
}
// No need to delete newElem, it is not a temporary object
}

A linked node that has 2 items in a single node

How can I create a linked node so that each linked node contains 2 items in a single node? Im not sure if I'm going in the right direction. I have 2 private members in my class, and I'm not sure if I need 2 set functions or if I can have a single set function with 2 parameters. For example void setItem(const string& anItem, const string secondItem);
#ifndef _NODE
#define _NODE
#include<string>
using namespace std;
class Node
{
private:
string item; // A data item
Node* next; // Pointer to next node
public:
Node();
Node(const string& anItem);
Node(const string& anItem, Node* nextNodePtr);
void setItem(const string& anItem);
void setNext(Node* nextNodePtr);
string getItem() const ;
Node* getNext() const ;
}; // end Node
#include "Node.cpp"
#endif
This is my Node.cpp file:
#include "Node.h"
#include <cstddef>
#include<string>
using namespace std;
Node::Node() : next(nullptr)
{
} // end default constructor
Node::Node(const string& anItem) : item(anItem), next(nullptr)
{
} // end constructor
Node::Node(const string& anItem, Node* nextNodePtr) :
item(anItem), next(nextNodePtr)
{
} // end constructor
void Node::setItem(const string& anItem)
{
item = anItem;
} // end setItem
void Node::setNext(Node* nextNodePtr)
{
next = nextNodePtr;
} // end setNext
string Node::getItem() const
{
return item;
} // end getItem
Node* Node::getNext() const
{
return next;
} // end getNext
For me, I'd go for two public functions for setting the two items of the node. One function will modify only one item, while the other function will modify the two item. Like:
// Function that will only set one item
void Node::setIndexItem(const int propNum, const string val)
{
if (propNum == 1) { // You may use 0 for the first item
this.item = val;
} else if (propNum == 2) { // You may use 1 for the second item
this.item2 = val;
} else {
// You may want to raise an exception here. Depends on you really.
}
}
// Function that will set the two items
void Node::setItems(const string val1, const string val2)
{
this.item = val1;
this.item2 = val2;
}
In your case, I would create a dedicated class for the data
struct DataNode
{
std::string key;
std::string value;
};
That separates class responsabilities (List may be focussed to link node).
That would allow you to modify data type without changing your class List (a templated list would be even better, but out of scope).
And then, your Node class would be something like:
class Node
{
private:
DataNode data;
Node* next; // Pointer to next node // I assume you can't use unique_ptr :-/
public:
Node();
Node(const DataNode& data);
Node(const DataNode& data, Node* nextNodePtr);
// Rule of 3
Node(const Node& rhs);
~Node();
Node& operator =(const Node& rhs);
// data accessor
void setItem(const DataNode& data);
const DataNode& getItem() const;
DataNode& getItem();
// Internal utility
void setNext(Node* nextNodePtr);
const Node* getNext() const;
Node* getNext();
};
I added a non-const version of the getter to allow modifying part of the item:
node.getItem().value = "new value";

Implementing a doubly linked list copy constructor in C++

I'm having trouble figuring out how to implement a copy constructor for doubly linked lists. The code I have so far is incorrect, I believe, because I lose track of the header node, but I'm not sure how to rectify this. Any help would be much appreciated!
DoublyLinkedList.h
#include <cstdlib>
#include <iostream>
using namespace std;
class DoublyLinkedList; // class declaration
// list node
class DListNode {
private:
int obj;
DListNode *prev, *next;
friend class DoublyLinkedList;
public:
DListNode(int e = 0, DListNode *p = NULL, DListNode *n = NULL)
: obj(e), prev(p), next(n) {}
int getElem() const { return obj; }
DListNode * getNext() const { return next; }
DListNode * getPrev() const { return prev; }
};
// doubly linked list
class DoublyLinkedList {
protected:
DListNode header, trailer;
public:
DoublyLinkedList() : header(0), trailer(0) // constructor
{ header.next = &trailer; trailer.prev = &header; }
DoublyLinkedList(const DoublyLinkedList& dll); // copy constructor
~DoublyLinkedList(); // destructor
DoublyLinkedList& operator=(const DoublyLinkedList& dll); // assignment operator
DListNode *getFirst() const { return header.next; } // return the pointer to the first node
const DListNode *getAfterLast() const { return &trailer; } // return the pointer to the trailer
bool isEmpty() const { return header.next == &trailer; } // return if the list is empty
int first() const; // return the first object
int last() const; // return the last object
void insertFirst(int newobj); // insert to the first of the list
int removeFirst(); // remove the first node
void insertLast(int newobj); // insert to the last of the list
int removeLast(); // remove the last node
};
// output operator
ostream& operator<<(ostream& out, const DoublyLinkedList& dll);
DoublyLinkedList.cpp - Copy Constructor
// copy constructor
DoublyLinkedList::DoublyLinkedList(const DoublyLinkedList& dll)
{
// Initialize the list
header = 0;
trailer = 0;
header.next = &trailer;
trailer.prev = &header;
// Copy from dll
DListNode* head = new DListNode;
head->prev = dll.header.prev;
head->obj = dll.header.obj;
head->next = dll.header.next;
DListNode* tail = new DListNode;
tail->prev = dll.trailer.prev;
tail->obj = dll.trailer.obj;
tail->next = dll.trailer.next;
DListNode* curr = new DListNode;
curr->prev = head;
while(curr != tail) {
DListNode* n = new DListNode;
curr->next = n;
n = curr->prev->next;
curr = curr->next;
}
curr = tail;
}
Rather than writing specific code to copy the list in dll using the internal structure, why not just loop through the list in dll as you normally would (using dll.getFirst() and dll.getAfterLast()) and just call insertLast with each value.