Parameterized Constructor for Node Based Linked List - c++

I'm in CS2 and we're just learning about linked lists and I have to code the parameterized constructor of a linked list class (node based). I don't really understand the node lists, so any help of what's going on here or how to approach would be helpful! I have the following Node class given:
class Node {
friend class NodeList;
public:
Node() : m_next(NULL) {}
Node(const DataType& data, Node* next = NULL) :
m_next(next), m_data(data) {}
Node(const Node& other) : m_next(other.m_next),
m_data(other.m_data) {}
DataType& data() { return m_data; }
const DataType& data() const { return m_data; }
private:
Node* m_next;
DataType m_data;
};
and I'm trying to create the parameterized constructor for the following class:
Class NodeList {
public:
NodeList();
NodeList(size_t count, const int value);
private:
Node* m_head;
}
, where the parameterized constructor is supposed to have 'count' nodes initialized to 'value'.
Thank you!

Solving a problem like this has 3 parts.
Break the problem down into smaller, simpler tasks that make it easier to solve
Do the smaller tasks
Use them to solve the big problem.
What would make it easy to solve this problem? Adding one value to a list is easier than adding multiple values to a list, so let's write a function to do that.
To add one value at the beginning of the list,
We can create a new node with that value
We have the new node point to the current first node
We set the current first node to the new node.
Let's call our function prepend, since it prepends the value to the list.
class NodeList {
public:
// The head should be set to null initially
NodeList()
: m_head(nullptr)
{
}
// This function takes a value and adds it to the beginning of the list
void prepend(const DataType& value) {
// The new node uses the current head as the next value
Node* newNode = new Node(value, m_head);
// We set the current head to the new node.
m_head = newNode;
}
Now, adding a value multiple times is easy. We can just call prepend once for each time we want to add an item.
class NodeList {
public:
// The head should be set to null initially
NodeList()
: m_head(nullptr)
{
}
// This function takes a value and adds it to the beginning of the list
void prepend(const DataType& value) {
// The new node uses the current head as the next value
Node* newNode = new Node(value, m_head);
// We set the current head to the new node.
m_head = newNode;
}
NodeList(size_t count, const DataType& value)
: m_head(nullptr) // The head still has to be null initially
{
for(size_t i = 0; i < count; i++)
{
prepend(value);
}
}
};

Related

C++ linked list Segmentation fault and valgrind errors

i need to code a linked list for university in c++, mostly to practice coding iterators.
I tested it with some basic cases and it works but after i pass it in valgrind and the test server for the program i get a list of different errors. Maybe somebody can help me not to despair.
(At the end i will append the error list)
template <typename T = float>
class ForwardList
{
struct Node
{
/// Constructs a Node from a data value and a link to the next element.
Node(const T &data, Node *next) : data{data}, next{next} {}
/// A Node owns all nodes after it, so it deletes them on destruction
~Node() { delete next; }
//Performs a deep copy of the Node and all Nodes after it. Bad practice but we got it like that
Node *clone() const
{
if (next == nullptr)
{
return new Node{data, nullptr};
}
else
{
return new Node{data, next->clone()};
}
}
T data;
Node *next;
};
public:
ForwardList() : head(nullptr) {}
/// Copy constructor performs a deep copy of the other list's Nodes
ForwardList(const ForwardList &other)
{
head = other.head->clone();
}
/// Destructor makes sure that all Nodes are correctly destroyed
~ForwardList()
{
while (head->next != nullptr)
{
Node *tmp = head;
head = head->next;
delete tmp;
}
delete head;
}
/// Copy assignment operator uses the copy-and-swap idiom to make a safe
/// assignment
ForwardList &operator=(ForwardList other)
{
swap(*this, other);
return *this;
}
/// Add an element to the front of the list.
void push_front(const T &value)
{
std::cout << "Num: " << numberOfNodes << std::endl;
Node *item = new Node(value, nullptr);
if (head==nullptr)
{
head = item;
}else
{
item->next=head;
head = item;
}
numberOfNodes++;
}
/// Remove the first element of the list. Calling this function on an empty
/// list is undefined behavior. When implementing this function, be careful
/// to delete the one and only the one element that is removed.
void pop_front()
{
Node *item;
item = head->next;
delete head;
head = item;
numberOfNodes--;
}
/// Get a reference to the first element of the list
/// (const and non-const version)
T &front()
{
return head->data;
}
const T &front() const
{
return head->data;
}
/// Return true is the list is empty
bool empty() const
{
return numberOfNodes == 0 ? true : false;
}
std::size_t size() const
{
return numberOfNodes;
}
friend void swap(ForwardList &l, ForwardList &r)
{
Node *tmp = l.head;
l.head = r.head;
r.head = tmp;
}
private:
Node *head;
size_t numberOfNodes = 0;
};
And now the fun part (i will put it on pastebin because its pretty long):
https://pastebin.com/4JAKkJtP
Your issue is that ~Node tries to delete its next, and you also try to walk the list in ~ForwardList. By deleting ~Node(), you let ForwardList handle cleanup and everything works.
The clue here is that valgrind reported use after free, meaning something was deleting a pointer twice. That was a clue to look at everything that deletes a Node* (or really, delete in general).

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.

Making a copy constructor more flexible for ADT queue

I have constructed a copy constructor for an ADT queue. The copy constructor works fine. I would want to improve my code, but I don't really know how to shorten it to make it more flexible. Code is given below:
template <typename T>
Queue <T>::Queue(const Queue & other)
{
if (other.first == nullptr)
{
first = nullptr;
nrOfElements = 0;
}
else
{
Node* saveFirst;
Node* walker;
first = other.first;
walker = new Node(first->data);
saveFirst = walker;
while (first->next != nullptr)
{
walker->next = new Node(first->next->data);
walker = walker->next;
first = first->next;
}
walker->next = nullptr;
first = saveFirst;
}
this->nrOfElements = other.nrOfElements;
}
The class Queue also contains an inner private Node class which contains the pointers first, next, etc:
private:
int nrOfElements;
class Node
{
public:
Node* next;
T data;
Node(T data)
{
this->data = data;
}
};
Node* first;
So, I would appreciate any suggestions/examples of how the copy constructor code above could be improved, as I'm a bit lost on the task.
try this one
may be in easier than your code
template <typename T>
Queue <T>::Queue(const Queue & other)
{
Front =NULL;Rear=NULL;Count=0;
Node *p= other.Front;
while(p!=NULL){
EnQueue(p->GetData());
Rear->SetData(p->GetData());
p=p->next;
}
}
First we set NULL value to Front & Rear and 0 for Count second make new Node to get the data from every Node in old Queue and copy it to the new Queue.

Copy Constructor for Simple Single Linked List including Nodes C++

I'm not very good at this, and I am a bit stuck making the copy constructor for a single linked list and the nodes that go with it.
Here is my header file:
#pragma once
#include <iostream>
using namespace std;
class Node
{
public:
int data;
Node* next;
Node()
{
next = NULL;
data = 0;
}
Node(const Node& copyNode); /*: data(copyNode.data), next(copyNode.next ? new Node(*copyNode.next) : NULL)*/
};
class SLLIntStorage
{
public:
Node* head;
Node* current;
Node* tail;
void Read(istream&);
void Write(ostream&);
void setReadSort(bool);
void sortOwn();
void print();
void mergeSort(Node**);
Node *merge(Node*, Node*);
void split(Node*, Node**, Node**);
bool _sortRead;
int numberOfInts;
SLLIntStorage(const SLLIntStorage& copying) //: head(copying.head ? new Node(*copying.head) : NULL)
{
}
SLLIntStorage(void);
~SLLIntStorage(void);
};
inline ostream& operator<< (ostream& out, SLLIntStorage& n)
{
n.Write(out);
return out;
}
inline istream& operator>> (istream& in, SLLIntStorage& s)
{
s.Read(in);
return in;
}
Could anyone give me a hand on understanding how this works and what I could do to create it? Thank you.
To copy a linked list, you must iterate the entire linked list and make a copy of each of the nodes, and append that to the new list. Remember that you don't just copy the pointers, but you must copy the entire Node structure and any data that needs copying as well (e.g. if the datas are pointers, you'll need to do deep copying on those too).
So here's an example copy constructor for your SLLIntStorage class:
SLLIntStorage(const SLLIntStorage& copying) : head(NULL)
{
Node* cur = copying.head;
Node* end = NULL;
while (cur)
{
Node* n = new Node;
n->data = cur->data;
if (!head) {
head = n;
end = head;
} else {
end->next = n;
end = n;
}
cur = cur->next;
}
}
Note that I didn't take into account the tail and current data members, etc. You'll have to account for those.
As it is homework, I will try to give the idea from which you can figure out what you need to do with the copy constructors.
Node(const Node& copyNode) : data(copyNode.data),
next(copyNode.next)
{
// ....
}
In the above snippet you are just actually making the next to point the location copyNode::next is pointing to. So, you run in to problems when any of the pointer deallocates the resource it is pointing to leaving the other dangling.
So, you should make the pointer next each instance to point to a location it independently holds. So, -
Node(const Node& copyNode) : data(copyNode.data),
next(new Node)
{
(*next) = *(copyNode.next) ;
// ....
}
Also read this thread which has an excellent explanation - Rule of Three

C++ new pointer from pointer to pointer?

I have a template linkedList that I would like to dynamically create "head" pointers for...
I seem unable to get any syntax to work.. my best guess is:
linkedList<int>** ptr;
ptr = new (linkedList<int>*)[1];
But it doesn't work. I'm fairly new to C++ so any help is appreciated! Thanks!
To get a pointer, do:
T* ptr = new T;
where T is your type.
For a pointer-to-pointer, do:
T** ptrptr = new T*;
allocating the space for one pointer, which still needs to be filled like the first method:
*ptrptr = new T;
Now you got a valid pointer-to-pointer.
Is there some reason you are not using std::list? (or std::forward_list)
Check out the header files for std::list, or your nearest C++ book, or in fact
cppreference.com
Your linked list class template should have a function to return the head of the list. Look at std::list::begin() in your compiler's c++ library. The std::list::iterator type is a pointer to whatever goes in the list. (ie T*)
Though I'm not sure pointer array is really needed for your linked
list, as for just new construct, the following form will be compiled.
ptr = new (linkedList<int>*[1]);
EDIT:
This allocates pointer array:
linkedList<int>** ptr = new (linkedList<int>*[1]);
This allocates array:
linkedList<int>* ptr = new linkedList<int>[1];
This allocates one element:
linkedList<int>* ptr = new linkedList<int>;
Normally the head of a linked list would look something like:
node<int> *head = NULL;
When you want to create and insert a node, you'd use something like:
insert(node<int> *&list, int value) {
// insert new node containing `value` at head of `list`.
node<int> *temp = new node(value);
temp->next = list;
list=temp;
}
You could use this something like:
node<int> *list = NULL;
for (int i=0; i<10; i++)
insert(list, i);
Of course, unless this is for homework (or something on that order), you should stop working on this immediately, and just std::list (or boost::slist, if you want a singly-linked list).
Edit: I'm adding more detail mentioned by the OP in comment. For the moment, the avl_tree::insert does not attempt to maintain balance. It's just a plain-jane un-balanced insert, but it should be adequate to demonstrate what we care about at the moment.
template <class T>
struct linked_list {
node *head;
void insert(T v) {
node<T> *n = new node(v, head);
head = n;
}
linked_list() : head(NULL) {}
template <class T>
struct node {
node *next;
T data;
node(T const &v, node *n=NULL) : data(v), next(n) {}
};
};
template <class keyType, class dataType>
class avl_tree {
struct node {
node *left, *right;
char balance;
keyType key;
dataType data;
node(keyType const &k, dataType const &d)
: left(NULL), right(NULL), balance(0), key(k), data(d)
{ }
bool operator<(node const &other) {
return key < other.key;
}
} *root;
bool insert(node const *new_node, node *&tree) {
if (tree == NULL) {
tree = new_node;
return true;
}
else if (*new_node < *tree)
return insert(new_node, tree->left);
else if (*new_node > *tree)
return insert(new_node, tree->right);
else // new_node == tree
return false; // couldn't insert -- already present.
}
public:
avl_tree() : root(NULL) {}
void insert(keyType const &key, dataType const &data) {
node *temp = new node(key, data);
insert(temp, root);
}
};