A linked node that has 2 items in a single node - c++

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

Related

Recursive remove in linked list

I am trying to remove the element from linked list recursively, but the remove function is not working. I need some help in solving this.
My node.h function
#ifndef NODE_
#define NODE_
template<class ItemType>
class Node {
private:
ItemType item; // A data item
Node<ItemType>* next; // Pointer to next node
public:
Node();
Node(const ItemType& anItem);
Node(const ItemType& anItem, Node<ItemType>* nextNodePtr);
void setItem(const ItemType& anItem);
void setNext(Node<ItemType>* nextNodePtr);
ItemType getItem() const;
Node<ItemType>* getNext() const;
}; // end Node
#include "Node.cpp"
#endif
My node.cpp file:
#include "Node.h"
template<class ItemType>
Node<ItemType>::Node() : next(nullptr)
{
} // end default constructor
template<class ItemType>
Node<ItemType>::Node(const ItemType& anItem) : item(anItem), next(nullptr)
{
} // end constructor
template<class ItemType>
Node<ItemType>::Node(const ItemType& anItem, Node<ItemType>* nextNodePtr) :
item(anItem), next(nextNodePtr)
{
} // end constructor
template<class ItemType>
void Node<ItemType>::setItem(const ItemType& anItem)
{
item = anItem;
} // end setItem
template<class ItemType>
void Node<ItemType>::setNext(Node<ItemType>* nextNodePtr)
{
next = nextNodePtr;
} // end setNext
template<class ItemType>
ItemType Node<ItemType>::getItem() const
{
return item;
} // end getItem
template<class ItemType>
Node<ItemType>* Node<ItemType>::getNext() const
{
return next;
} // end getNext
My main function:
#include <iostream>
#include "Node.h"
using namespace std;
// Function to insert an item into the front of a linked list
template<class T>
void insert(Node<T>* &headPtr, const T& entry)
{
// Create a new node and have the next pointer point to current front
Node<T> *newNodePtr = new Node<T>( entry , headPtr );
// Current front now becomes this new node
headPtr = newNodePtr;
}
// Recursive function to remove an item from a linked list
// Returns true if the operation was done; false, otherwise
template< typename T >
bool removes(Node<T>* &nodePtr, T target)
{
if(!nodePtr)
{
return false;
}
if(nodePtr->getNext() != NULL)
{
Node<T>*next = nodePtr->getNext();
removes(next,target);
if(nodePtr->getNext()->getItem()==target)
{
Node<T>*del = nodePtr;
nodePtr->setNext(nodePtr->getNext()->getNext());
delete del;
return true;
}
//nodePtr->setNext(nodePtr->getNext());
}
}
// Recursive function to display the contents of a linked list
// in the reverse order.
template<class T>
void display(Node<T> *currNodePtr)
{
// YOUR CODE GOES HERE - CHECK YOUR NOTES!
Node<T> *curr=currNodePtr;
if(curr!=NULL)
{
cout<<curr->getItem();
display(curr->getNext());
}
cout<<endl;
}
int main()
{
// (1) Declare an empty linked list of unsigned values
// based on the Node class and call it myList
Node<unsigned>*myList;
// (2) Read in values from standard input. Non-negative
// values are inserted into myList and a negative
// value terminates input.
int data=0;
unsigned k;
while(cin>>data)
{
if (data>=0)
{
k=data;
insert(myList,k);
}
else
{
break;
}
}
cout<<"out of loop";
// (3) Display the contents of the linked list myList
// in the order they were entered (hence, the display()
// function displays myList in reverse order!
display(myList);
// (4) Read in values from standard input. Non-negative
// values are removed from myList and a negative
// value terminates input.
int data1=0;
unsigned m;
while(cin>>data1)
{
if (data1>=0)
{
m=data1;
removes(myList,m);
}
else
{
break;
}
}
// (5) Display the contents of the linked list myList
// in the order they were entered (hence, the display()
// function displays myList in reverse order!
cout<<endl;
display(myList);
}
The remove function is in main. It is not removing the correct element. For example, in the list of 1 2 3 4 5, if I try to remove 3 it is removing 2.

How do you use access the information from a string*?

I am using a doubly linked list and I am trying to use the data that is passed by reference to insert a node before said data. I've used string* data = new string(s); to allocate memory however, when I try to use data I get an error.
#ifndef __DOUBLYLINKEDLIST_H__
#define __DOUBLYLINKEDLIST_H__
//
//
#include
#include
using namespace std;
class DoublyLinkedList {
public:
DoublyLinkedList();
~DoublyLinkedList();
void append (const string& s);
void insertBefore (const string& s);
void insertAfter (const string& s);
void remove (const string& s);
bool empty();
void begin();
void end();
bool next();
bool prev();
bool find(const string& s);
const std::string& getData() const;
private:
class Node
{
public:
Node();
Node(const string& data);
~Node();
Node* next;
Node* prev;
string* data;
};
Node* head;
Node* tail;
Node* current;
};
void DoublyLinkedList::insertBefore(const string& s)
{
Node* ptr = head;
string* data = new string(s);
if (head == NULL)
{
append(s);
return;
}
if (head == current)
{
//this is where I get an error...
this->data= new Node();
current->prev = head;
current = head;
return;
}
There is no reason to use a pointer to a string, which forces you to manage memory. Use a simple string instead.
But this is not the problem here. Here a local variable has the same name than a class member of a Node , and the member in node gets never initalized. Furtherthermore the DoublyLinkedList has itself no such member, so this->data is unknown. See my comments here:
void DoublyLinkedList::insertBefore(const string& s)
{
...
string* data = new string(s); // --> ok, but this is local variable
if (head == NULL)
{
append(s);
return; // ouch !!! memory leak !! data pointer is never freed
}
if (head == current)
{
//this is where I get an error...
this->data= new Node(); // --> 'this' is a DoublyLinkedList, not a Node
...
return;
}
Now this being said, is it possbile that you make a confusion between the DoublyLinkedList and the nodes it contains ? See here a start of correction, but you need to do more to handle the linking between the nodes:
void DoublyLinkedList::insertBefore(const string& s)
{
Node* ptr = head;
if (head == NULL)
{
append(s);
return;
}
if (head == current)
{
string* data = new string(s);
Node nd = new Node();
nd->data = data; // initialize node's pointer
nd->prev = ... // you need to link new node to the rest
nd->next = ...
... // and you need to update the previous and next node
return;
}
Now, as said in the first place, replace the pointer to string with a string. At least, you'll avoid leaking memory, shallow copies, and lots of other troubles. Then you can focus better on the real problems of a linked list data structure.

How do I fix the "error: lvalue required as left operand of assignment"

I am attempting to create a doubly linked list and use a function which accepts a value passed by reference. However, when I try to access the value it throws an error. I am getting the "error: lvalue required as left operand of assignment &da= NULL;"
I have tried:
#ifndef __DOUBLYLINKEDLIST_H__
#define __DOUBLYLINKEDLIST_H__
//
//
#include
#include
using namespace std;
class DoublyLinkedList {
public:
DoublyLinkedList();
~DoublyLinkedList();
void append (const string& s);
void insertBefore (const string& s);
void insertAfter (const string& s);
void remove (const string& s);
bool empty();
void begin();
void end();
bool next();
bool prev();
bool find(const string& s);
const std::string& getData() const;
private:
class Node
{
public:
Node();
Node(const string& data);
~Node();
Node* next;
Node* prev;
string* data;
};
Node* head;
Node* tail;
Node* current;
};
DoublyLinkedList::Node::Node(const string& da)
{
this->data=nullptr;
this->next=nullptr;
this->prev=nullptr;
&da= NULL;
}
The line
&da= NULL;
is trying to set NULL to the address of the variable da. You can't do that.
You might mean
this->data = &da;
which would work (as in, compile), but would probably cause errors if the string passed as data goes out of scope before your list does (which is very likely).
What you probably actually want, if you're going to use a string*, is
this->data = new string(da);
which dynamically allocates a new string, giving it da to copy from. In the destructor, you'd then want something like
if (data != nullptr) delete data;
I'm not a Standards guy, so can't give you the technical explanation of lvalues and such.

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.

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
}