Learning Platform
Troubleshooting
Глоссарий

Глоссарий — DSA 01

Справочник ключевых терминов курса DSA 01.

6 категорий · 86 терминов

complexity

Big-O notation

Термин

Асимптотическая верхняя граница роста функции. f(n) = O(g(n)) означает, что при больших n значение f(n) не превышает константу, умноженную на g(n). Используется для описания худшего случая времени или памяти алгоритма, отбрасывая константы и младшие члены.

Big-Theta notation

Термин

Асимптотически точная граница. f(n) = Theta(g(n)) означает, что f(n) ограничена и сверху, и снизу константами, умноженными на g(n). Сильнее, чем Big-O: Theta(n) — это и O(n), и Omega(n) одновременно.

Big-Omega notation

Термин

Асимптотическая нижняя граница. f(n) = Omega(g(n)) означает, что f(n) растёт не медленнее, чем константа, умноженная на g(n). Используется для нижних границ алгоритмов (например, сортировка сравнениями — Omega(n log n)).

amortized analysis

Термин

Метод анализа, при котором стоимость операции усредняется по последовательности из N операций. Отдельная операция может быть дорогой (resize массива — O(n)), но в среднем по последовательности она дешёвая (append — O(1) amortized). Это не то же самое, что average case.

aggregate method

Термин

Простейший способ доказать амортизированную сложность: посчитать суммарную стоимость T(n) для последовательности из n операций и поделить на n. Для x2 dynamic array сумма работы copy при resize — геометрическая прогрессия, меньше 2n, что даёт amortized O(1) на append.

accounting method

Термин

Банковский метод амортизации: каждой операции назначается амортизированная плата (больше реальной), излишек откладывается в «банк». Дорогие операции (resize) оплачиваются из банка. Если банк никогда не уходит в минус, амортизированная плата — корректная верхняя граница.

potential method

Термин

Формальный метод амортизации: вводится функция потенциала Phi от состояния структуры, amortized cost = actual cost + delta(Phi). Если Phi >= 0 и Phi_initial = 0, сумма amortized — верхняя граница реальной стоимости. Используется для сложных структур: splay tree, Fibonacci heap.

time complexity

Термин

Зависимость количества элементарных операций алгоритма от размера входа n. Меряется в Big-O: O(1) — константа, O(log n) — логарифм, O(n) — линейно, O(n log n) — сортировка сравнениями, O(n^2) — квадрат, O(2^n) — экспонента.

space complexity

Термин

Зависимость объёма памяти, нужного алгоритму, от размера входа n. Включает auxiliary space (рабочая память) и input space (сам вход). BFS — O(n) по памяти (нужна очередь), DFS — O(h) (глубина стека).

P

Термин

Класс задач, решаемых за полиномиальное время O(n^k) для константы k. Сюда входят сортировки, поиск, графовые обходы, кратчайшие пути. «Эффективно решаемые» в теоретическом смысле.

NP

Термин

Класс задач, решение которых можно проверить за полиномиальное время. Сюда входят все задачи из P, плюс задачи, для которых решения мы пока умеем находить только перебором (SAT, коммивояжёр). Открытый вопрос: P = NP?

NP-complete

Термин

Самые «трудные» задачи в NP: если для любой NP-complete найдётся полиномиальный алгоритм, то P = NP. Классические примеры: SAT, 3-COLOR, TSP, subset sum. На практике решаются эвристиками и приближёнными алгоритмами.

data-structure

array

Термин

Структура данных с фиксированным размером, элементы которой лежат в непрерывной памяти по равным offset-ам. Доступ по индексу — O(1). В Python чистого статического array нет; есть module array и numpy.ndarray для однотипных элементов.

dynamic array

Термин

Массив, который умеет расти при заполнении: при достижении ёмкости выделяется новый буфер большего размера (обычно x2 или x1.125), элементы копируются. Append амортизированно O(1), вставка в середину O(n). В Python это PyListObject.

linked list

Термин

Структура данных, в которой каждый элемент (узел) хранит данные и указатель на следующий узел. Узлы лежат в произвольных местах памяти. Insert/delete в начало — O(1), доступ по индексу — O(n). На современном железе медленнее массива из-за pointer chasing.

singly linked

Термин

Связный список, в котором каждый узел хранит указатель только на следующий. Удаление текущего узла за O(1) невозможно без предыдущего узла. Меньше памяти на узел, чем у doubly linked.

doubly linked

Термин

Связный список, в котором каждый узел хранит указатели и на следующий, и на предыдущий. Позволяет O(1) удаление узла, если есть ссылка на него. Используется внутри collections.deque и LRU cache.

stack

Термин

LIFO-структура: push и pop работают с одного конца. O(1) на обе операции. Реализуется поверх dynamic array (Python list) или связного списка. Применяется в DFS, парсерах, undo-историях, call stack.

queue

Термин

FIFO-структура: enqueue в конец, dequeue из начала. O(1) на обе операции в правильной реализации. В Python — collections.deque, не list (list.pop(0) — O(n)).

deque

Термин

Double-ended queue — структура, которая поддерживает O(1) добавление и удаление с обоих концов. В CPython collections.deque реализован как doubly linked list блоков (по 64 элемента в блоке), а не как массив.

ring buffer

Термин

Циклический массив фиксированного размера с двумя указателями (head и tail). Push/pop с обоих концов — O(1). Используется в low-latency-системах, аудио-буферах, network drivers. Хорошая spatial locality в отличие от связных списков.

hash map

Термин

Структура key -> value, использующая хеш-функцию для размещения ключа в bucket. Средняя сложность операций — O(1), худший случай — O(n) при плохом хеше. В Python это dict, реализованный через open addressing с perturbation.

hash set

Термин

Множество уникальных элементов на основе хеш-таблицы. В Python — set/frozenset. Внутренне почти идентичен dict, но без значений. O(1) на add/remove/in в среднем.

BST

Термин

Binary search tree — бинарное дерево, в котором для каждого узла левое поддерево содержит ключи меньше узла, правое — больше. Поиск, вставка, удаление — O(h), где h — высота. Без балансировки h может выродиться в n. Балансированные варианты: AVL, red-black.

binary heap

Термин

Полное бинарное дерево, хранящееся в массиве, со свойством heap (родитель меньше или равен детям для min-heap). Insert и extract-min — O(log n), peek — O(1). Используется для priority queue и heap sort. Дети узла i лежат на 2i+1 и 2i+2.

min-heap

Термин

Куча, в которой корень — минимальный элемент. Используется в priority queue (sched), top-K largest (хранить top-K через min-heap размера K), Dijkstra. Python heapq реализует именно min-heap.

max-heap

Термин

Куча, в которой корень — максимальный элемент. Применяется в heap sort, top-K smallest (через max-heap размера K), task schedulers. В Python максимум через heapq делается через инверсию знаков или кортежи (-key, value).

graph

Термин

Структура из вершин (V) и рёбер (E), описывающая отношения. Бывает направленный или ненаправленный, взвешенный или нет. Используется в DE для lineage, DAG-ов оркестрации (Airflow), графов транзакций. Представления: adjacency matrix, adjacency list, CSR.

adjacency matrix

Термин

Представление графа квадратной матрицей V x V, где matrix[i][j] = 1 если есть ребро. Память O(V^2), проверка ребра — O(1), обход соседей — O(V). Выгодна для плотных графов и алгоритмов вроде Floyd-Warshall.

adjacency list

Термин

Представление графа как dict (или массив) списков: для каждой вершины — список соседей. Память O(V + E), обход соседей — O(degree). Выгодно для разреженных графов. В Python обычно dict[int, list[int]] или defaultdict(list).

CSR

Термин

Compressed Sparse Row — компактное представление графа двумя массивами: offsets (где начинаются соседи каждой вершины) и indices (сами соседи). Отличная spatial locality, в 2-4 раза быстрее adjacency list в обходах. Используется в scipy.sparse, NetworkX-аналогах для больших графов.

memory

cache line

Термин

Минимальная единица, которой CPU читает из RAM в кэш — 64 байта на современных x86 и ARM. Чтение одного байта физически невозможно — всегда подгружаются 64 байта, выровненных по границе. Это основа spatial locality.

L1 cache

Термин

Первый уровень кэша CPU — обычно 32-64 KB на ядро, latency ~1 ns (3-4 такта). Разделён на L1d (данные) и L1i (инструкции). Самый быстрый, но самый маленький. Промах в L1 ведёт к чтению из L2.

L2 cache

Термин

Второй уровень кэша — обычно 256 KB - 1 MB на ядро, latency ~3-5 ns (10-15 тактов). Больше L1, медленнее. Промах ведёт к L3 или RAM.

L3 cache

Термин

Третий уровень кэша — обычно 4-64 MB, общий для всех ядер сокета. Latency ~10-20 ns. Последний уровень перед RAM. Промах — это уже ~60-100 ns на чтение из RAM.

RAM

Термин

Random Access Memory — основная память. Latency ~60-100 ns на чтение, в 60-100 раз медленнее L1. Чтение всегда выровнено по cache line. Имя «random access» обманчиво: последовательный доступ быстрее случайного из-за prefetcher и cache lines.

spatial locality

Термин

Свойство паттерна доступа: если код обращается к адресу X, скоро понадобятся X+1, X+2 и так далее. Превращает дорогие RAM-чтения в почти бесплатные cache hits. Хорошо: проход по массиву. Плохо: random access, linked list.

temporal locality

Термин

Свойство: если код обратился к X, скоро обратится к X снова. Cache держит недавние данные именно ради этого. Хорошо: переменная цикла в регистре, hot-data в hash-таблице. Плохо: однократный проход через гигантский dataset.

prefetcher

Термин

Аппаратный механизм CPU, который предсказывает следующие читаемые адреса и заранее подгружает их в кэш. Хорошо работает на sequential access. Не работает на linked list — указатели непредсказуемы.

branch prediction

Термин

Аппаратный механизм CPU: пытается предсказать, по какой ветке пойдёт if, чтобы не останавливать конвейер. Промах предсказания (branch misprediction) — 10-20 тактов простоя. Хорошо предсказываются монотонные паттерны (отсортированный массив), плохо — случайные.

pipeline

Термин

Конвейерное исполнение инструкций в CPU: пока одна инструкция декодируется, следующая уже читает операнды, следующая исполняется. На современных CPU — 14-20 стадий. Промах branch prediction или cache miss обнуляет полезную работу нескольких стадий.

pointer chasing

Термин

Паттерн доступа, при котором каждый следующий адрес становится известен только после чтения предыдущего (next = node.next). Prefetcher беспомощен, каждая итерация — потенциальный cache miss. Отсюда — медленность linked list, BST, graph через объекты.

sequential access

Термин

Последовательный проход по памяти с постоянным offset (arr[0], arr[1], arr[2]). Оптимальный паттерн: prefetcher успевает подгружать следующие cache lines, каждый доступ — cache hit. Основа быстрых обходов массивов и numpy.

memory hierarchy

Термин

Иерархия памяти: регистры (sub-ns) -> L1 (1 ns) -> L2 (3-5 ns) -> L3 (10-20 ns) -> RAM (60-100 ns) -> SSD (10000 ns) -> HDD (10 ms). Каждый уровень в 3-100 раз медленнее предыдущего. DSA-выбор должен учитывать, в какой уровень попадут данные.

algorithm

BFS

Термин

Breadth-first search — обход графа по уровням: сначала все соседи стартовой вершины, потом их соседи, и так далее. Использует очередь (collections.deque). Сложность O(V + E). Находит кратчайший путь в невзвешенном графе. Память — O(V).

DFS

Термин

Depth-first search — обход графа в глубину: спускаемся по одной ветке как можно глубже, затем откат. Использует стек (рекурсия или явный stack). O(V + E) по времени, O(h) по памяти, где h — глубина. Основа топологической сортировки.

binary search

Термин

Поиск элемента в отсортированном массиве делением пополам: O(log n). Реализован в bisect (Python). Тонкие места: off-by-one на границах, выбор upper vs lower bound, обработка дубликатов. Не работает на linked list — нужен random access.

linear search

Термин

Поиск элемента простым проходом: O(n) в худшем случае. На малых n (десятки элементов) обгоняет binary search и hash из-за лучшей cache locality и отсутствия overhead. Лучший выбор для коротких списков.

bubble sort

Термин

Простая сортировка: проходим массив, меняем соседей местами если нарушен порядок, повторяем. O(n^2) в худшем и среднем случае. Стабильная. Практически нигде не используется, кроме учебных целей.

insertion sort

Термин

Сортировка вставками: берём элемент, сдвигаем влево, пока не найдёт своё место. O(n^2) в худшем, O(n) на почти отсортированном. Используется как «нижний этаж» Timsort и introsort для малых подмассивов (обычно n < 32-64).

selection sort

Термин

Сортировка выбором: находим минимум в неотсортированной части и ставим в начало. O(n^2) всегда, не зависит от входных данных. Делает минимум swap-ов — O(n). Используется редко, в основном на embedded.

merge sort

Термин

Сортировка слиянием: рекурсивно делим массив пополам, сортируем половины, сливаем. O(n log n) по времени всегда. O(n) дополнительной памяти. Стабильная. Базис Timsort и внешней сортировки (k-way merge на дисках).

quicksort

Термин

Сортировка через partitioning вокруг pivot. Среднее — O(n log n), худший случай — O(n^2) (плохой pivot). Не стабильная, in-place. С randomized pivot или median-of-three используется в introsort (libc++, .NET).

Timsort

Термин

Гибридная стабильная сортировка, использующая insertion sort на малых блоках (runs) и merge sort для их слияния. Использует естественно отсортированные участки. O(n log n) в худшем, O(n) на отсортированном. Стандартная сортировка в Python и Java.

heapsort

Термин

Сортировка через построение max-heap и последовательный extract-max. O(n log n) в худшем случае, in-place. Не стабильная. Хуже Timsort на cache locality (произвольные обмены в массиве), используется реже.

radix sort

Термин

Не-сравнительная сортировка: распределяем элементы по «корзинам» по цифрам/битам, повторяя по разрядам. O(n * k), где k — длина ключа. Работает только на целых или строках фиксированной длины. Быстрее O(n log n) при больших n и коротких ключах.

counting sort

Термин

Не-сравнительная сортировка для целых из малого диапазона [0, k]: считаем сколько раз встретился каждый ключ, потом раскладываем. O(n + k) по времени и памяти. Стабильная. Используется как «низший уровень» radix sort.

partition

Термин

Операция разделения массива относительно pivot: слева — меньше или равно, справа — больше. Базовая операция quicksort. Lomuto и Hoare — два классических варианта. Один проход — O(n).

heapify

Термин

Построение кучи из массива за O(n) (а не O(n log n), как могло бы показаться). Идея: пройти от середины массива к началу, для каждого узла «просеять» вниз. Используется при инициализации heap (heapq.heapify).

k-way merge

Термин

Слияние k отсортированных последовательностей в одну. Через min-heap размера k: O(N log k), где N — суммарное число элементов. Основа external sort и merge-операции в Spark/Flink shuffle.

divide-and-conquer

Термин

Парадигма: задачу делим на меньшие подзадачи того же типа, решаем рекурсивно, объединяем. Merge sort, quicksort, binary search, FFT, Strassen. Анализ через рекуррентные соотношения и Master Theorem.

python-internal

PyListObject

Термин

C-структура CPython, реализующая list. Содержит указатель на массив PyObject*, длину и ёмкость. При переполнении ёмкости growth-формула CPython: new = (old + (old >> 3) + 6) & ~3 — рост примерно x1.125, не x2.

PyObject pointer

Термин

Указатель на структуру PyObject — представление любого Python-объекта на уровне C. В list хранятся именно указатели (8 байт на 64-битке), а не сами объекты. Поэтому list[int] на 1M элементов весит около 36 MB (8 байт на указатель плюс 28 байт на сам PyLongObject), а не 4 MB.

dict probing

Термин

Стратегия поиска свободного слота в Python dict при коллизии: j = (5*j + 1 + perturb) & mask, perturb >>= 5. Использует все биты хеша через perturbation, гарантирует обход всех слотов до повторения.

perturbation

Термин

Техника в Python dict probing: переменная perturb, изначально равная полному хешу, сдвигается на 5 битов каждую итерацию. Подключает старшие биты хеша к probing — ключи с одинаковыми младшими битами расходятся по разным слотам.

SipHash

Термин

Криптографически безопасная хеш-функция, которую CPython использует для hash(str), hash(bytes). Защищает от hash-flooding атак: при старте процесса генерируется случайный seed (PYTHONHASHSEED), поэтому hash(s) одной строки разный между запусками.

sys.getsizeof

Термин

Функция CPython: возвращает размер объекта в байтах без учёта объектов, на которые он ссылается. Поэтому sys.getsizeof([1,2,3]) даёт размер самого list-объекта (~88 байт), но не учитывает int-ов внутри. Для глубокого размера — pympler.asizeof.

pympler.asizeof

Термин

Утилита для рекурсивного измерения памяти Python-объектов: считает размер вместе со всеми ссылками, обрабатывая циклы. Медленнее sys.getsizeof, но даёт реальное потребление памяти структурой.

timeit

Термин

Модуль stdlib для микро-бенчмаркинга Python-кода: запускает фрагмент N раз, выключая GC, и возвращает время. timeit.timeit(stmt, number=10000) — основа всех измерений в курсе. Чувствителен к шуму CPU, fan-curve, фоновым процессам.

tracemalloc

Термин

Модуль stdlib для трекинга аллокаций памяти Python-программы. Показывает, где (по строкам кода) и сколько байт было выделено. Лучше sys.getsizeof для поиска утечек и узких мест в реальных пайплайнах.

collections.deque

Термин

Двусторонняя очередь CPython, реализованная как doubly linked list блоков по 64 указателя. appendleft, append, popleft, pop — O(1). Используется для BFS, sliding window, history buffer. Быстрее list для head-операций.

heapq

Термин

Модуль stdlib для работы с min-heap поверх обычного list. heappush, heappop — O(log n). heapify — O(n). nlargest, nsmallest — частые операции для top-K. Не имеет max-heap — нужна инверсия знаков.

sortedcontainers

Термин

Чистый Python-пакет, дающий SortedList/SortedDict/SortedSet с O(log n) на insert/delete/lookup. Внутри — список списков (B-tree-подобная структура), а не RB-tree. На практике быстрее BST из-за cache locality.

GIL

Термин

Global Interpreter Lock — глобальная блокировка CPython, разрешающая исполнять Python-байткод только одному потоку за раз. Из-за GIL multi-threading в Python не даёт CPU-параллелизма на чистом Python-коде. В 3.13 появился экспериментальный no-GIL build.

refcount

Термин

Reference counting — основной механизм управления памятью в CPython. Каждый объект хранит счётчик ссылок, при достижении нуля объект освобождается. Видно через sys.getrefcount(obj). Не справляется с циклическими ссылками — для них есть GC.

applied

top-K

Термин

Задача: найти K самых больших (или маленьких) элементов в потоке из N. Наивно через sort — O(N log N). Через min-heap размера K — O(N log K), сильно лучше при K << N. Базовый паттерн в DE: top-N клиентов по выручке.

dedup

Термин

Дедупликация — удаление повторяющихся записей. Через set — O(N) по времени, O(N) по памяти. На миллиардах записей set не помещается в RAM — нужны Bloom filter (вероятностный) или внешняя сортировка с merge.

Bloom filter

Термин

Вероятностная структура для проверки принадлежности множеству. Битовый массив + k хеш-функций. Не даёт false negatives (если говорит «нет», то точно нет), но допускает false positives. В 8-10 раз меньше памяти, чем set. Используется в Cassandra, HBase, RocksDB.

sliding window

Термин

Окно фиксированного размера W, которое скользит по потоку: на каждом шаге добавляется новый элемент справа, выкидывается крайний слева. O(1) на шаг через deque или ring buffer. Базовый паттерн стриминговых агрегаций.

tumbling window

Термин

Не-перекрывающееся окно фиксированного размера: события группируются в блоки по времени или количеству. Используется в Flink/Spark Structured Streaming для агрегаций по периодам (минуты, часы).

session window

Термин

Окно переменного размера, определяемое gap-ом неактивности: события одной сессии группируются, пока разрыв между ними меньше threshold. Используется для аналитики поведения пользователей: визит на сайт, активность в приложении.

external sort

Термин

Сортировка данных, не помещающихся в RAM. Классический алгоритм: разделить на чанки по размеру памяти, отсортировать каждый, записать на диск, сделать k-way merge на дисках. O(N log N) по сравнениям, но с минимизацией I/O.

lineage graph

Термин

DAG зависимостей между датасетами и трансформациями в пайплайне: какая таблица из какой получена и какой операцией. Хранится в Marquez, DataHub, OpenLineage. Используется для impact analysis и debug «откуда взялась эта строчка».

DAG

Термин

Directed acyclic graph — направленный граф без циклов. Базовая абстракция оркестраторов (Airflow, Dagster, Prefect): вершины — задачи, рёбра — зависимости. Допускает топологическую сортировку — порядок исполнения задач.

topological sort

Термин

Линейный порядок вершин DAG, в котором каждое ребро направлено вперёд. Алгоритм Кана: O(V + E) через очередь вершин с in-degree=0. Используется в оркестраторах для определения порядка задач, в build-системах, при проверке зависимостей пакетов.

LRU cache

Термин

Least-Recently-Used cache — хранит K последних использованных элементов, при переполнении выкидывает least-recently-used. Реализуется через doubly linked list + hash map: O(1) на get и put. В Python — functools.lru_cache.