#ifndef __LQUEUE_HPP #define __LQUEUE_HPP #include #include "abstract_queue.hpp" template struct QueueElement { T data; QueueElement* next; QueueElement(T const& _data, QueueElement* _next = nullptr) : data(_data), next(_next) {} }; template class LinkedQueue : public AbstractQueue { private: QueueElement *front, *back; // инвариант на класа: // front == nullptr && back == nullptr || front != nullptr && back != nullptr void copy(LinkedQueue const&); void erase(); public: LinkedQueue() : front(nullptr), back(nullptr) {} LinkedQueue(LinkedQueue const&); LinkedQueue& operator=(LinkedQueue const&); ~LinkedQueue(); // проверява дали опашка е празна virtual bool empty() const { return front == nullptr; } // включване на елемент в края на опашката virtual void enqueue(T const&); // изключване на елемента в началото на опашката virtual T dequeue(); // поглеждане на елемента в началото на опашката virtual T const& head() const; // поглеждане на елемента в началото на опашката с възможност за промяна virtual T& head(); }; template T const& LinkedQueue::head() const { if (empty()) throw std::runtime_error("Опит за поглеждане в празна опашка"); return front->data; } template T& LinkedQueue::head() { if (empty()) throw std::runtime_error("Опит за поглеждане в празна опашка"); return front->data; } template void LinkedQueue::enqueue(T const& x) { QueueElement* newElement = new QueueElement{x}; if (empty()) front = newElement; else back->next = newElement; back = newElement; } template T LinkedQueue::dequeue() { if (empty()) throw std::runtime_error("Опит за изваждане от празна опашка"); if (front == back) // само 1 елемент back = nullptr; QueueElement* oldElement = front; front = front->next; T result = oldElement->data; delete oldElement; return result; } template LinkedQueue::LinkedQueue(LinkedQueue const& other) { copy(other); } template LinkedQueue& LinkedQueue::operator=(LinkedQueue const& other) { if (this != &other) { erase(); copy(other); } return *this; } template LinkedQueue::~LinkedQueue() { erase(); } template void LinkedQueue::copy(LinkedQueue const& other) { /* !!! while (!other.empty()) enqueue(other.dequeue()); */ if (other.front != nullptr) { // other не е празен back = front = new QueueElement{other.front->data, nullptr}; QueueElement* nextToCopy = other.front->next; while (nextToCopy) { back = back->next = new QueueElement{nextToCopy->data, nullptr}; nextToCopy = nextToCopy->next; } } else front = back = nullptr; } template void LinkedQueue::erase() { while(!empty()) dequeue(); } #endif