#include <iostream>
#include <stdexcept>
#include <cstddef>
template <typename T>
class CircularQueue {
private:
T* data; // Массив для хранения элементов
std::size_t capacity; // Максимальная вместимость
std::size_t frontIndex; // Индекс первого элемента
std::size_t rearIndex; // Индекс следующей свободной позиции
std::size_t count; // Текущее количество элементов
public:
// Конструктор
explicit CircularQueue(std::size_t capacity)
: data(nullptr),
capacity(capacity),
frontIndex(0),
rearIndex(0),
count(0) {
if (capacity == 0) {
throw std::invalid_argument(
"Размер очереди должен быть больше нуля"
);
}
data = new T[capacity];
}
// Деструктор
~CircularQueue() {
delete[] data;
}
// Запрещаем копирование для безопасной работы с динамической памятью
CircularQueue(const CircularQueue&) = delete;
CircularQueue& operator=(const CircularQueue&) = delete;
// Проверка, пуста ли очередь
bool isEmpty() const noexcept {
return count == 0;
}
// Проверка, заполнена ли очередь
bool isFull() const noexcept {
return count == capacity;
}
// Получение текущего количества элементов
std::size_t size() const noexcept {
return count;
}
// Получение максимального количества элементов
std::size_t maxSize() const noexcept {
return capacity;
}
// Добавление элемента в конец очереди
void enqueue(const T& value) {
if (isFull()) {
throw std::overflow_error("Очередь заполнена");
}
data[rearIndex] = value;
// Циклический переход к следующей позиции массива
rearIndex = (rearIndex + 1) % capacity;
++count;
}
// Удаление элемента из начала очереди
void dequeue() {
if (isEmpty()) {
throw std::underflow_error("Очередь пуста");
}
// Элементы не сдвигаются, изменяется только индекс начала
frontIndex = (frontIndex + 1) % capacity;
--count;
}
// Получение первого элемента очереди
T& front() {
if (isEmpty()) {
throw std::underflow_error("Очередь пуста");
}
return data[frontIndex];
}
const T& front() const {
if (isEmpty()) {
throw std::underflow_error("Очередь пуста");
}
return data[frontIndex];
}
// Получение последнего элемента очереди
T& back() {
if (isEmpty()) {
throw std::underflow_error("Очередь пуста");
}
std::size_t index =
(rearIndex + capacity - 1) % capacity;
return data[index];
}
const T& back() const {
if (isEmpty()) {
throw std::underflow_error("Очередь пуста");
}
std::size_t index =
(rearIndex + capacity - 1) % capacity;
return data[index];
}
// Полная очистка очереди
void clear() noexcept {
frontIndex = 0;
rearIndex = 0;
count = 0;
}
// Вывод элементов очереди
void print() const {
if (isEmpty()) {
std::cout << "Очередь: пуста\n";
return;
}
std::cout << "Очередь: ";
for (std::size_t i = 0; i < count; ++i) {
std::size_t index =
(frontIndex + i) % capacity;
std::cout << data[index];
if (i + 1 < count) {
std::cout << " ";
}
}
std::cout << '\n';
}
// Вывод внутреннего состояния циклического массива
void printState() const {
std::cout << "Индекс начала (front): " << frontIndex
<< ", индекс конца (rear): " << rearIndex
<< ", размер: " << count
<< ", вместимость: " << capacity
<< '\n';
}
};
int main() {
try {
// Создание очереди вместимостью 5 элементов
CircularQueue<int> queue(5);
// ---------------------------------------------------------
// 1. Начальное состояние
// ---------------------------------------------------------
std::cout << "=== 1. Начальное состояние очереди ===\n";
queue.print();
queue.printState();
// ---------------------------------------------------------
// 2. Добавление элементов
// ---------------------------------------------------------
std::cout << "\n=== 2. Добавление элементов ===\n";
queue.enqueue(10);
queue.enqueue(20);
queue.enqueue(30);
queue.print();
queue.printState();
// ---------------------------------------------------------
// 3. Просмотр первого и последнего элемента
// ---------------------------------------------------------
std::cout
<< "\n=== 3. Просмотр первого и последнего элемента ===\n";
std::cout << "Первый элемент: "
<< queue.front() << '\n';
std::cout << "Последний элемент: "
<< queue.back() << '\n';
// ---------------------------------------------------------
// 4. Удаление элемента
// ---------------------------------------------------------
std::cout << "\n=== 4. Удаление элемента ===\n";
queue.dequeue();
std::cout << "После удаления первого элемента:\n";
queue.print();
queue.printState();
// ---------------------------------------------------------
// 5. Проверка циклического массива
// ---------------------------------------------------------
std::cout << "\n=== 5. Проверка циклического массива ===\n";
queue.enqueue(40);
queue.enqueue(50);
queue.enqueue(60);
queue.print();
queue.printState();
std::cout
<< "Освободившаяся позиция массива была использована повторно.\n"
<< "Элементы очереди не сдвигаются.\n";
// ---------------------------------------------------------
// 6. Проверка заполнения очереди
// ---------------------------------------------------------
std::cout << "\n=== 6. Проверка заполнения очереди ===\n";
queue.print();
std::cout << "Очередь заполнена: "
<< (queue.isFull() ? "да" : "нет")
<< '\n';
// ---------------------------------------------------------
// 7. Проверка переполнения
// ---------------------------------------------------------
std::cout << "\n=== 7. Проверка переполнения ===\n";
try {
queue.enqueue(70);
}
catch (const std::overflow_error& error) {
std::cout
<< "Переполнение обработано корректно: "
<< error.what() << '\n';
}
// ---------------------------------------------------------
// 8. Повторное использование освободившихся ячеек
// ---------------------------------------------------------
std::cout
<< "\n=== 8. Повторное использование освободившихся ячеек ===\n";
queue.dequeue();
queue.dequeue();
std::cout << "После удаления двух элементов:\n";
queue.print();
queue.printState();
queue.enqueue(70);
queue.enqueue(80);
std::cout << "После добавления новых элементов:\n";
queue.print();
queue.printState();
// ---------------------------------------------------------
// 9. Проверка размера очереди
// ---------------------------------------------------------
std::cout << "\n=== 9. Проверка размера очереди ===\n";
std::cout << "Текущий размер очереди: "
<< queue.size() << '\n';
std::cout << "Максимальный размер очереди: "
<< queue.maxSize() << '\n';
std::cout << "Очередь пуста: "
<< (queue.isEmpty() ? "да" : "нет")
<< '\n';
std::cout << "Очередь заполнена: "
<< (queue.isFull() ? "да" : "нет")
<< '\n';
// ---------------------------------------------------------
// 10. Очистка очереди
// ---------------------------------------------------------
std::cout << "\n=== 10. Очистка очереди ===\n";
queue.clear();
queue.print();
queue.printState();
std::cout << "Очередь пуста: "
<< (queue.isEmpty() ? "да" : "нет")
<< '\n';
// ---------------------------------------------------------
// 11. Проверка удаления из пустой очереди
// ---------------------------------------------------------
std::cout
<< "\n=== 11. Проверка удаления из пустой очереди ===\n";
try {
queue.dequeue();
}
catch (const std::underflow_error& error) {
std::cout
<< "Удаление из пустой очереди обработано корректно: "
<< error.what() << '\n';
}
// ---------------------------------------------------------
// 12. Повторное использование после очистки
// ---------------------------------------------------------
std::cout
<< "\n=== 12. Повторное использование после очистки ===\n";
queue.enqueue(100);
queue.enqueue(200);
queue.print();
queue.printState();
std::cout << "Первый элемент: "
<< queue.front() << '\n';
std::cout << "Последний элемент: "
<< queue.back() << '\n';
std::cout
<< "\n=== Все проверки успешно завершены ===\n";
}
catch (const std::invalid_argument& error) {
std::cerr
<< "Ошибка при создании очереди: "
<< error.what() << '\n';
return 1;
}
catch (const std::exception& error) {
std::cerr
<< "Непредвиденная ошибка: "
<< error.what() << '\n';
return 1;
}
return 0;
}