Вам необходимо перечислить узлы старого списка, выделить новые узлы для скопированных данных и добавить их в новый список.Лучшее место для этого - конструктор копирования и оператор присваивания класса set
.
Кроме того, конструктор класса set
по умолчанию выполняет ту работу, которую должен выполнять ваш деструктор.Что не является необходимым, так как в конструкторе нечего удалять.Ваш деструктор не выполняет итерацию по списку правильно.Код, который вы используете в конструкторе по умолчанию, выполняется правильно.Этот код необходимо переместить из конструктора в деструктор.
Ваши другие методы класса set
реализованы не очень эффективно (избыточный поиск в списке) или даже в некоторых случаях правильно (совершенно неверная логика,утечки памяти и т. д.).
Вместо этого попробуйте что-нибудь подобное:
struct Snode
{
char data;
int count;
Snode *next = nullptr;
Snode(char a, int c = 1) : data(a), count(c) {}
};
class set
{
private:
Snode *head = nullptr;
Snode *tail = nullptr;
void append(char value, int count)
{
Snode *temp = new Snode(value, count);
if (!head)
head = temp;
if (tail)
tail->next = temp;
tail = temp;
}
void remove(Snode *node, Snode *previous)
{
if (previous)
previous->next = node->next;
if (head == node)
head = node->next;
if (tail == node)
tail = previous;
delete node;
}
void swap(set &other)
{
Snode *ptr = head;
head = other.head;
other.head = ptr;
ptr = tail;
tail = other.tail;
other.tail = ptr;
}
public:
set() = default;
set(const set &src)
{
Snode *temp = src.head;
while (temp)
{
append(temp->data, temp->count);
temp = temp->next;
}
}
set(set &&src)
{
src.swap(*this);
}
~set()
{
Snode *temp = head;
while (temp)
{
Snode *next = temp->next;
delete temp;
temp = next;
}
}
set& operator=(const set &rhs)
{
if (&rhs != this)
{
set temp(rhs);
temp.swap(*this);
}
return *this;
}
set& operator=(set &&rhs)
{
rhs.swap(*this);
return *this;
}
bool isAvailable(char value)
{
return (find(value) != nullptr);
}
Snode* find(char value, Snode **previous = nullptr)
{
if (previous)
*previous = nullptr;
Snode *temp = head;
Snode *prev = nullptr;
while (temp)
{
if (temp->data == value)
{
if (previous)
*previous = prev;
return temp;
}
prev = temp;
temp = temp->next;
}
return nullptr;
}
bool isFirst(char value)
{
return ((head) && (head->data == value));
}
bool isLast(char value)
{
return ((tail) && (tail->data == value));
}
void display()
{
Snode *temp = head;
while (temp)
{
std::cout << temp->data << " " << temp->count << std::endl;
temp = temp->next;
}
}
void insert(char value)
{
Snode *temp = find(value);
if (temp)
temp->count += 1;
else
append(value, 1);
}
int count(char value)
{
Snode *temp = find(value);
return (temp) ? temp->count : 0;
}
void deleteFirst()
{
if (head)
remove(head, nullptr);
}
void deleteLast()
{
if (head)
{
Snode *last = head;
Snode *previous = nullptr;
while (last->next)
{
previous = last;
last = last->next;
}
remove(last, previous);
}
}
void remove(char value)
{
Snode *previous;
Snode *temp = find(value, &previous);
if (temp)
{
if (temp->count > 1)
temp->count -= 1;
else
remove(temp, previous);
}
}
};
Тогда вы можете сделать что-то вроде этого:
int main()
{
//defining a mySet as a "set" type
set mySet;
//adding values to create nodes
mySet.insert('c');
mySet.insert('a');
mySet.insert('a');
mySet.insert('c');
mySet.insert('c');
set myCopiedSet = mySet; // make a copy of the list
//adding more values to create nodes
myCopiedSet.insert('a');
myCopiedSet.insert('b');
myCopiedSet.insert('b');
myCopiedSet.insert('c');
//displaying nodes through "value count" format
std::cout << "original:" << std::endl;
mySet.display();
std::cout << "copy:" << std::endl;
myCopiedSet.display();
return 0;
}
Вы можете упростить set
Класс немного дальше, если вы используете двусвязный список вместо односвязного списка:
struct Snode
{
char data;
int count;
Snode *previous = nullptr;
Snode *next = nullptr;
Snode(char a, int c) : data(a), count(c) {}
};
class set
{
private:
Snode *head = nullptr;
Snode *tail = nullptr;
void append(char value, int count)
{
Snode *temp = new Snode(value, count);
if (!head)
head = temp;
if (tail)
{
temp->previous = tail;
tail->next = temp;
}
tail = temp;
}
void remove(Snode *node)
{
if (node->previous)
node->previous->next = node->next;
if (node->next)
node->next->previous = node->previous;
if (head == node)
head = node->next;
if (tail == node)
tail = node->previous;
delete node;
}
void swap(set &other)
{
Snode *ptr = head;
head = other.head;
other.head = ptr;
ptr = tail;
tail = other.tail;
other.tail = ptr;
}
public:
set() = default;
set(const set &src)
{
Snode *temp = src.head;
while (temp)
{
append(temp->data, temp->count);
temp = temp->next;
}
}
set(set &&src)
{
src.swap(*this);
}
~set()
{
Snode *temp = head;
while (temp)
{
Snode *next = temp->next;
delete temp;
temp = next;
}
}
set& operator=(const set &rhs)
{
if (&rhs != this)
{
set temp(rhs);
temp.swap(*this);
}
return *this;
}
set& operator=(set &&rhs)
{
rhs.swap(*this);
return *this;
}
bool isAvailable(char value)
{
return (find(value) != nullptr);
}
Snode* find(char value)
{
Snode *temp = head;
while (temp)
{
if (temp->data == value)
return temp;
temp = temp->next;
}
return nullptr;
}
bool isFirst(char value)
{
return ((head) && (head->data == value));
}
bool isLast(char value)
{
return ((tail) && (tail->data == value));
}
void display()
{
Snode *temp = head;
while (temp)
{
std::cout << temp->data << " " << temp->count << std::endl;
temp = temp->next;
}
}
void insert(char value)
{
Snode *temp = find(value);
if (temp)
temp->count += 1;
else
append(value, 1);
}
int count(char value)
{
Snode *temp = find(value);
return (temp) ? temp->count : 0;
}
void deleteFirst()
{
if (head)
remove(head);
}
void deleteLast()
{
if (tail)
remove(tail);
}
void remove(char value)
{
Snode *temp = find(value);
if (temp)
{
if (temp->count > 1)
temp->count -= 1;
else
remove(temp);
}
}
};
В этом случае вы можете значительно упростить класс set
, используя STL's std::list
вместо контейнера, который является стандартизированной реализацией двойного связанного списка:
#include <list>
#include <algorithm>
struct Snode
{
char data;
int count;
};
class set
{
private:
std::list<Snode> nodes;
auto findValue(char value)
{
return std::find_if(nodes.begin(), nodes.end(),
[=](const Snode &n){ return (n.data == value); }
);
}
public:
bool isAvailable(char value)
{
return (find(value) != nullptr);
}
Snode* find(char value)
{
auto iter = findValue(value);
if (iter != nodes.end())
return &*iter;
return nullptr;
}
bool isFirst(char value)
{
return ((!nodes.empty()) && (nodes.front().data == value));
}
bool isLast(char value)
{
return ((!nodes.empty()) && (nodes.back().data == value));
}
void display()
{
for (auto &n : nodes)
std::cout << n.data << " " << n.count << std::endl;
}
void insert(char value)
{
Snode *temp = find(value);
if (temp)
temp->count += 1;
else
nodes.push_back(Snode{value, 1});
}
int count(char value)
{
Snode *temp = find(value);
return (temp) ? temp->count : 0;
}
void deleteFirst()
{
if (!nodes.empty())
nodes.pop_front();
}
void deleteLast()
{
if (!nodes.empty())
nodes.pop_back();
}
void remove(char value)
{
auto iter = findValue(value);
if (iter != nodes.end())
{
if (iter->count > 1)
iter->count -= 1;
else
nodes.erase(iter);
}
}
};