Skip to content

Commit 4aea0f2

Browse files
committed
Deque
1 parent be66332 commit 4aea0f2

1 file changed

Lines changed: 45 additions & 2 deletions

File tree

src/main/java/algorithms/sprint2/Deque.java

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,49 @@
55
import java.io.InputStream;
66
import java.io.OutputStream;
77

8+
/*
9+
Принцип работы алгоритма
10+
Используется дек фиксированного размера m, реализованный на массиве как кольцевой буфер.
11+
Храним:
12+
- a[] — массив ёмкости m;
13+
- head — индекс первого элемента дека;
14+
- tail — индекс позиции "после последнего" элемента дека;
15+
- size — текущее количество элементов.
16+
17+
Индексы head и tail двигаются по кругу: при выходе за границу массива переходят в начало/конец.
18+
Операции:
19+
- push_back(x): записать x в a[tail], сдвинуть tail вперёд по кругу, увеличить size.
20+
- push_front(x): сдвинуть head назад по кругу, записать x в a[head], увеличить size.
21+
- pop_front(): взять a[head], сдвинуть head вперёд, уменьшить size.
22+
- pop_back(): сдвинуть tail назад, взять a[tail], уменьшить size.
23+
24+
Корректность (почему работает)
25+
Поддерживаются инварианты:
26+
1) size всегда в диапазоне [0..m].
27+
2) head указывает на первый элемент (если size > 0).
28+
3) tail указывает на позицию сразу после последнего элемента (если size > 0).
29+
4) Элементы дека в порядке обхода лежат в a по циклу, начиная с head и длиной size.
30+
31+
Проверка по операциям:
32+
- push_back при size < m кладёт новый элемент ровно в позицию tail, затем tail сдвигается на следующую
33+
позицию по кругу, поэтому tail снова указывает на "после последнего", а порядок элементов сохраняется.
34+
- push_front при size < m сначала сдвигает head на предыдущую позицию по кругу и кладёт туда новый элемент,
35+
поэтому head начинает указывать на добавленный элемент (он становится первым), а порядок сохраняется.
36+
- pop_front при size > 0 читает первый элемент из a[head], затем сдвигает head вперёд, уменьшая size:
37+
новым первым становится следующий элемент, инварианты сохраняются.
38+
- pop_back при size > 0 сначала сдвигает tail назад (на позицию последнего элемента), читает его и уменьшает size:
39+
tail снова становится "после последнего", инварианты сохраняются.
40+
41+
Ошибки "error" выводятся только когда операция невозможна:
42+
- push_* при size == m (переполнение),
43+
- pop_* при size == 0 (пустой дек).
44+
В этих случаях состояние (head, tail, size) не меняется, что сохраняет инварианты.
45+
46+
Сложность
47+
Каждая операция дека выполняет константное число действий: O(1) по времени.
48+
Память: массив из m элементов и несколько целых переменных: O(m) по памяти.
49+
*/
50+
851
public class Deque {
952

1053
// -------------------- FAST INPUT --------------------
@@ -296,7 +339,7 @@ private static void test() throws Exception {
296339
)
297340
);
298341

299-
// Емкость 1 + переполнение
342+
// Емкость 1 + переполнение + попытка pop из пустого
300343
assertEq(
301344
"error\n1\nerror\n",
302345
solveIO(
@@ -309,7 +352,7 @@ private static void test() throws Exception {
309352
)
310353
);
311354

312-
// Проверка кольцевого перехода (wrap-around)
355+
// Wrap-around: head/tail должны корректно "перепрыгивать" границу массива
313356
assertEq(
314357
"1\n4\n2\n3\n",
315358
solveIO(

0 commit comments

Comments
 (0)