fork download
  1. #include <iostream>
  2. #include <stdexcept>
  3. #include <cstddef>
  4.  
  5. template <typename T>
  6. class CircularQueue {
  7. private:
  8. T* data; // Массив для хранения элементов
  9. std::size_t capacity; // Максимальная вместимость
  10. std::size_t frontIndex; // Индекс первого элемента
  11. std::size_t rearIndex; // Индекс следующей свободной позиции
  12. std::size_t count; // Текущее количество элементов
  13.  
  14. public:
  15. // Конструктор
  16. explicit CircularQueue(std::size_t capacity)
  17. : data(nullptr),
  18. capacity(capacity),
  19. frontIndex(0),
  20. rearIndex(0),
  21. count(0) {
  22.  
  23. if (capacity == 0) {
  24. throw std::invalid_argument(
  25. "Размер очереди должен быть больше нуля"
  26. );
  27. }
  28.  
  29. data = new T[capacity];
  30. }
  31.  
  32. // Деструктор
  33. ~CircularQueue() {
  34. delete[] data;
  35. }
  36.  
  37. // Запрещаем копирование для безопасной работы с динамической памятью
  38. CircularQueue(const CircularQueue&) = delete;
  39. CircularQueue& operator=(const CircularQueue&) = delete;
  40.  
  41. // Проверка, пуста ли очередь
  42. bool isEmpty() const noexcept {
  43. return count == 0;
  44. }
  45.  
  46. // Проверка, заполнена ли очередь
  47. bool isFull() const noexcept {
  48. return count == capacity;
  49. }
  50.  
  51. // Получение текущего количества элементов
  52. std::size_t size() const noexcept {
  53. return count;
  54. }
  55.  
  56. // Получение максимального количества элементов
  57. std::size_t maxSize() const noexcept {
  58. return capacity;
  59. }
  60.  
  61. // Добавление элемента в конец очереди
  62. void enqueue(const T& value) {
  63. if (isFull()) {
  64. throw std::overflow_error("Очередь заполнена");
  65. }
  66.  
  67. data[rearIndex] = value;
  68.  
  69. // Циклический переход к следующей позиции массива
  70. rearIndex = (rearIndex + 1) % capacity;
  71.  
  72. ++count;
  73. }
  74.  
  75. // Удаление элемента из начала очереди
  76. void dequeue() {
  77. if (isEmpty()) {
  78. throw std::underflow_error("Очередь пуста");
  79. }
  80.  
  81. // Элементы не сдвигаются, изменяется только индекс начала
  82. frontIndex = (frontIndex + 1) % capacity;
  83.  
  84. --count;
  85. }
  86.  
  87. // Получение первого элемента очереди
  88. T& front() {
  89. if (isEmpty()) {
  90. throw std::underflow_error("Очередь пуста");
  91. }
  92.  
  93. return data[frontIndex];
  94. }
  95.  
  96. const T& front() const {
  97. if (isEmpty()) {
  98. throw std::underflow_error("Очередь пуста");
  99. }
  100.  
  101. return data[frontIndex];
  102. }
  103.  
  104. // Получение последнего элемента очереди
  105. T& back() {
  106. if (isEmpty()) {
  107. throw std::underflow_error("Очередь пуста");
  108. }
  109.  
  110. std::size_t index =
  111. (rearIndex + capacity - 1) % capacity;
  112.  
  113. return data[index];
  114. }
  115.  
  116. const T& back() const {
  117. if (isEmpty()) {
  118. throw std::underflow_error("Очередь пуста");
  119. }
  120.  
  121. std::size_t index =
  122. (rearIndex + capacity - 1) % capacity;
  123.  
  124. return data[index];
  125. }
  126.  
  127. // Полная очистка очереди
  128. void clear() noexcept {
  129. frontIndex = 0;
  130. rearIndex = 0;
  131. count = 0;
  132. }
  133.  
  134. // Вывод элементов очереди
  135. void print() const {
  136. if (isEmpty()) {
  137. std::cout << "Очередь: пуста\n";
  138. return;
  139. }
  140.  
  141. std::cout << "Очередь: ";
  142.  
  143. for (std::size_t i = 0; i < count; ++i) {
  144. std::size_t index =
  145. (frontIndex + i) % capacity;
  146.  
  147. std::cout << data[index];
  148.  
  149. if (i + 1 < count) {
  150. std::cout << " ";
  151. }
  152. }
  153.  
  154. std::cout << '\n';
  155. }
  156.  
  157. // Вывод внутреннего состояния циклического массива
  158. void printState() const {
  159. std::cout << "Индекс начала (front): " << frontIndex
  160. << ", индекс конца (rear): " << rearIndex
  161. << ", размер: " << count
  162. << ", вместимость: " << capacity
  163. << '\n';
  164. }
  165. };
  166.  
  167.  
  168. int main() {
  169. try {
  170. // Создание очереди вместимостью 5 элементов
  171. CircularQueue<int> queue(5);
  172.  
  173.  
  174. // 1. Начальное состояние
  175.  
  176. std::cout << "=== 1. Начальное состояние очереди ===\n";
  177.  
  178. queue.print();
  179. queue.printState();
  180.  
  181. // 2. Добавление элементов
  182. std::cout << "\n=== 2. Добавление элементов ===\n";
  183.  
  184. queue.enqueue(10);
  185. queue.enqueue(20);
  186. queue.enqueue(30);
  187.  
  188. queue.print();
  189. queue.printState();
  190.  
  191. // 3. Просмотр первого и последнего элемента
  192. std::cout
  193. << "\n=== 3. Просмотр первого и последнего элемента ===\n";
  194.  
  195. std::cout << "Первый элемент: "
  196. << queue.front() << '\n';
  197.  
  198. std::cout << "Последний элемент: "
  199. << queue.back() << '\n';
  200.  
  201. // 4. Удаление элемента
  202. std::cout << "\n=== 4. Удаление элемента ===\n";
  203.  
  204. queue.dequeue();
  205.  
  206. std::cout << "После удаления первого элемента:\n";
  207. queue.print();
  208. queue.printState();
  209.  
  210. // 5. Проверка циклического массива
  211. std::cout << "\n=== 5. Проверка циклического массива ===\n";
  212.  
  213. queue.enqueue(40);
  214. queue.enqueue(50);
  215. queue.enqueue(60);
  216.  
  217. queue.print();
  218. queue.printState();
  219.  
  220. std::cout
  221. << "Освободившаяся позиция массива была использована повторно.\n"
  222. << "Элементы очереди не сдвигаются.\n";
  223.  
  224. // 6. Проверка заполнения очереди
  225. std::cout << "\n=== 6. Проверка заполнения очереди ===\n";
  226.  
  227. queue.print();
  228.  
  229. std::cout << "Очередь заполнена: "
  230. << (queue.isFull() ? "да" : "нет")
  231. << '\n';
  232.  
  233. // 7. Проверка переполнения
  234. std::cout << "\n=== 7. Проверка переполнения ===\n";
  235.  
  236. try {
  237. queue.enqueue(70);
  238. }
  239. catch (const std::overflow_error& error) {
  240. std::cout
  241. << "Переполнение обработано корректно: "
  242. << error.what() << '\n';
  243. }
  244.  
  245. // 8. Повторное использование освободившихся ячеек
  246. std::cout
  247. << "\n=== 8. Повторное использование освободившихся ячеек ===\n";
  248.  
  249. queue.dequeue();
  250. queue.dequeue();
  251.  
  252. std::cout << "После удаления двух элементов:\n";
  253. queue.print();
  254. queue.printState();
  255.  
  256. queue.enqueue(70);
  257. queue.enqueue(80);
  258.  
  259. std::cout << "После добавления новых элементов:\n";
  260. queue.print();
  261. queue.printState();
  262.  
  263. // 9. Проверка размера очереди
  264. std::cout << "\n=== 9. Проверка размера очереди ===\n";
  265.  
  266. std::cout << "Текущий размер очереди: "
  267. << queue.size() << '\n';
  268.  
  269. std::cout << "Максимальный размер очереди: "
  270. << queue.maxSize() << '\n';
  271.  
  272. std::cout << "Очередь пуста: "
  273. << (queue.isEmpty() ? "да" : "нет")
  274. << '\n';
  275.  
  276. std::cout << "Очередь заполнена: "
  277. << (queue.isFull() ? "да" : "нет")
  278. << '\n';
  279.  
  280. // 10. Очистка очереди
  281. std::cout << "\n=== 10. Очистка очереди ===\n";
  282.  
  283. queue.clear();
  284.  
  285. queue.print();
  286. queue.printState();
  287.  
  288. std::cout << "Очередь пуста: "
  289. << (queue.isEmpty() ? "да" : "нет")
  290. << '\n';
  291.  
  292. // 11. Проверка удаления из пустой очереди
  293. std::cout
  294. << "\n=== 11. Проверка удаления из пустой очереди ===\n";
  295.  
  296. try {
  297. queue.dequeue();
  298. }
  299. catch (const std::underflow_error& error) {
  300. std::cout
  301. << "Удаление из пустой очереди обработано корректно: "
  302. << error.what() << '\n';
  303. }
  304.  
  305. // 12. Повторное использование после очистки
  306. std::cout
  307. << "\n=== 12. Повторное использование после очистки ===\n";
  308.  
  309. queue.enqueue(100);
  310. queue.enqueue(200);
  311.  
  312. queue.print();
  313. queue.printState();
  314.  
  315. std::cout << "Первый элемент: "
  316. << queue.front() << '\n';
  317.  
  318. std::cout << "Последний элемент: "
  319. << queue.back() << '\n';
  320.  
  321. std::cout
  322. << "\n=== Все проверки успешно завершены ===\n";
  323. }
  324. catch (const std::invalid_argument& error) {
  325. std::cerr
  326. << "Ошибка при создании очереди: "
  327. << error.what() << '\n';
  328.  
  329. return 1;
  330. }
  331. catch (const std::exception& error) {
  332. std::cerr
  333. << "Непредвиденная ошибка: "
  334. << error.what() << '\n';
  335.  
  336. return 1;
  337. }
  338.  
  339. return 0;
  340. }
Success #stdin #stdout 0s 5320KB
stdin
Standard input is empty
stdout
=== 1. Начальное состояние очереди ===
Очередь: пуста
Индекс начала (front): 0, индекс конца (rear): 0, размер: 0, вместимость: 5

=== 2. Добавление элементов ===
Очередь: 10 20 30
Индекс начала (front): 0, индекс конца (rear): 3, размер: 3, вместимость: 5

=== 3. Просмотр первого и последнего элемента ===
Первый элемент: 10
Последний элемент: 30

=== 4. Удаление элемента ===
После удаления первого элемента:
Очередь: 20 30
Индекс начала (front): 1, индекс конца (rear): 3, размер: 2, вместимость: 5

=== 5. Проверка циклического массива ===
Очередь: 20 30 40 50 60
Индекс начала (front): 1, индекс конца (rear): 1, размер: 5, вместимость: 5
Освободившаяся позиция массива была использована повторно.
Элементы очереди не сдвигаются.

=== 6. Проверка заполнения очереди ===
Очередь: 20 30 40 50 60
Очередь заполнена: да

=== 7. Проверка переполнения ===
Переполнение обработано корректно: Очередь заполнена

=== 8. Повторное использование освободившихся ячеек ===
После удаления двух элементов:
Очередь: 40 50 60
Индекс начала (front): 3, индекс конца (rear): 1, размер: 3, вместимость: 5
После добавления новых элементов:
Очередь: 40 50 60 70 80
Индекс начала (front): 3, индекс конца (rear): 3, размер: 5, вместимость: 5

=== 9. Проверка размера очереди ===
Текущий размер очереди: 5
Максимальный размер очереди: 5
Очередь пуста: нет
Очередь заполнена: да

=== 10. Очистка очереди ===
Очередь: пуста
Индекс начала (front): 0, индекс конца (rear): 0, размер: 0, вместимость: 5
Очередь пуста: да

=== 11. Проверка удаления из пустой очереди ===
Удаление из пустой очереди обработано корректно: Очередь пуста

=== 12. Повторное использование после очистки ===
Очередь: 100 200
Индекс начала (front): 0, индекс конца (rear): 2, размер: 2, вместимость: 5
Первый элемент: 100
Последний элемент: 200

=== Все проверки успешно завершены ===