Загрузка данных


#include <iostream>
#include <stdexcept>
#include <algorithm>
#include <cstddef>

using namespace std;

// ===============================
// Общий узел для двусвязных списков
// ===============================
template <typename T>
struct DoubleNode {
    T data;
    DoubleNode* prev;
    DoubleNode* next;
    DoubleNode(const T& val) : data(val), prev(nullptr), next(nullptr) {}
};

// ===============================
// Вспомогательные функции сортировки слиянием
// ===============================
template <typename T>
DoubleNode<T>* mergeSorted(DoubleNode<T>* a, DoubleNode<T>* b) {
    if (!a) return b;
    if (!b) return a;

    DoubleNode<T>* head = nullptr;
    DoubleNode<T>* tail = nullptr;

    while (a && b) {
        if (a->data <= b->data) {
            if (!head) {
                head = tail = a;
            }
            else {
                tail->next = a;
                a->prev = tail;
                tail = a;
            }
            a = a->next;
        }
        else {
            if (!head) {
                head = tail = b;
            }
            else {
                tail->next = b;
                b->prev = tail;
                tail = b;
            }
            b = b->next;
        }
    }

    if (a) {
        tail->next = a;
        a->prev = tail;
    }
    else if (b) {
        tail->next = b;
        b->prev = tail;
    }

    // Обнуляем next у последнего узла
    DoubleNode<T>* cur = head;
    while (cur->next) cur = cur->next;
    cur->next = nullptr;

    if (head) head->prev = nullptr;
    return head;
}

template <typename T>
DoubleNode<T>* mergeSort(DoubleNode<T>* head) {
    if (!head || !head->next) return head;

    // Разделение списка пополам (быстрый и медленный указатели)
    DoubleNode<T>* slow = head;
    DoubleNode<T>* fast = head->next;
    while (fast && fast->next) {
        slow = slow->next;
        fast = fast->next->next;
    }

    DoubleNode<T>* mid = slow->next;
    slow->next = nullptr;
    if (mid) mid->prev = nullptr;

    DoubleNode<T>* left = mergeSort(head);
    DoubleNode<T>* right = mergeSort(mid);

    return mergeSorted(left, right);
}

// ===============================
// Задание 1.1. Шаблонный двусвязный список
// ===============================
template <typename T>
class DoubleList {
private:
    DoubleNode<T>* head;
    DoubleNode<T>* tail;
    size_t sz;

    void copyFrom(const DoubleList& other) {
        for (DoubleNode<T>* cur = other.head; cur; cur = cur->next) {
            push_back(cur->data);
        }
    }

public:
    class iterator {
        DoubleNode<T>* node;
        DoubleList<T>* owner;
        size_t index;

    public:
        iterator(DoubleNode<T>* n = nullptr, DoubleList<T>* o = nullptr, size_t i = 0)
            : node(n), owner(o), index(i) {
        }

        T& operator*() const {
            if (!node) throw out_of_range("dereference of end iterator");
            return node->data;
        }

        T* operator->() const {
            return &node->data;
        }

        iterator& operator++() {
            if (!owner || index >= owner->sz)
                throw out_of_range("++ on end iterator");
            node = node->next;
            ++index;
            return *this;
        }

        iterator operator++(int) {
            iterator tmp = *this;
            ++(*this);
            return tmp;
        }

        iterator& operator--() {
            if (!owner) throw out_of_range("-- on invalid iterator");
            if (node == nullptr) {
                if (owner->sz == 0)
                    throw out_of_range("-- on empty DoubleList");
                node = owner->tail;
                index = owner->sz - 1;
            }
            else {
                node = node->prev;
                --index;
            }
            return *this;
        }

        iterator operator--(int) {
            iterator tmp = *this;
            --(*this);
            return tmp;
        }

        bool operator==(const iterator& other) const {
            return owner == other.owner && index == other.index;
        }

        bool operator!=(const iterator& other) const {
            return !(*this == other);
        }

        friend class DoubleList;
    };

    DoubleList() : head(nullptr), tail(nullptr), sz(0) {}

    ~DoubleList() {
        clear();
    }

    DoubleList(const DoubleList& other) : head(nullptr), tail(nullptr), sz(0) {
        copyFrom(other);
    }

    DoubleList(DoubleList&& other) noexcept
        : head(other.head), tail(other.tail), sz(other.sz) {
        other.head = other.tail = nullptr;
        other.sz = 0;
    }

    DoubleList& operator=(const DoubleList& other) {
        if (this != &other) {
            clear();
            copyFrom(other);
        }
        return *this;
    }

    DoubleList& operator=(DoubleList&& other) noexcept {
        if (this != &other) {
            clear();
            head = other.head;
            tail = other.tail;
            sz = other.sz;
            other.head = other.tail = nullptr;
            other.sz = 0;
        }
        return *this;
    }

    void push_front(const T& val) {
        DoubleNode<T>* node = new DoubleNode<T>(val);
        if (!head) {
            head = tail = node;
        }
        else {
            node->next = head;
            head->prev = node;
            head = node;
        }
        ++sz;
    }

    void push_back(const T& val) {
        DoubleNode<T>* node = new DoubleNode<T>(val);
        if (!head) {
            head = tail = node;
        }
        else {
            tail->next = node;
            node->prev = tail;
            tail = node;
        }
        ++sz;
    }

    void pop_front() {
        if (empty()) throw out_of_range("pop_front from empty DoubleList");
        DoubleNode<T>* tmp = head;
        head = head->next;
        if (head) head->prev = nullptr;
        else tail = nullptr;
        delete tmp;
        --sz;
    }

    void pop_back() {
        if (empty()) throw out_of_range("pop_back from empty DoubleList");
        DoubleNode<T>* tmp = tail;
        tail = tail->prev;
        if (tail) tail->next = nullptr;
        else head = nullptr;
        delete tmp;
        --sz;
    }

    iterator insert(iterator pos, const T& val) {
        if (pos.owner != this)
            throw invalid_argument("iterator from another DoubleList");

        if (pos.node == nullptr) { // вставка в конец
            push_back(val);
            return iterator(tail, this, sz - 1);
        }

        DoubleNode<T>* cur = pos.node;
        DoubleNode<T>* node = new DoubleNode<T>(val);
        node->next = cur;
        node->prev = cur->prev;

        if (cur->prev) cur->prev->next = node;
        else head = node;

        cur->prev = node;
        ++sz;
        return iterator(node, this, pos.index);
    }

    iterator erase(iterator pos) {
        if (pos.owner != this)
            throw invalid_argument("iterator from another DoubleList");
        if (pos.node == nullptr)
            throw out_of_range("erase on end iterator");

        DoubleNode<T>* cur = pos.node;
        DoubleNode<T>* next = cur->next;
        DoubleNode<T>* prev = cur->prev;

        if (prev) prev->next = next;
        else head = next;

        if (next) next->prev = prev;
        else tail = prev;

        delete cur;
        --sz;
        return iterator(next, this, pos.index);
    }

    void clear() {
        DoubleNode<T>* cur = head;
        while (cur) {
            DoubleNode<T>* next = cur->next;
            delete cur;
            cur = next;
        }
        head = tail = nullptr;
        sz = 0;
    }

    size_t size() const { return sz; }
    bool empty() const { return sz == 0; }

    iterator begin() { return iterator(head, this, 0); }
    iterator end() { return iterator(nullptr, this, sz); }

    // Задание 2.1. Разворот списка
    void reverse() {
        if (sz < 2) return;
        DoubleNode<T>* cur = head;
        while (cur) {
            swap(cur->next, cur->prev);
            cur = cur->prev; // после swap prev — это бывший next
        }
        swap(head, tail);
    }

    // Задание 2.2. Слияние двух отсортированных списков
    void merge(DoubleList& other) {
        if (this == &other) return;

        DoubleNode<T>* a = head;
        DoubleNode<T>* b = other.head;

        head = tail = nullptr;
        size_t newSz = 0;

        while (a && b) {
            if (a->data <= b->data) {
                DoubleNode<T>* next = a->next;
                a->prev = tail;
                if (tail) tail->next = a;
                else head = a;
                tail = a;
                a = next;
            }
            else {
                DoubleNode<T>* next = b->next;
                b->prev = tail;
                if (tail) tail->next = b;
                else head = b;
                tail = b;
                b = next;
            }
            ++newSz;
        }

        while (a) {
            DoubleNode<T>* next = a->next;
            a->prev = tail;
            if (tail) tail->next = a;
            else head = a;
            tail = a;
            a = next;
            ++newSz;
        }

        while (b) {
            DoubleNode<T>* next = b->next;
            b->prev = tail;
            if (tail) tail->next = b;
            else head = b;
            tail = b;
            b = next;
            ++newSz;
        }

        if (head) head->prev = nullptr;
        if (tail) tail->next = nullptr;
        sz = newSz;

        other.head = other.tail = nullptr;
        other.sz = 0;
    }

    // Задание 2.3. Сортировка слиянием (без массива)
    void sort() {
        if (sz < 2) return;
        head = mergeSort(head);
        tail = head;
        while (tail->next) tail = tail->next;
        if (head) head->prev = nullptr;
        if (tail) tail->next = nullptr;
    }
};

// ===============================
// Задание 1.2. Кольцевой двусвязный список
// ===============================
template <typename T>
class RingDoubleList {
private:
    DoubleNode<T>* head;
    DoubleNode<T>* tail;
    size_t sz;

    void copyFrom(const RingDoubleList& other) {
        if (other.empty()) return;
        DoubleNode<T>* cur = other.head;
        for (size_t i = 0; i < other.sz; ++i) {
            push_back(cur->data);
            cur = cur->next;
        }
    }

public:
    class iterator {
        DoubleNode<T>* node;
        RingDoubleList<T>* owner;
        size_t index;

    public:
        iterator(DoubleNode<T>* n = nullptr, RingDoubleList<T>* o = nullptr, size_t i = 0)
            : node(n), owner(o), index(i) {
        }

        T& operator*() const {
            if (!node || index >= owner->sz)
                throw out_of_range("dereference of end iterator");
            return node->data;
        }

        T* operator->() const {
            return &node->data;
        }

        iterator& operator++() {
            if (!owner || index >= owner->sz)
                throw out_of_range("++ on end iterator");
            ++index;
            node = node->next;
            return *this;
        }

        iterator operator++(int) {
            iterator tmp = *this;
            ++(*this);
            return tmp;
        }

        iterator& operator--() {
            if (!owner) throw out_of_range("-- on invalid iterator");
            if (index == owner->sz) { // end
                if (owner->sz == 0)
                    throw out_of_range("-- on empty ring");
                index = owner->sz - 1;
                node = owner->tail;
            }
            else {
                --index;
                node = node->prev;
            }
            return *this;
        }

        iterator operator--(int) {
            iterator tmp = *this;
            --(*this);
            return tmp;
        }

        bool operator==(const iterator& other) const {
            return owner == other.owner && index == other.index;
        }

        bool operator!=(const iterator& other) const {
            return !(*this == other);
        }

        friend class RingDoubleList;
    };

    RingDoubleList() : head(nullptr), tail(nullptr), sz(0) {}

    ~RingDoubleList() {
        clear();
    }

    RingDoubleList(const RingDoubleList& other) : head(nullptr), tail(nullptr), sz(0) {
        copyFrom(other);
    }

    RingDoubleList(RingDoubleList&& other) noexcept
        : head(other.head), tail(other.tail), sz(other.sz) {
        other.head = other.tail = nullptr;
        other.sz = 0;
    }

    RingDoubleList& operator=(const RingDoubleList& other) {
        if (this != &other) {
            clear();
            copyFrom(other);
        }
        return *this;
    }

    RingDoubleList& operator=(RingDoubleList&& other) noexcept {
        if (this != &other) {
            clear();
            head = other.head;
            tail = other.tail;
            sz = other.sz;
            other.head = other.tail = nullptr;
            other.sz = 0;
        }
        return *this;
    }

    void push_front(const T& val) {
        DoubleNode<T>* node = new DoubleNode<T>(val);
        if (empty()) {
            node->next = node;
            node->prev = node;
            head = tail = node;
        }
        else {
            node->next = head;
            node->prev = tail;
            head->prev = node;
            tail->next = node;
            head = node;
        }
        ++sz;
    }

    void push_back(const T& val) {
        DoubleNode<T>* node = new DoubleNode<T>(val);
        if (empty()) {
            node->next = node;
            node->prev = node;
            head = tail = node;
        }
        else {
            node->next = head;
            node->prev = tail;
            tail->next = node;
            head->prev = node;
            tail = node;
        }
        ++sz;
    }

    void pop_front() {
        if (empty()) throw out_of_range("pop_front from empty ring");
        if (sz == 1) {
            delete head;
            head = tail = nullptr;
            sz = 0;
            return;
        }
        DoubleNode<T>* tmp = head;
        head = head->next;
        head->prev = tail;
        tail->next = head;
        delete tmp;
        --sz;
    }

    void pop_back() {
        if (empty()) throw out_of_range("pop_back from empty ring");
        if (sz == 1) {
            delete head;
            head = tail = nullptr;
            sz = 0;
            return;
        }
        DoubleNode<T>* tmp = tail;
        tail = tail->prev;
        tail->next = head;
        head->prev = tail;
        delete tmp;
        --sz;
    }

    iterator insert(iterator pos, const T& val) {
        if (pos.owner != this)
            throw invalid_argument("iterator from another ring");

        if (empty()) {
            DoubleNode<T>* node = new DoubleNode<T>(val);
            node->next = node;
            node->prev = node;
            head = tail = node;
            sz = 1;
            return iterator(node, this, 0);
        }

        if (pos.index == sz) { // вставка в конец (перед end)
            push_back(val);
            return iterator(tail, this, sz - 1);
        }

        if (pos.index == 0) { // вставка перед head
            push_front(val);
            return iterator(head, this, 0);
        }

        DoubleNode<T>* cur = pos.node;
        DoubleNode<T>* node = new DoubleNode<T>(val);
        node->next = cur;
        node->prev = cur->prev;
        cur->prev->next = node;
        cur->prev = node;
        ++sz;
        return iterator(node, this, pos.index);
    }

    iterator erase(iterator pos) {
        if (pos.owner != this)
            throw invalid_argument("iterator from another ring");
        if (empty() || pos.index >= sz)
            throw out_of_range("erase invalid iterator");

        DoubleNode<T>* cur = pos.node;

        if (sz == 1) {
            delete cur;
            head = tail = nullptr;
            sz = 0;
            return end();
        }

        DoubleNode<T>* next = cur->next;
        DoubleNode<T>* prev = cur->prev;

        prev->next = next;
        next->prev = prev;

        if (cur == head) head = next;
        if (cur == tail) tail = prev;

        delete cur;
        --sz;

        if (pos.index == sz) { // удалили последний элемент
            return iterator(head, this, 0);
        }
        return iterator(next, this, pos.index);
    }

    void clear() {
        if (!head) return;
        DoubleNode<T>* cur = head;
        for (size_t i = 0; i < sz; ++i) {
            DoubleNode<T>* next = cur->next;
            delete cur;
            cur = next;
        }
        head = tail = nullptr;
        sz = 0;
    }

    size_t size() const { return sz; }
    bool empty() const { return sz == 0; }

    iterator begin() { return iterator(head, this, 0); }
    iterator end() { return iterator(head, this, sz); }

    // Поворот кольца на k позиций за O(min(k, n-k))
    void rotate(int k) {
        if (sz <= 1) return;
        k %= static_cast<int>(sz);
        if (k < 0) k += static_cast<int>(sz);
        if (k == 0) return;

        if (k <= static_cast<int>(sz) - k) {
            for (int i = 0; i < k; ++i) head = head->next;
            tail = head->prev;
        }
        else {
            int steps = static_cast<int>(sz) - k;
            for (int i = 0; i < steps; ++i) head = head->prev;
            tail = head->prev;
        }
    }

    // Эффективный поиск: идём с двух сторон навстречу
    iterator find(const T& value) {
        if (empty()) return end();

        DoubleNode<T>* f = head;
        DoubleNode<T>* b = tail;

        for (size_t i = 0; i <= sz / 2; ++i) {
            if (f->data == value) return iterator(f, this, i);
            if (b->data == value) return iterator(b, this, sz - 1 - i);

            f = f->next;
            b = b->prev;

            if (f == b) {
                if (f->data == value) return iterator(f, this, i + 1);
                break;
            }
        }
        return end();
    }

    // Задание 2.1. Разворот кольцевого списка
    void reverse() {
        if (sz < 2) return;
        DoubleNode<T>* cur = head;
        for (size_t i = 0; i < sz; ++i) {
            swap(cur->next, cur->prev);
            cur = cur->prev;
        }
        swap(head, tail);
    }

    // Задание 2.3. Сортировка кольцевого списка
    void sort() {
        if (sz < 2) return;

        // Разрываем кольцо
        head->prev = nullptr;
        tail->next = nullptr;

        head = mergeSort(head);

        // Находим новый хвост
        tail = head;
        while (tail->next) tail = tail->next;

        // Снова замыкаем в кольцо
        head->prev = tail;
        tail->next = head;
    }
};

// ===============================
// Задание 3.1. Проблема Иосифа
// ===============================
void josephus(int n, int k) {
    RingDoubleList<int> ring;
    for (int i = 1; i <= n; ++i) {
        ring.push_back(i);
    }

    cout << "========================================\n";
    cout << " Проблема Иосифа: n = " << n << ", k = " << k << "\n";
    cout << "========================================\n\n";

    auto it = ring.begin();
    int step = 0;

    // Ширина колонки для ровного вывода
    const int colWidth = 5;
    const int perRow = 10;

    cout << "Порядок удаления:\n";
    while (ring.size() > 1) {
        // Отсчитываем k-й элемент
        for (int i = 1; i < k; ++i) {
            ++it;
            if (it == ring.end()) it = ring.begin();
        }

        ++step;
        cout << "[" << step << "] " << *it << "  ";

        // Переход на новую строку каждые perRow элементов
        if (step % perRow == 0) cout << "\n";

        it = ring.erase(it);
        if (it == ring.end()) it = ring.begin();
    }

    if (step % perRow != 0) cout << "\n";
    cout << "\n";

    cout << "----------------------------------------\n";
    cout << " Всего удалено: " << step << "\n";
    cout << " Последний выживший: " << *ring.begin() << "\n";
    cout << "----------------------------------------\n";

    if (n == 41 && k == 3) {
        cout << " Проверка: ожидается 31 -> "
            << (*ring.begin() == 31 ? "OK" : "ОШИБКА") << "\n";
        cout << "----------------------------------------\n";
    }
}

// ===============================
// Демонстрация
// ===============================
int main() {
    setlocale(LC_ALL, "");

    cout << "===== Проверка DoubleList =====" << endl;

    DoubleList<int> lst;
    lst.push_back(3);
    lst.push_back(1);
    lst.push_back(2);
    lst.sort();

    cout << "Отсортированный DoubleList: ";
    for (auto it = lst.begin(); it != lst.end(); ++it)
        cout << *it << " ";
    cout << endl;

    DoubleList<int> a, b;
    a.push_back(1); a.push_back(3); a.push_back(5);
    b.push_back(2); b.push_back(4); b.push_back(6);

    a.merge(b);
    cout << "После merge: ";
    for (auto it = a.begin(); it != a.end(); ++it)
        cout << *it << " ";
    cout << endl;

    a.reverse();
    cout << "После reverse: ";
    for (auto it = a.begin(); it != a.end(); ++it)
        cout << *it << " ";
    cout << endl;

    cout << "\n===== Проверка RingDoubleList =====" << endl;

    RingDoubleList<int> ring;
    for (int i = 1; i <= 10; ++i) ring.push_back(i);

    cout << "Кольцо: ";
    auto rit = ring.begin();
    for (size_t i = 0; i < ring.size(); ++i) {
        cout << *rit << " ";
        ++rit;
    }
    cout << endl;

    ring.rotate(3);
    cout << "После rotate(3): ";
    rit = ring.begin();
    for (size_t i = 0; i < ring.size(); ++i) {
        cout << *rit << " ";
        ++rit;
    }
    cout << endl;

    ring.reverse();
    cout << "После reverse: ";
    rit = ring.begin();
    for (size_t i = 0; i < ring.size(); ++i) {
        cout << *rit << " ";
        ++rit;
    }
    cout << endl;

    cout << "\n===== Задание 3.1. Проблема Иосифа =====" << endl;
    josephus(41, 3); // Должен остаться элемент с начальной позицией 31

    return 0;
}