|
| 1 | +# Queue |
| 2 | + |
| 3 | +<p style="text-align: left"> |
| 4 | + <a href="#русский">Русский</a> ・ <a href="#english">English</a> |
| 5 | +</p> |
| 6 | + |
| 7 | +--- |
| 8 | + |
| 9 | +## Русский |
| 10 | + |
| 11 | +Очередь — линейная структура данных, работающая по принципу **FIFO** (First In, First Out): элемент, добавленный первым, извлекается первым. Это полная противоположность стеку. |
| 12 | + |
| 13 | +Пример: если добавить элементы в порядке `1, 2, 3`, то первым выйдет `1`, затем `2`, затем `3`. Порядок выхода в точности повторяет порядок входа. |
| 14 | + |
| 15 | +### Внутреннее устройство |
| 16 | + |
| 17 | +Реализация использует кольцевой буфер на основе среза `arr`, два индекса — `head` и `tail`, а также счётчик `count`. |
| 18 | + |
| 19 | +- `head` указывает на ячейку, из которой будет читать следующая операция `Dequeue` или `Peek`. |
| 20 | +- `tail` указывает на ячейку, в которую запишет следующая операция `Enqueue`. |
| 21 | +- `count` хранит текущее число элементов в очереди. Оно необходимо, чтобы различать состояния «пуста» и «полна», так как при `head == tail` буфер может быть и пустым, и полностью заполненным — только счётчик даёт ответ. |
| 22 | + |
| 23 | +При добавлении элемента (`Enqueue`) значение записывается в `arr[tail]`, после чего `tail` сдвигается циклически вперёд по формуле `(tail + 1) % len(arr)`, а `count` увеличивается на единицу. |
| 24 | + |
| 25 | +При извлечении (`Dequeue`) читается `arr[head]`, затем `head` сдвигается вперёд так же циклически, а `count` уменьшается. |
| 26 | + |
| 27 | +Фиксированная ёмкость очереди задаётся при создании и не меняется. Попытка добавить элемент в заполненную очередь приводит к ошибке, как и попытка извлечь из пустой. |
| 28 | + |
| 29 | +Дополнительно доступны методы `Size()` (возвращает `count`) и `Cap()` (возвращает `len(arr)`), позволяющие узнать текущую заполненность и предельную вместимость. |
| 30 | + |
| 31 | +### Использование |
| 32 | + |
| 33 | +```go |
| 34 | +q, err := NewQueue[int](3) |
| 35 | +if err != nil { |
| 36 | + // обработать неверную ёмкость |
| 37 | +} |
| 38 | +q.Enqueue(10) |
| 39 | +q.Enqueue(20) |
| 40 | +val, _ := q.Dequeue() // val = 10 |
| 41 | +``` |
| 42 | + |
| 43 | +### Операции |
| 44 | + |
| 45 | +| Операция | Сложность | Описание | |
| 46 | +|---|---|---| |
| 47 | +| `Enqueue(x)` | O(1) | добавить элемент в конец очереди | |
| 48 | +| `Dequeue()` | O(1) | извлечь элемент из начала очереди | |
| 49 | +| `Peek()` | O(1) | посмотреть элемент в начале, не удаляя | |
| 50 | +| `IsEmpty()` | O(1) | проверка, пуста ли очередь | |
| 51 | +| `IsFull()` | O(1) | проверка, заполнена ли очередь | |
| 52 | +| `Size()` | O(1) | текущее количество элементов | |
| 53 | +| `Cap()` | O(1) | максимальная ёмкость | |
| 54 | + |
| 55 | +### Сборка и тестирование |
| 56 | + |
| 57 | +```bash |
| 58 | +go test -v ./... |
| 59 | +``` |
| 60 | + |
| 61 | +Корректность проверяется с помощью набора модульных тестов, покрывающих граничные случаи, циклическое поведение индексов и стресс-теста, который сравнивает поведение очереди с эталонной реализацией на срезе. |
| 62 | + |
| 63 | +--- |
| 64 | + |
| 65 | +## English |
| 66 | + |
| 67 | +A queue is a linear data structure that follows the **FIFO** principle (First In, First Out): the element inserted first is the first one to be removed. It is the exact opposite of a stack. |
| 68 | + |
| 69 | +Example: inserting elements in the order `1, 2, 3` will retrieve `1` first, then `2`, then `3`. The order of removal precisely matches the order of insertion. |
| 70 | + |
| 71 | +### Internal layout |
| 72 | + |
| 73 | +The implementation uses a circular buffer built on a slice `arr`, two indices `head` and `tail`, and a counter `count`. |
| 74 | + |
| 75 | +- `head` points to the cell from which the next `Dequeue` or `Peek` operation will read. |
| 76 | +- `tail` points to the cell where the next `Enqueue` operation will write. |
| 77 | +- `count` holds the current number of elements. It is essential to tell apart the empty and full states, because when `head == tail` the buffer could be either empty or completely full — only the counter provides the answer. |
| 78 | + |
| 79 | +When an element is added (`Enqueue`), the value is stored in `arr[tail]`, then `tail` advances circularly via `(tail + 1) % len(arr)`, and `count` increases by one. |
| 80 | + |
| 81 | +When an element is removed (`Dequeue`), the value at `arr[head]` is read, then `head` advances circularly in the same way, and `count` decreases. |
| 82 | + |
| 83 | +The fixed capacity of the queue is set at creation and never changes. Inserting into a full queue or removing from an empty one both result in errors. |
| 84 | + |
| 85 | +Additionally, `Size()` (returns `count`) and `Cap()` (returns `len(arr)`) are provided to inspect how many elements are currently stored and what the maximum capacity is. |
| 86 | + |
| 87 | +### Usage |
| 88 | + |
| 89 | +```go |
| 90 | +q, err := NewQueue[int](3) |
| 91 | +if err != nil { |
| 92 | + // handle invalid capacity |
| 93 | +} |
| 94 | +q.Enqueue(10) |
| 95 | +q.Enqueue(20) |
| 96 | +val, _ := q.Dequeue() // val = 10 |
| 97 | +``` |
| 98 | + |
| 99 | +### Operations |
| 100 | + |
| 101 | +| Operation | Complexity | Description | |
| 102 | +|---|---|---| |
| 103 | +| `Enqueue(x)` | O(1) | add an element to the back of the queue | |
| 104 | +| `Dequeue()` | O(1) | remove and return the front element | |
| 105 | +| `Peek()` | O(1) | return the front element without removing | |
| 106 | +| `IsEmpty()` | O(1) | check whether the queue is empty | |
| 107 | +| `IsFull()` | O(1) | check whether the queue is at capacity | |
| 108 | +| `Size()` | O(1) | current number of elements | |
| 109 | +| `Cap()` | O(1) | maximum capacity | |
| 110 | + |
| 111 | +### Build and test |
| 112 | + |
| 113 | +```bash |
| 114 | +go test -v ./... |
| 115 | +``` |
| 116 | + |
| 117 | +Correctness is verified through a suite of unit tests that cover edge cases, circular index wrapping, and a stress test that compares the queue's behavior against a reference slice-based implementation. |
| 118 | + |
| 119 | +--- |
| 120 | + |
| 121 | +<br> |
| 122 | + |
| 123 | +> Очередь не смотрит на важность, не слышит просьб пропустить вперёд. Она знает только одно: кто пришёл раньше, тот и уйдёт раньше. В этом её слепая справедливость. |
| 124 | +> |
| 125 | +> *A queue does not look at importance, nor does it hear pleas to skip ahead. It knows only one thing: whoever came first leaves first. In that lies its blind justice.* |
0 commit comments