so I was trying to build this project on deque using the doubly linked list. but when I build it. it says build but gives threads and doesn't give the output as required.
I have re-implemented the major problem(copy constructor) and all the functions again and again but then it still gives me new threads every time.
this is the header file.
#pragma once
#include <stdexcept>
using namespace std;
class Node
{
public:
int data;
Node* next;
Node* previous;
Node();
Node(const int &x);
};
class Deque
{
public:
Deque();
Deque(const Deque &d);
Deque &operator= (const Deque &d);
~Deque();
void insertFront(const int &x);
void insertBack(const int &x);
int removeFront();
int removeBack();
int peekFront();
int peekBack();
bool empty() const;
int size()const;
friend ostream& operator << (ostream &out, const Deque &d);
private:
Node* front;
Node* rear;
};
this will be the .cpp (implementation file.)
//
// Deque_cmpt225.cpp
// Deque_cmpt225
//
// Created by Aryan Arora on 2017-10-09.
// Copyright © 2017 Aryan Arora. All rights reserved.
//
#include "Deque_cmpt225.h"
#include <iostream>
#include <stdexcept>
using namespace std;
Node:: Node()
{
previous = nullptr;
next = nullptr;
data = 0;
}
Node:: Node(const int &x)
{
Node();
data = x;
}
Deque:: Deque() //Empty Deque.
{
front = nullptr;
rear = nullptr;
}
Deque:: ~Deque()
{
if (this->empty())
return;
else{
Node* temp;
while (this->front->next != nullptr){
temp = this->front;
this->front = this->front->next;
delete temp;
}
temp = this->front;
this->front = nullptr;
this->rear = nullptr;
delete temp;
}
}
Deque:: Deque (const Deque &d) //Copy Constructor
{
if (d.empty()) //Deque is empty.
{
return;
}
Node* temp = d.front;
int x;
if (temp->next == nullptr) //Deque of just one node
{
x = temp->data;
Node *n1 = new Node (x);
n1->next = nullptr;
n1->previous = nullptr;
this->front = n1;
this->rear = n1;
}
else //Deque has more than one node
{
while (temp!= nullptr)
{
this->insertBack(temp->data);
temp = temp -> next;
}
}
}
Deque& Deque:: operator=(const Deque &d) //============================check again
{
if (this == &d)
return *this;
else
{
this->~Deque(); //DELETING THE DEQUE
Node* temp = d.front; //COPYING EACH NODE
while (temp != NULL)
{
this->insertBack(temp->data); //INSERTING AT THE BACK
temp = temp->next; //POINTING TEMP TO NEXT NODE
}
}
return *this;
}
void Deque:: insertFront(const int &x)
{
Node* temp = new Node(x);
temp->next = nullptr;
temp->previous = nullptr;
if (empty())
{
this->front = temp;
this->rear = temp;
}
else
{
temp->next = this->front;
temp->previous = nullptr;
this->front->previous = temp;
this->front = temp;
}
}
void Deque:: insertBack(const int &x)
{
Node* temp = new Node(x);
temp->next = nullptr;
temp->previous = nullptr;
if (empty())
{
this->front = temp;
this->rear = temp;
}
else
{
temp->next = nullptr;
temp->previous = this->rear;
this->rear->next = temp;
this->rear = temp;
}
}
int Deque:: removeFront()
{
if (empty()) //=================runtime error
{
throw std::runtime_error("The que is empty.");
}
else{
Node* temp;
temp = this->front;
int x = temp->data;
if ( this->front->next != nullptr )
{
this->front = this->front->next;
this->front->previous = nullptr;
}
else
{
this->front = nullptr;
this->rear = nullptr;
}
delete temp;
return x;
}
}
int Deque:: removeBack()
{
if (empty()) //=================runtime error
{
throw std::runtime_error("The que is empty.");
}
else{
Node* temp = this->rear;
int x = temp->data;
if ( this->rear->previous != nullptr )
{
this->rear = this->rear->previous;
this->rear->next = nullptr;
}
else
{
this->rear = nullptr;
this->front = nullptr;
}
delete temp;
return x;
}
}
int Deque:: peekFront()
{
if (empty()) //=================runtime error
{
throw std::runtime_error("The que is empty.");
}
else
{
return this->front->data;
}
}
int Deque:: peekBack()
{
if (empty()) //=================runtime error
{
throw std::runtime_error("The que is empty.");
}
else
{
return this->rear->data;
}
}
bool Deque:: empty() const
{
if (this->front == nullptr && this->rear == nullptr)
return true;
else
return false;
}
int Deque:: size() const
{
Node* temp = this->front;
int count = 0;
while (temp != nullptr)
{
count++;
temp = temp->next;
}
return count;
}
ostream& operator << (ostream &out, const Deque &d)
{
Node* temp = d.front;
out << "NULL -> ";
while (temp != nullptr)
{
out << temp->data << " <-> ";
temp= temp->next;
}
out << "<- NULL" << endl;
return out;
}
thanks in advance.
Your code has many problems..
Your Node constructor doesn't delegate properly..
Node::Node()
{
previous = nullptr;
next = nullptr;
data = 0;
}
Node::Node(const int &x)
{
Node(); //Creates a temporary node that gets destroyed immediately..
data = x;
}
It's much simpler if you change it to:
Node::Node() : Node(0) //Delegating constructor.
{
}
Node::Node(const int &x) : previous(nullptr), next(nullptr), data(x)
{
}
This point isn't really a problem, but worth mentioning.. You keep setting the Node pointers to nullptr right after construction. This is not necessary because your constructor already does that..
Node* temp = new Node(x);
temp->next = nullptr; //Not needed anymore with the above fixes.
temp->previous = nullptr; //Not needed anymore with the above fixes.
You never initialize your variables in the copy constructor..
In your constructor, you have (I changed it, but it has the same meaning):
Deque::Deque() : front(nullptr), rear(nullptr)
{
}
But in your copy constructor, you have:
Deque::Deque(const Deque &d)
{
//Other code here.. You never initialized front and rear to nullptr..
}
You never set front and rear to nullptr so empty() returns false since they are a "random" uninitialized value.. Then in insertBack you go on to access this and boom.. Access Violation.
To fix it, you do:
Deque::Deque(const Deque &d) : front(nullptr), rear(nullptr)
{
//Other code here..
}
Next issue is that your copy assignment operator is calling the destructor!
Deque& Deque::operator=(const Deque &d)
{
if (this == &d)
return *this;
else
{
this->~Deque() //YOU CANNOT DO THIS.. Create a private member function for cleaning up.. Then call that function in your destructor and call that function here.. You cannot invoke the destructor like this.
}
//....
}
Related
#include <iostream>
using namespace std;
template <typename Object>
struct Node
{
Object data;
Node* next;
Node(const Object &d = Object(), Node *n = (Object)NULL) : data(d), next(n) {}
};
template <typename Object>
class singleList
{
public:
singleList() { init(); }
~singleList() { eraseList(head); }
singleList(const singleList &rhs)
{
eraseList(head);
init();
*this = rhs;
print();
contains(head);
}
void init()
{
theSize = 0;
head = new Node<Object>;
head->next = (Object)NULL;
}
void eraseList(Node<Object> *h)
{
Node<Object> *ptr = h;
Node<Object> *nextPtr;
while (ptr != (Object)NULL)
{
nextPtr = ptr->next;
delete ptr;
ptr = nextPtr;
}
}
int size()
{
return theSize;
}
void print()
{
int i;
Node<Object> *current = head;
for(i=0; i < theSize; ++i){
cout << current->data << " ";
current = current->next;
}
}
bool contains(int x)
{
Node<Object> *current = head;
for (int i = 0; i < theSize; ++i){
if (current->data == x){
return true;
}
current = current -> next;
}
return false;
}
bool add(Object x){
if(!contains(x)){
Node<Object> *new_node = new Node<Object>(x);
new_node->data = x;
new_node->next = head;
head = new_node;
//head->next = new_node;
theSize++;
return true;
}
return false;
}
bool remove(int x)
{
if(contains(x)){
Node<Object> *temp = head;
Node<Object> *prev = NULL;
if(temp != NULL && temp ->data == x){
head = temp->next;
delete temp;
return 0;
}else{
while(temp != NULL && temp->data != x){
prev = temp;
temp = temp->next;
}
if(temp ==NULL){
return 0;
}
prev->next = temp->next;
delete temp;
}
return true;
//theSize--;
}
return false;
}
private:
Node<Object> *head;
int theSize;
};
int main()
{
singleList<int> *lst = new singleList<int>();
lst->add(10);
lst->add(12);
lst->add(15);
lst->add(6);
lst->add(3);
lst->add(8);
lst->add(3);
lst->add(18);
lst->add(5);
lst->add(15);
cout << "The original linked list: ";
lst->print();
cout << endl;
lst->remove(6);
lst->remove(15);
cout << "The updated linked list: ";
lst->print();
cout << endl;
cout << "The number of node in the list: " << lst->size() << endl;
return 0;
}
so the output is supposed to be the following:
The original linked list: 5 18 8 3 6 15 12 10
The update linked list: 5 18 8 3 12 10
The number of node in the list: 6
my output gives the original linked list part but then gives a segmentation fault (core dumped) error. I am not sure where my code is wrong but i think it is in my remove().
Some help will definitely be appreciated.
on line 109 i needed to decrement size.
bool remove(int x)
{
if(contains(x)){
Node<Object> *temp = head;
Node<Object> *prev = NULL;
if(temp != NULL && temp ->data == x){
head = temp->next;
delete temp;
return 0;
}else{
while(temp != NULL && temp->data != x){
prev = temp;
temp = temp->next;
}
if(temp ==NULL){
return 0;
}
prev->next = temp->next;
delete temp;
theSize--;
}
return true;
//theSize--;
}
return false;
}
Answer after second update:
had to fix the remove()
#include <iostream>
using namespace std;
template <typename Object>
struct Node
{
Object data;
Node* next;
Node(const Object &d = Object(), Node *n = (Object)NULL) : data(d), next(n) {}
};
template <typename Object>
class singleList
{
public:
singleList() { init(); }
~singleList() { eraseList(head); }
singleList(const singleList &rhs)
{
eraseList(head);
init();
*this = rhs;
print();
contains(head);
}
void init()
{
theSize = 0;
head = new Node<Object>;
head->next = (Object)NULL;
}
void eraseList(Node<Object> *h)
{
Node<Object> *ptr = h;
Node<Object> *nextPtr;
while (ptr != (Object)NULL)
{
nextPtr = ptr->next;
delete ptr;
ptr = nextPtr;
}
}
int size()
{
return theSize;
}
void print()
{
int i;
Node<Object> *current = head;
for(i=0; i < theSize; ++i){
cout << current->data << " ";
current = current->next;
}
}
bool contains(int x)
{
Node<Object> *current = head;
for (int i = 0; i < theSize; ++i){
if (current->data == x){
return true;
}
current = current -> next;
}
return false;
}
bool add(Object x){
if(!contains(x)){
Node<Object> *new_node = new Node<Object>(x);
new_node->data = x;
new_node->next = head;
head = new_node;
//head->next = new_node;
theSize++;
return true;
}
return false;
}
bool remove(int x){
Node<Object> *pCur = head;
Node<Object> *pPrev = pCur;
while (pCur && pCur->data != x) {
pPrev = pCur;
pCur = pCur->next;
}
if (pCur==nullptr) // not found
return false;
if (pCur == head) { // first element matches
head = pCur->next;
} else {
pPrev->next = pCur->next;
}
// pCur now is excluded from the list
delete pCur;
theSize--;
return true;
}
private:
Node<Object> *head;
int theSize;
};
int main()
{
singleList<int> *lst = new singleList<int>();
lst->add(10);
lst->add(12);
lst->add(15);
lst->add(6);
lst->add(3);
lst->add(8);
lst->add(3);
lst->add(18);
lst->add(5);
lst->add(15);
cout << "The original linked list: ";
lst->print();
cout << endl;
lst->remove(6);
lst->remove(15);
cout << "The updated linked list: ";
lst->print();
cout << endl;
cout << "The number of node in the list: " << lst->size() << endl;
return 0;
}
New to c++ and I'm having trouble implementing an Iterator class in my LinkedList. I have a Iterator class defined in the private section of my LinkedList class as follows:
cs_linked_list.h
#ifndef LINKED_LIST_H_
#define LINKED_LIST_H_
#include <initializer_list>
#include <iostream>
namespace cs {
template <typename T>
class LinkedList {
struct Node; // forward declaration for our private Node type
public:
/**Constructs an empty list.**/
LinkedList(){
head_ = nullptr;
}
/**
* #brief Constructs a list from a range.
*
*/
template <class InputIterator>
LinkedList(InputIterator first, InputIterator last) {
for (; first != last; ++first) this->push_back(*first);
}
/** Constructs a list with a copy of each of the elements in `init_list`, in the same order. */
LinkedList(std::initializer_list<T> init_list) {
this->operator=(init_list); // call initializer list assignment
}
/**Constructs a container with a copy of each of the elements in another, in the same order**/
LinkedList(const LinkedList<T>& another){
//TODO
this->operator=(another);
}
/** Destroys each of the contained elements, and deallocates all memory allocated by this list. */
~LinkedList() {
while (this->head_) {
Node* old_head = this->head_;
this->head_ = old_head->next;
delete old_head;
}
}
/**Returns the number of elements in this list.Node *head**/
size_t size() const{ //DONE
//TODO
Node *temp = head_;
size_t len = 0;
while (temp != nullptr){
len++;
temp = temp->next;
}
return len;
}
/**Returns whether the list container is empty (that is, whether its size is 0). **/
bool empty() const{ //DONE
if(size_ == 0){
return true;
} else{
return false;
}
}
/** Appends a copy of `val` to this list. */
void push_back(const T& val) {
Node* new_node = new Node{val};
if (this->size_ == 0) {
this->head_ = this->tail_ = new_node;
} else {
this->tail_->next = new_node;
new_node->prev = this->tail_;
this->tail_ = new_node;
}
++this->size_;
}
/** Prepends a copy of `val` to this list. */
void push_front(const T& val) {
Node* new_node = new Node{val};
if (this->size_ == 0) {
this->head_ = this->tail_ = new_node;
} else {
new_node->next = this->head_;
this->head_->prev = new_node;
this->head_ = new_node;
}
++this->size_;
}
/**Returns a reference to the value in the first element in this list.**/
T& front() const{
return head_->data;
}
/**Returns a reference to the value in the last element in this list. **/
T& back() const{
return tail_->data;
}
/**Deletes the first value in this list. **/
void pop_front(){
Node *temp = head_;
if(empty()){
return;
}
if(temp == tail_){
return;
}
head_ = head_->next;
if (head_ != nullptr) {
head_->prev = nullptr;
} else {
tail_ = nullptr;
}
delete temp;
}
/**Deletes the last value in this list**/
void pop_back(){
if(empty()){
return;
}
if(head_ == tail_){
return;
}
Node *temp = head_;
while(temp->next->next != nullptr){
temp = temp->next;
}
tail_ = temp;
delete tail_->next;
tail_->next = nullptr;
size_--;
}
/**resizes the list so that it contains n elements.**/
void resize(std::size_t n){
//TODO
for (size_t i = 0; i < n; i++){
push_back('\0');
}
}
/**resizes the list so that it contains n elements**/
void resize(std::size_t n, const T &fill_value){
//TODO
for (size_t i = 0; i < n; i++) {
push_back(fill_value);
}
}
/**Removes from the container all the elements that compare equal to val. **/
void remove(const T &val){
//TODO
Node *p1 = head_;
Node *p2 = nullptr;
if(p1 != nullptr && p1->data == val){
head_ = p1->next;
delete p1;
} else {
while (p1 != nullptr && p1->data != val){
p2 = p1;
p1 = p1->next;
}
if (p1 == nullptr) {
return;
}
p2->next = p1->next;
delete p1;
}
}
/**Removes duplicate values from this list**/
void unique(){
//TODO
Node *temp = head_;
while (temp != nullptr && temp->next != nullptr) {
Node *temp2 = temp;
while (temp2->next != nullptr) {
if (temp->data == temp2->next->data) {
Node *temp3 = temp2->next;
temp2->next = temp2->next->next;
delete temp3;
} else {
temp2 = temp2->next;
}
}
temp = temp->next;
}
}
/**Deletes all values in this list.**/
void clear(){
//TODO
while (head_ != nullptr){
Node *temp = head_;
head_ = head_->next;
delete temp;
}
tail_ = nullptr;
size_ = 0;
}
/**Reverses the order of the elements in this list.**/
void reverse(){
//TODO
Node *p1 = head_;
Node *p2 = nullptr;
while (p1 != nullptr) {
Node *temp = p1->next;
p1->next = p2;
p2 = p1;
p1 = temp;
}
head_ = p2;
}
/** Replaces the contents of this list with a copy of each element in `init_list`. */
LinkedList& operator=(std::initializer_list<T> init_list) {
this->size_ = 0;
for (auto&& val : init_list)
this->push_back(val);
return *this;
}
/**Replaces the contents of this list with a copy of each element in another, in the same order.**/
LinkedList& operator=(const LinkedList& another){
//TODO
if (this != &another) {
this->clear();
Node *temp = another.head_;
this->size_ = 0;
while (temp) {
this->push_back(temp->data);
temp = temp->next;
}
}
return *this;
}
/**Compares this list with another for equality.**/
bool operator==(const LinkedList &another){ //DONE
//TODO
auto comp = head_;
auto comp2 = another.head_;
while(comp != nullptr){
if(comp != comp2){
return false;
}
comp = comp->next;
comp2 = comp2->next;
}
return true;
}
/**Compares this list with another for inequality. **/
bool operator!=(const LinkedList &another){ //DONE
//TODO
auto comp = head_;
auto comp2 = another.head_;
while(comp != nullptr){
if(comp != comp2){
return true;
}
comp = comp->next;
comp2 = comp2->next;
}
return false;
}
/** Inserts this list into an ostream, with the format `[element1, element2, element3, ...]` */
friend std::ostream& operator<<(std::ostream& out, const LinkedList& list) {
out << '[';
for (Node* cur = list.head_; cur; cur = cur->next) {
out << cur->data;
if (cur->next)
out << ", ";
}
out << ']';
return out;
}private:
struct Node {
T data;
Node* next = nullptr;
Node* prev = nullptr;
};
Node* head_ = nullptr;
Node* tail_ = nullptr;
std::size_t size_ = 0;
class Iterator {
public:
using iterator_category = std::bidirectional_iterator_tag;
using value_type = T;
using difference_type = int;
using pointer = T*;
using reference = T&;
// Default constructor
Iterator() {
//TODO
n = nullptr;
}
// Copy constructor
Iterator(const Iterator& other) {
//TODO
this->operator=(other);
}
//Destructor if needed
~Iterator() {
//TODO
while (this->list.head_){
Node *old_head = this->list.head_;
this->list.head_ = old_head->next;
delete old_head;
}
}
// Copy assign
Iterator& operator=(const Iterator& that) {
//TODO
if(this != &that){
this->list.clear();
Node *temp = that.list.head_;
this->list.size_ = 0;
while (temp){
this->list.push_back(temp->data);
temp = temp->next;
}
}
return *this;
}
// Prefix increment
Iterator& operator++() {
//TODO
this->n = this->n->next;
return *this;
}
// Postfix increment
Iterator operator++(int) {
Iterator tmp(*this);
this->operator++();
return tmp;
}
// Prefix decrement
Iterator& operator--() {
//TODO
this->n = this->n->prev;
return *this;
}
// Postfix decrement
Iterator operator--(int) {
Iterator tmp(*this);
this->operator--();
return tmp;
}
// Inequality
bool operator!=(Iterator that) const {
return !(this->operator==(that));
}
// Equality
bool operator==(Iterator that) const {
//TODO
auto temp = list.head_;
auto temp2 = that.list.head_;
while(temp != nullptr){
if(*temp != *temp2){
return false;
}
temp = temp->next;
temp2 = temp2->next;
}
return true;
}
// lvalue dereference
T& operator*() const {
//TODO
return this->n->data;
}
// referring
Iterator* operator->() const {
return this;
}
Iterator begin(){
//TODO
return Iterator(list.head_->next);
}
Iterator end(){
//TODO
return Iterator(list.tail_);
}
private:
Node *n;
LinkedList<T> list;
};
};
} // namespace cs
#endif // LINKED_LIST_H_
Main:
#include "cs_linked_list.h"
#include <iostream>
int main() {
/***TESTING***/
cs::LinkedList<int> list;
// Add few items to the end of LinkedList
list.push_back(1);
list.push_back(2);
list.push_back(3);
std::cout << "Traversing LinkedList through Iterator" << std::endl;
for ( cs::LinkedList<int>::Iterator iter = list.begin();iter != list.end(); iter++) {
std::cout << *iter << " ";
}
std::cout << std::endl;
return 0;
}
Since my Iterator class is private I can't seem to implement my Begin() and End() functions. Should I Make it public or am I missing one crucial step. Instructions say to define a Iterator class in the private section of my LinkedList class.
I'm trying to implement a function in my linked list that pushes the values of one list into a stack, and then pops off those values into another list.
The problem is, when I try to std::cout << x, the first stack's topmost element, I get this error:
c:\mingw\lib\gcc\mingw32\8.2.0\include\c++\ostream:682:5: error: no type named 'type' in 'struct std::enable_if<false, std::basic_ostream<char>&>'
#include <iostream>
#include <cstddef>
#include <string>
#include <stack>
#include <vector>
using Item = std::string;
class List {
public:
class ListNode { //Changed this to public so I could access it. If this was in private how would I accomplish this?
public:
Item item;
ListNode * next;
ListNode(Item i, ListNode *n=nullptr) {
item = i;
next = n;
}
};
ListNode * head;
ListNode * tail; //Also in private, changed to public, so I could access it. This is the bottom boundry.
class iterator {
ListNode *node;
public:
iterator(ListNode *n = nullptr) {
node = n;
}
Item& getItem() { return node->item; }
void next() { node = node->next; }
bool end() { return node==nullptr; }
friend class List;
};
public:
List() {
// list is empty
head = nullptr;
tail = nullptr;
}
List(const List &other)
{
iterator o = other.begin();
while(!o.end())
{
append(o.getItem());
o.next();
}
}
bool empty() {
return head==nullptr;
}
// Only declared, here, implemented
// in List.cpp
void append(Item a);
bool remove (Item ©);
void insertAfter(iterator, Item);
void removeAfter(iterator, Item&);
iterator begin() const {
return iterator(head);
}
};
void List::append(Item a) {
ListNode *node = new ListNode(a);
if ( head == nullptr ) {
// empty list
head = node;
tail = node;
} else {
tail->next = node;
tail = node;
}
}
bool List::remove(Item ©)
{
if (!empty()) {
copy = head->item;
ListNode *tmp = head->next;
delete head;
head = tmp;
if (head==nullptr)
tail = nullptr;
return true;
}
return false;
}
void List::insertAfter(iterator it, Item item)
{
if (it.node == nullptr)
{
// insert at head
ListNode *tmp = new ListNode(item,head);
// if list is empty, set tail to new node
if (tail==nullptr) {
tail = tmp;
}
// set head to new node
head = tmp;
}
else
{
ListNode *tmp = new ListNode(item,it.node->next);
it.node->next = tmp;
// could be a new tail, if so update tail
if (tail==it.node) {
tail = tmp;
}
}
}
void List::removeAfter(iterator it, Item& item)
{
// emtpy list or at tail, just return
if (it.node == tail) return;
if (it.node == nullptr)
{
ListNode * tmp = head;
head = head->next;
delete tmp;
if (head==nullptr)
tail = nullptr;
}
else
{
ListNode *tmp = it.node->next;
it.node->next = tmp->next;
delete tmp;
// could be that it.node is the new nullptr
if (it.node->next == nullptr)
tail = it.node;
}
}
List reverse(const List &l)
{
List::iterator iter1 = l.begin();
std::stack<List::ListNode> first;
while(!(iter1.end())) {
first.push(iter1.getItem());
iter1.next();
}
List lthe3;
int z = first.size();
for (int i=0; i < z; ++i) {
List::ListNode x = first.top();
std::cout << x;
}
return l;
}
void printList(List &l) {
List::iterator i = l.begin();
while(!i.end()) {
std::cout << i.getItem() << ", ";
i.next();
}
std::cout << std::endl;
}
int main()
{
List l;
l.append("one");
l.append("two");
l.append("three");
l.append("four");
std::cout << "List in order: ";
printList(l);
List l2 = reverse(l);
std::cout << "List in reverse order: ";
printList(l2);
return 0;
}
I have no clue what I'm doing wrong, but I'm really close to finishing this function.
Is there any way I could get some feedback?
so I have this code for linked list below. I need to create copy/move constructors and operators.
I am having troubles how to make it the right way.
I know the code isn't perfect, I will appreciate all tips, but I want to focus mainly on copy/move semantic.
#include <iostream>
#include <string>
#include <stdexcept>
using namespace std;
class List {
class Node {
Node* next;
string text;
int index;
friend class List;
public:
Node(const string& value, int i) : next(nullptr), index(i), text(value) {}
friend ostream& operator<< (ostream& wy, const Node& wzl) {
if (wzl.next) return wy << wzl.text << ", " << *wzl.next;
else return wy << wzl.text;
}
};
Node* head;
int _size(Node* node, int size = 0) {
if (node == NULL) {
return size;
} else {
_size(node->next, size+1);
}
}
void _insert(Node* node, const string& value, int index) {
if (node->next == NULL || node->next->index > index) {
if (node->index == index) {
node->text = value;
} else {
Node* element = new Node(value, index);
element->next = node->next;
node->next = element;
}
} else {
_insert(node->next, value, index);
}
}
string _read(Node* node, int index) {
if (node->next != NULL && node->next->index <= index) {
return _read(node->next, index);
} else if (node->index == index) {
return node->text;
} else {
throw invalid_argument("No such index");
}
}
void _remove(Node* node, int index) {
if (node->next != NULL && node->next->index < index) {
_remove(node->next, index);
} else if (node->next->index == index) {
Node* temp;
if (node->next->next != NULL) {
int temp_index = node->next->next->index;
temp = new Node(node->next->next->text, temp_index);
if (node->next->next->next != NULL) {
temp->next = node->next->next->next;
} else {
temp->next = NULL;
}
temp->index = node->next->next->index;
} else {
temp = nullptr;
}
delete node->next;
node->next = temp;
} else {
throw invalid_argument("No such index");
}
}
public:
List() : head(nullptr){};
List(const List &lst) : head(nullptr) {
Node* tmp_lst = lst.head;
Node* tmp_this = this->head;
while (tmp_lst != NULL) {
// cerr << this->head->text;
tmp_this = new Node(tmp_lst->text, tmp_lst->index);
tmp_this = tmp_this->next;
tmp_lst = tmp_lst->next;
}
}
List(List&& lst);
List(initializer_list<string> lst) : List() {
Node* tmp;
int pos = 0;
for (auto element : lst) {
if (this->head != NULL){
tmp->next = new Node(element, pos);
tmp = tmp->next;
pos++;
} else {
this->head = new Node(element, pos);
tmp = this->head;
pos++;
}
}
};
List& operator= (const List& lst) {
if (this != &lst) {
delete this->head;
this->head = nullptr;
Node* tmp_lst = lst.head;
Node* tmp_this = this->head;
while (tmp_lst != NULL) {
tmp_this = new Node(tmp_lst->text, tmp_lst->index);
tmp_this = tmp_this->next;
tmp_lst = tmp_lst->next;
}
}
return *this;
}
List& operator= (List&& lst);
~List(){
delete head;
};
void insert(const string& value, int pos) {
if (pos < 0) {
throw invalid_argument("Position cant be negative");
}
if (this->head == NULL) {
Node* new_head = new Node(value, pos);
this->head = new_head;
} else if (this->head->index > pos) {
Node* new_head = new Node(value, pos);
new_head->next = this->head;
this->head = new_head;
} else {
_insert(this->head, value, pos);
}
}
string read(int pos) {
return _read(this->head, pos);
}
int size() {
return _size(this->head);
}
void remove(int pos) {
return _remove(this->head, pos);
}
public:
friend ostream& operator<< (ostream& wy, const List& lst) {
if (lst.head) return wy << "(" << *lst.head << ")";
else return wy << "()";
}
};
int main() {
return 0;
}
You List copy-constructor is severely flawed:
You initialize tmp_this to the value of this->head which is a null pointer
The above doesn't matter because the first thing you do in the loop is reassign tmp_this to point to a new Node object.
Then you immediately discard that pointer, by reassigning tmp_this to point to tmp_this->next which is a null pointer.
And you don't link anything into the list.
A working function could look something like
List(const List &lst) : head(nullptr) {
Node* tmp_lst = lst.head;
Node** tmp_current = &head;
while (tmp_lst != NULL) {
Node* tmp_this = new Node(tmp_lst->text, tmp_lst->index);
// Would prefer to use the copy-constructor here too, instead of the above
// Node* tmp_this = new Node(tmp_lst);
// This links the new node into the end of the list
*tmp_current = tmp_this
tmp_current = &tmp_this->next;
tmp_lst = tmp_lst->next;
}
}
I wrote this implementation of Linked list:
template<typename T> // implementation: Linked_list
class Linked_list {
private:
Node<T>* head;
Node<T>* tail;
Node<T>* current;
int size;
void init()
{
head = tail = current = new Node<T>();
size = 0;
}
Node<T>* search_previous()
{
if (current == head) {
return nullptr;
}
Node<T>* previous_node = head;
while (previous_node->next != current) {
previous_node = previous_node->next;
}
return previous_node;
}
public:
Linked_list()
{
init();
}
void clear()
{
while (head != nullptr) {
current = head;
head = head->next;
delete current;
}
init();
}
~Linked_list()
{
clear();
delete head;
}
void append(T p_element)
{
tail->next = new Node<T>(p_element);
tail = tail->next;
++size;
}
void insert(T p_element)
{
current->next = new Node<T>(p_element, current->next);
if (current == tail) {
tail = tail->next;
}
++size;
}
T remove()
{
if (current->next == nullptr) {
throw std::runtime_error("No element to remove");
}
T removed_element = current->next->element;
Node<T>* temporary_pointer = current->next;
current->next = current->next->next;
if (temporary_pointer == tail) {
tail = current;
}
delete temporary_pointer;
--size;
return removed_element;
}
T get_element()
{
if (current->next == nullptr) {
throw std::runtime_error("No element to get");
}
return current->next->element;
}
void go_to_start()
{
current = head;
}
void go_to_end()
{
current = tail;
}
void go_to_pos(int p_pos)
{
if ((p_pos < 0) || (p_pos >= size)) {
throw std::runtime_error("Index out of bounds");
}
current = head;
for (int index = 0; index < p_pos; ++index) {
current = current->next;
}
}
void next()
{
if (current != tail) {
current = current->next;
}
else {
throw std::runtime_error("There's no next positition");
}
}
void previous()
{
if (current != head) {
current = search_previous();
}
else {
throw std::runtime_error("There's no previous positition");
}
}
int get_pos()
{
int pos = 0;
Node<T>* temporary_pointer = head;
while (temporary_pointer != current) {
temporary_pointer = temporary_pointer->next;
++pos;
}
return pos;
}
int get_size()
{
return size;
}
void concat(Linked_list<T> p_list)
{
for (p_list.go_to_start(); p_list.get_pos() < p_list.get_size(); p_list.next()) {
append(p_list.get_element());
}
}
};
And here's the node:
template<typename T>
class Node {
public:
T element;
Node<T>* next;
Node(T p_element, Node<T>* p_next = nullptr)
{
element = p_element;
next = p_next;
}
Node(Node<T>* p_next = nullptr)
{
next = p_next;
}
};
The problem that I have is that when I try to use the method concat I get this message from Clang:
proofs(13417,0x7fff7bb9f000) malloc: * error for object 0x7fe10b603170: pointer being freed was not allocated
* set a breakpoint in malloc_error_break to debug
Abort trap: 6
What can I do for fix it?
The obvious error is this:
void concat(Linked_list<T> p_list)
You are passing a Linked_list by value. That means that a temporary copy of the linked list is created and destroyed. Since the destructor deletes the memory, it is also deleting the memory of the linked list that you are making the copy of.
Since your Linked_list class does not have a user-defined assignment operator or copy constructor to handle the members that point to dynamically allocated memory, the class cannot be safely copied (if you debugged, you should have seen that a destructor was called that you didn't expect, and that is the temporary being destroyed, thus corrupting the original object).
To prevent this, either pass by reference (not value),
void concat(Linked_list<T>& p_list)
or provide appropriate copy constructor and assignment operator.
See What is the rule of Three