template<typename T>
LinkedStack<T>::LinkedStack(const LinkedStack<T> &other) {
Node<T> *temp = other.stktop;
if (other.stktop != nullptr) {
Node<T> *newnode = new Node<T>;
newnode = temp;
while (temp->next != nullptr) {
temp = temp->next;
newnode->next = temp;
}
}
}
This is my copy constructor.
template <typename U>
struct Node {
U data;
Node<U> *next;
};
Node<T> *stktop;
and this is my struct node located in private section of my LinkedStack Class.
I tried following the logic for writing the copy constructors and I came up with this code.However it doesn't work.Any idea what is wrong?
Something like that:
template<typename T>
LinkedStack<T>::LinkedStack(const LinkedStack<T> &other)
{
// Create first node
if (!other.stktop) // Use pointer to bool cast
{
stktop = new Node<T>;
// Copy data. This is the simplest copy if U support it.
stktop->data = other.stktop->data;
}
else
{
stktop = nullptr; // Very important otherwise its value is undefined
return;
}
auto pothernode = other.stktop;
auto pthisnode = stktop;
// Iterate overall the elements
while (pothernode->next)
{
pthisnode->next = new Node<T>;
pthisnode->next->data = pothernode->next->data;
pothernode = pothernode->next;
pthisnode = pthisnode->next;
}
}
Note that all the nodes are allocated on the heap so do not forget to delete them. I suggest to use std::unique_ptr or std::shared_ptr instead of pure pointer.
Some possible optimization:
template<typename T>
LinkedStack<T>::LinkedStack(const LinkedStack<T> &other)
{
const auto& pothernode = other.stktop;
auto& pthisnode = stktop;
pthisnode = nullptr;
// Iterate overall the elements
while (pothernode)
{
pthisnode = new Node<T>;
pthisnode->data = pothernode->data;
pothernode = pothernode->next;
pthisnode = pthisnode->next;
}
}
Related
I don't know where I am wrong, when I debugged the code I found out that the 'new node' address is 'new node' address, basically the new node is referring to itself
void insertend(struct node *parent, int item)
{
while (parent->addr != NULL)
parent = parent->addr;
struct node new_node;
new_node.a = item;
parent->addr = &new_node;
parent->addr->addr = NULL;
}
void insertend(struct node *parent, int item)
{
while (parent->addr != NULL)
parent = parent->addr;
struct node new_node;
new_node.a = item;
parent->addr = &new_node;
parent->addr->addr = NULL;
}
The lifetime of new_node is limited to the function. Once that function returns, it is no longer valid.
In order to circumvent this, it is necessary to dynamically allocate memory for new_node. Of course, as already pointed out, this means explicitly deallocating the memory eventually.
Note: as this is C++ rather than C, we do not need to add struct to the front of the type in use, and NULL is better spelled nullptr.
void insertend(node *parent, int item)
{
while (parent->addr != nullptr)
parent = parent->addr;
node *new_node = new node;
new_node.a = item;
parent->addr = new_node;
parent->addr->addr = nullptr;
}
As C++ structs are just classes with default public access, it's also worth noting we could implement this as a member function. Something like:
template <typename T>
struct Node {
T value;
Node<T> *next;
void append(T val) {
Node<T> * temp = this;
while (temp->next != nullptr) {
temp = temp->next;
}
temp->next = new Node<T>;
temp->next->value = val;
temp->next->next = nullptr;
}
};
int main() {
auto n = Node<int>();
n.value = 27;
n.append(42);
n.append(34);
for (Node<int> *t = &n; t != nullptr; t = t->next) {
std::cout << t->value << std::endl;
}
return 0;
}
The next step would be implementing a constructor and destructor.
One more thing to keep in mind is that getting to the end of a list this way is O(n) time complexity. Doing it over and over again is costly. If you have Node::append return a pointer to the new Node, then you can call append on that.
template <typename T>
struct Node {
T value;
Node<T> *next;
Node<T> *append(T val) {
Node<T> * temp = this;
while (temp->next != nullptr) {
temp = temp->next;
}
temp->next = new Node<T>;
temp->next->value = val;
temp->next->next = nullptr;
return temp->next;
}
};
int main() {
auto n = Node<int>();
n.value = 27;
auto n2 = n.append(42);
n2 = n2->append(34);
n2 = n2->append(15);
for (Node<int> *t = &n; t != nullptr; t = t->next) {
std::cout << t->value << std::endl;
}
return 0;
}
I’m not sure what the addr refers to, but I would assume it points to the next node in the linked list. In your code, there needs to be another node to use as a temporary node, because the parent node keeps being reassigned, and the previous items are lost. We also need to check that the parent node is not NULL.
void insertend(struct node **parent, int item)
{
node *new_node = new node;
new_node->a = item;
new_node->addr = NULL;
if(*parent == NULL)
{
*parent = new_node;
}
else
{
node *temp = *parent;
while (temp->addr != NULL)
temp = temp->addr;
temp->addr = new_node;
}
}
The if statement checks whether the parent node is NULL. If true, then we assign parent node to new_node. If false, then we go to the end of the list and assign the next node in the list to new_node.
As Igor correctly pointed out, your new node gets destroyed when the function finishes. So, in this context you could just allocate memory. You can use the new operator for this. However, you would need to explicitly free the memory, eventually.
void insertend(struct node *parent, int item)
{
while (parent->addr != NULL)
parent = parent->addr;
struct * new_node = new node;
new_node->a = item;
parent->addr = new_node;
parent->addr->addr = NULL;
}
I have just start C++ and learned about pointers and I need some hints.
The code is about splitting a forward list into two (*this and *other). I think I have gotten the finding mid point right but I am really confuse about the pointers at the end (causing errors). I think I might have pointed ptr to lists but I am not sure. Can someone please giving me some ideas.
template <typename T>
class Forward_list
{
public:
class Node
{
public:
// A node will hold data of type T
T data{};
// next will point to the next node in the list
// we initialise next to nullptr
Node* next = nullptr;
Node(){}
Node(T input_data, Node* next_node= nullptr)
{
data = input_data;
next = next_node;
}
// Destructor
~Node(){}
};
private:
// private member variables for Forward_list
unsigned size_ = 0;
Node* head_ = nullptr;
template <typename T>
Forward_list<T> Forward_list<T>::split() {
Node* other = nullptr;
Node* tmp = this->head_;
struct Node* current = this->head_;
int length = this->size();
int mid = (length-1) / 2;
for(int i = 0; i < mid; i++) {
tmp = tmp->next;
}
*other = current->next;
current->next = nullptr;
return *this;
}
Not sure if this is enough to be understood. Thanks for the help.
Hi for my c++ assignment i have to implement a bunch of functions and one of them requires me to copy the values from a forward list and store them in a linked list. My university uses a website called Edstem to run and mark the code. It goes through a bunch of tests in a file called tests.hpp
I wrote up my code for this specific function in another IDE and it works perfectly and i got it to print out all the nodes in the linked list.
here is my code that I did in repl.it to figure out how to apply it to my assignment
and this is what i get after running the test on the edstem website
this is from the tests.hpp
#include <iostream>
#include <map>
#include<forward_list>
using namespace std;
#include <iostream>
using namespace std;
class Node {
public:
int data;
Node* next = nullptr;
};
int main() {
forward_list<int> flist1;
flist1 = {1,2,3,4,5,6,5,3,7,3,5,2,6,3,6,34,3,65,6};
Node * head = nullptr;
Node * temp = head;
for (auto it = flist1.begin() ; it != flist1.end(); it++){
if (head == nullptr){
head = new Node();
head->data = *it;
temp = head;
}else{
if(temp != nullptr){
temp->next = new Node();
temp->next->data = *it;
temp = temp->next;
}
}
//temp->next = new Node();
//temp->next->data = *it;
// temp = temp->next;
}
temp = head;
while (temp != nullptr){
cout << temp->data<< endl;
temp = temp->next;
}
}
Here is the function that I have to implement
// Constructor from initializer list
// ***For you to implement
// This implements the functionality you see with, for example,
// std::forward_list<int> my_list = {1,2,3}
// which creates a new linked list where the first node holds 1, second 2, and
// third 3.
// The {1,2,3} here is of type std::initializer_list<int> and you
// see this is the argument to this constructor (with data of type T
// rather than just int).
// You can access the elements of a std::initializer_list via an iterator
// for example you can cycle through all the elements with
// for(auto it = input.begin(); it!= input.end(); ++it){Do something with *it}
template <typename T>
Forward_list<T>::Forward_list(std::initializer_list<T> input)
{
head_ = nullptr;
Node * temp = head_;
for (auto it = input.begin(); it != input.end(); it++){
if (head_ == nullptr){
head_ = new Node(*it);
temp = head_;
}else{
if(temp != nullptr){
temp->next = new Node(*it);
temp = temp->next;
}
}
temp = head_;
}
}
#endif
here is the class for the Linked List, the relevant parts
template <typename T>
class Forward_list
{
public:
class Node
{
public:
// A node will hold data of type T
T data{};
// next will point to the next node in the list
// we initialise next to nullptr
Node* next = nullptr;
// Because we have already intialised the variables
// the default constructor doesn't need to do anything
Node(){}
// To make life easier we also provide a constructor
// that takes the T data to be copied into the data member variable
// There is an optional second argument which is
// used to update the next pointer. This defaults to nullptr
// if the constructor is called with just one argument.
Node(T input_data, Node* next_node= nullptr)
{
data = input_data;
next = next_node;
}
// Destructor
~Node(){}
};
private:
// private member variables for Forward_list
// the trailing underscore is a stylistic choice to
// distinguish these as private member variables
unsigned size_ = 0;
Node* head_ = nullptr;
and the test function that is used
void test_initializer_list(void)
{
std::initializer_list<int> inputs = {5,23,1,105,-2,7,88,0};
Forward_list<int> my_list {inputs};
std::forward_list<int> real_list {inputs};
for(unsigned i=8; i>0; --i)
{
assert(my_list.front() == real_list.front());
assert(my_list.size() == i);
real_list.pop_front();
my_list.pop_front();
}
}
Just remove the line
temp = head_;
at the end of the loop body. Otherwise you reset the node you're working with to the head node in every iteration regardless of whether you're at the first element or not.
Imho an alternative loop that doesn't have to consider 2 states would be preferable.
Additionally size_ is never set in the constructor for some reason.
Here are both the version of your implementation with the bug mentioned fixed and a version implemented from scratch.
Your version with fix
template <typename T>
Forward_list<T>::Forward_list(std::initializer_list<T> input)
: size_(input.size())
{
head_ = nullptr;
Node* temp = head_;
for (auto it = input.begin(); it != input.end(); it++) {
if (head_ == nullptr) {
head_ = new Node(*it);
temp = head_;
}
else {
if (temp != nullptr) {
temp->next = new Node(*it);
temp = temp->next;
}
}
}
}
My own version
template <typename T>
Forward_list<T>::Forward_list(std::initializer_list<T> input)
: size_(input.size()),
head_(nullptr)
{
auto it = input.begin();
auto const end = input.end();
if (it != end)
{
head_ = new Node(*it);
++it;
for (auto temp = head_; it != end; ++it)
{
auto next = new Node(*it);
temp->next = next;
temp = next;
}
}
}
I have this code, and I have to create a copy constructor for it to create a deep copy of the passed object. How can I create that?
template<typename T>
class SSL {
struct Node {
T data;
Node* next;
};
Node* head = nullptr;
public:
// ...
};
You simply need to iterate the source object's list, making new nodes that have copies of its data, eg:
template <typename T>
class SSL {
struct Node {
T data;
Node* next = nullptr;
Node(const T &value) : data(value) {}
};
Node* head = nullptr;
public:
// ...
SSL() = default;
SSL(const SSL &src) {
Node **n = &head;
for (Node *cur = src.head; cur; cur = cur->next) {
*n = new Node{cur->data};
n = &(n->next);
}
}
SSL(SSL &&src) : head(src.head) {
src.head = nullptr;
};
~SSL() {
Node *cur = head;
while (cur) {
Node *n = cur;
cur = cur->next;
delete n;
}
}
SSL& operator=(SSL rhs) {
std::swap(head, rhs.head);
return *this;
}
// ...
};
I'm trying to write Lined list in C++, but some tests fails.
One of those says:
GivenNonEmptyCollection_WhenMoveAssigning_ThenAllElementsAreMoved
And second:
GivenNonEmptyCollection_WhenMovingToOther_ThenAllItemsAreMoved
Here's how I implement operator=
LinkedList& operator=(const LinkedList& other)
{
if(this!=&other)
{
while (!isEmpty())
erase(begin());
for (auto it = other.begin(); it != other.end(); it++)
append(*it);
}
return *this;}
And second one:
LinkedList& operator=(LinkedList&& other)
{
/* SELF ASSIGNMENT CHECK */
if(this!=&other)
{
while (!isEmpty())
erase(begin());
while (!other.isEmpty())
{
append(*(other.begin()));
other.erase(other.begin());
}
}
return *this;
}
Here's something about class Linked list and struct Node:
template <typename Type>
class LinkedList
{
struct Node
{
Node* prev;
Node* next;
Type* data;
Node()
{
data = nullptr;
prev = nullptr;
next = nullptr;
}
Node(const Type val)
{
data = new Type(val);
prev = nullptr;
next = nullptr;
}
~Node()
{
prev = nullptr;
next = nullptr;
delete data;
}
};
private:
Node *head;
Node *tail;
size_type length;
public:
LinkedList(): head(nullptr), tail(nullptr), length(0)
{
head = new Node;
tail = new Node;
head->next = tail;
tail->prev = head;
}
(...)
I have no idea what's wrong with that.
You're copying and deleting the original list, but you should move it.
In this case, this means "stealing" the data from the other list.
It should look more like this:
LinkedList& operator=(LinkedList&& other)
{
if(this!=&other)
{
// Assuming the existence of 'LinkedList::clear', which empties the list.
// Replace with the name you chose for that function.
clear();
head = other.head;
other.head = nullptr;
tail = other.tail;
other.tail = nullptr;
length = other.length;
other.length = 0;
}
return *this;
}
and your move constructor should be changed similarly.