Добавил:
CanyonE
СПбГУТ * ИКСС * Программная инженерия
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Решения лабораторных работ (местами есть ошибки) / Lab5_2_Singly linked list
.cpp#include <iostream>
#include <stdexcept>
using std::cin;
using std::cout;
using std::endl;
// Простая реализация однонаправленного списка
template <class T>
class List {
protected:
// Структура "список"
struct list {
T *elem;
list *next;
};
// Полная очистка списка
void standart_clear() {
if (data_) {
list **next = &data_;
for (size_t i = 0; i < n_; ++i) {
delete ( *next )->elem; // Освобождаем очередной соответствующий элемент родителя
list *t = ( *next )->next; // Передвигаемся к child в t
delete *next, *next = t; // Освобождаем родителя, next = t (child)
}
data_ = nullptr;
}
n_ = 0;
}
private:
// Текущий размер списка
size_t n_ = 0;
// Указатель на структуру list
list *data_ = nullptr;
public:
// Конструктор
explicit List(size_t n = 0) : n_(n) {
if (n >= 0) {
data_ = nullptr;
list **next = &data_;
for (size_t i = 0; i < n; ++i) {
*next = new list {new T(), nullptr}; // Выделяем память для родителя
next = &( ( *next )->next ); // Переходим к его child
}
return;
}
throw std::bad_array_new_length();
}
// Конструктор копирования
List(const List &arg) {
n_ = 0;
if (arg.data_) {
n_ = arg.n_;
data_ = new list {new T(*arg.data_->elem), nullptr};
list **next = &data_->next, **arg_next = &arg.data_->next;
for (size_t i = 1; i < n_; ++i) {
*next = new list {new T(*( *arg_next )->elem), nullptr};
next = &( ( *next )->next );
arg_next = &( ( *arg_next )->next );
}
}
}
// Оператор копирования
List &operator=(const List &arg) {
List temp(arg);
swap(*this, temp);
return *this;
}
// Конструктор перемещения
List(List &&arg) noexcept {
n_ = arg.n_, data_ = arg.data_;
arg.n_ = 0, arg.data_ = nullptr;
}
// Оператор перемещения
List &operator=(List &&arg) noexcept {
if (this != &arg) {
swap(*this, arg);
arg.standart_clear();
arg.n_ = 0;
}
return *this;
}
// Деструктор
virtual ~List() {
standart_clear();
}
// Очистка списка
void clear() {
standart_clear();
}
// Получает элемент списка по индексу [сложность T(n_)]
T &operator[](const size_t &idx) noexcept(false) {
if (idx >= 0 && idx < n_) {
list **next = &data_;
for (size_t i = 0; i < idx; ++i) {
next = &( ( *next )->next );
}
return *( *next )->elem;
}
throw std::out_of_range("List. Operator[]. Out of range");
}
// Вставляет элемент ELEM в позицию IDX [сложность T(n_)]
void insert(const size_t &idx, const T &elem) noexcept(false) {
if (idx >= 0 && idx <= n_) {
if (data_) {
list **next = &data_;
for (size_t i = 0; i < idx; ++i) {
next = &( ( *next )->next );
}
*next = new list {new T {elem}, *next};
++n_;
return;
}
data_ = new list {new T {elem}, nullptr};
++n_;
return;
}
throw std::out_of_range("List. Method insert. Out of range");
}
// Удаляет элемент с индексом IDX [сложность T(n_)]
void erase(const size_t &idx) noexcept(false) {
if (idx > 0 && idx < n_) {
list **next = &data_;
for (size_t i = 1; i < idx; ++i) {
next = &( ( *next )->next );
}
list *temp = ( ( *next )->next ? ( *next )->next->next : nullptr );
delete ( *next )->next, ( *next )->next = temp;
--n_;
return;
} else if (idx == 0 && data_) {
list *temp = data_->next;
delete data_, data_ = temp;
--n_;
return;
}
throw std::out_of_range("List. Method erase. Out of range");
}
// Возвращает размер списка
size_t size() const noexcept {
return n_;
}
// True, если список пустой, иначе False
bool empty() const noexcept {
return n_ == 0;
}
// Оператор приведения к типу bool
explicit operator bool () {
return n_ != 0;
}
// Вывод содержимого списка в поток ostream (cout, ...)
friend std::ostream &operator<<(std::ostream &os, List &arg) {
list **next = &arg.data_;
if (*next) {
os << *( *next )->elem;
next = &( ( *next )->next );
for (size_t i = 1; i < arg.n_; ++i) {
os << ' ' << *( *next )->elem;
next = &( ( *next )->next );
}
}
return os;
}
friend void swap(List &first, List &second) noexcept {
std::swap(first.n_, second.n_);
std::swap(first.data_, second.data_);
}
};
int main() {
List<double> listA, listB(5);
// Добавление и удаление элементов
for (size_t i = 0; i < 5; ++i) { listA.insert(listA.size(), ( i + 1 )); }
for (size_t i = 0; i < 5; ++i) { listA.erase(0); }
for (size_t i = 0; i < 5; ++i) { listA.insert(( i + 1 ) / 2, i + 1); }
for (size_t i = 0; i < 5; ++i) { listB[i] = i + 1; }
// Отображение содержимого списков
cout << "List A: " << listA << endl;
cout << "List B: " << listB << endl;
// Доступ к любому элементу [сложность T(n_)]
cout << "List A[0]: " << ( listA.size() > 0 ? listA[0] : -0 ) << endl;
cout << "List A[" << listA.size() - 1 << "]: " << ( listA.size() - 1 > 0 ? listA[listA.size() - 1] : -0 ) << endl;
cout << "List B[0]: " << ( listB.size() > 0 ? listB[0] : -0 ) << endl;
cout << "List B[" << listB.size() - 1 << "]: " << ( listB.size() - 1 > 0 ? listB[listB.size() - 1] : -0 ) << endl;
// Конструктор копирования
List<double> listC(listA);
cout << "List (after copy): " << listA << endl;
cout << "Copy ^ (constructor): " << listC << endl;
// Оператор копирования
listC = listB;
cout << "List (after copy): " << listB << endl;
cout << "Copy ^ (assignment): " << listC << endl;
// Конструктор перемещения
List<double> listD(std::move(listA));
cout << "List (after move): " << listA << endl;
cout << "Move ^ (constructor): " << listD << endl;
// Оператор перемещения
listC = std::move(listB);
cout << "List (after move): " << listB << endl;
cout << "Move ^ (assignment): " << listC << endl;
// Размер списка
cout << "List D (size): " << listD.size() << " (isEmpty ? " << ( listD.empty() ? "TRUE" : "FALSE" ) << ")\n";
cout << "List C (size): " << listC.size() << " (isEmpty ? " << ( listC.empty() ? "TRUE" : "FALSE" ) << ")\n";
// Очистка списка
listD.erase(4);
listD.erase(3);
listD.erase(2);
listD.erase(1);
listD.erase(0);
listC.clear();
cout << "List D (size after pop): " << listD.size() << " (isEmpty ? " << ( listD.empty() ? "TRUE" : "FALSE" )
<< ")\n";
cout << "List C (size after pop): " << listC.size() << " (isEmpty ? " << ( listC.empty() ? "TRUE" : "FALSE" )
<< ")\n";
// Работа деструктора...
listD.insert(0, 1000);
listD.insert(0, 1200);
listD.insert(0, 1300);
}
Соседние файлы в папке Решения лабораторных работ (местами есть ошибки)