Операторы break и continue – базовые средства управления циклическими процессами. Первый немедленно завершает текущий цикл (или ближайший вложенный), второй пропускает остаток тела итерации и переходит к следующей проверке условия. Текст системно описывает формальную семантику, правила корректного проектирования алгоритмов с ранним завершением и пропуском шага, взаимодействие с инвариантами, оценку сложности и типичные идиомы (поиск первого/минимального, ранний выход при обнаружении контрпримера, фильтрация). Показана прямая связь с компетенциями ЕГЭ: трассировка программ, подсчёт операций, преобразование циклов, корректное чтение условий, работа с файлами/массивами. Завершает материал практикум из пяти упражнений стандарта ЕГЭ.
Цикл как конструкция управления
Цикл – повторение тела при выполнении предиката продолжения P.В абстрактной форме:
while P do
T // тело цикла
end
или
for i in Range do
T
end
Семантика break
break – немедленный выход из ближайшего активного цикла, минуя оставшиеся операторы текущей итерации и прыгая в точку после цикла. В языках семейства C/C++/Java break также завершает switch-ветвь; в алгоритмическом псевдокоде и Python под break обычно понимают завершение только цикла.
Гарантии:
Тело после break в текущей итерации не выполняется.
Состояние после выхода – такое, как если бы предикат продолжения стал ложным.
Семантика continue
continue – пропуск остатка тела текущей итерации с переходом к следующему шагу цикла:
для while – к повторной проверке условия P;
для for (с управляющим счётчиком) – к шагу обновления счётчика и/или взятию следующего значения из диапазона/итератора.
Гарантии:
Принцип минимальной области действия.
Применяйте break/continue только там, где их эффект локален и очевиден из условия; избегайте глубоких вложенностей, требующих «мысленного прыжка» через десятки строк.
Явный предикат выхода/пропуска.
Формулируйте читаемые условия:
if найден_ответ then break
if элемент_не_подходит then continue
Сохранение инварианта цикла.
Перед continue обязателен завершённый шаг поддержания инварианта (например, инкремент счётчика или продвижение итератора в ручных схемах). Если инвариант нарушён, возможны зацикливания или пропуски.
Одно место завершения – по возможности.
Хороший стиль – не плодить несколько break в одной ветви. Однако для раннего выхода по найденному контрпримеру (поиск первого, проверка «все/существует») break улучшает сложность и читаемость.
Ранний выход вместо флага.
Если единственная цель флага found – остановить цикл, break предпочтительнее: меньше ветвлений, ниже когнитивная нагрузка.
Сложность и кратчайшее доказательство.
break часто переводит худший случай O(n) в средний O(k) при первом срабатывании на позиции k. При проектировании приводите оценку: «ранний выход ограничивает среднее время обратной величиной плотности удачных событий».
Корректная обработка ресурсов.
Если в теле цикла открываются ресурсы (файлы, соединения), перед break обеспечьте их закрытие или используйте языковые RAII/with-конструкции (в теоретической записи – «выход через охраняющий блок»).
Не подменять условие цикла.
Если каждая итерация начинается с if not P then break, вероятно, предикат должен стоять в заголовке цикла; оставляйте break для исключительных
условий (найден ответ, ошибка формата, невозможно продолжать).
Идемпотентность continue.
Всё, что остаётся «за continue», не должно иметь побочных эффектов, критичных для следующей итерации (накопление результата, продвижение курсора и пр.).
Поиск первого вхождения (ранний выход)
pos := -1
for i in 0..n-1 do
if A[i] == x then
pos := i
break
end
Сложность: лучший случай Θ(1), средний ≈ Θ(n/2), худший Θ(n).

isPrime(n):
if n < 2 then return false
for d in 2..floor(sqrt(n)) do
if n mod d == 0 then return false // break не нужен – мгновенный return
end
return true
Если return недопустим внутри цикла (например, в учебном псевдоязыке), используйте found := true; break.
Фильтрация (пропуск неподходящих элементов)
sum := 0
for x in Stream do
if not условие(x) then continue
sum := sum + weight(x) // выполняется только для подходящих
end
Вложенные циклы и «двойной разрыв»
found := false
for i in 0..n-1 do
for j in 0..m-1 do
if predicate(A[i], B[j]) then
found := true
break // выходит только из внутреннего
end
if found then break // наружный следит за флагом
end
(В языках с метками допускается break outer;, но в алгоритмическом стандарте ЕГЭ – через флаг.)
Обработка файла до «сторожа» (sentinel)
count := 0
while read(x) do // чтение успешно
if x == SENTINEL then break
if not isValid(x) then continue
count := count + 1
end
Пусть цикл вычисляет агрегат R. Инвариант: перед каждой итерацией R содержит правильный результат по уже обработанным элементам.
При continue инвариант должен сохраняться: раз данные не учитываются, агрегат не изменяется либо изменяется в согласии с условием.
При break инвариант гарантирует завершённость: все элементы до момента разрыва учтены корректно, а дальнейшие не требуются по логике задачи (например, «найти первый»).
Для доказательства корректности фиксируйте тройки Хоара: {I ∧ P} T {I} для тела до continue и {I ∧ ¬P ∨ break_cond} → постусловие после цикла.
В типовых заданиях ЕГЭ необходимо:
Трассировать код с ветвлениями внутри циклов (break/continue) и правильно выписывать порядок действий/вывод.
Подсчитывать количество итераций/операций с ранним выходом (включая крайние случаи).
Реализовывать фильтры по нескольким условиям (пропуск строк/чисел с заданными признаками).
Читать файлы до «сторожа» или до конца, корректно прекращая обработку при ошибке формата.
Оптимизировать решения: «ранний выход при первом контрпримере» вместо проверки всей выборки.
Переписывать решения: из «флага + if» в break/continue и обратно, сохраняя инварианты.
break меняет фактическую (не асимптотическую верхнюю) сложность: в среднем сокращает число итераций до позиции первого срабатывания.
continue не меняет число итераций, но сокращает работу внутри итерации (пропуская тяжёлые разделы тела), что важно при накоплении агрегатов.
Вложенные циклы с break могут снизить среднюю сложность с Θ(n·m) до Θ(n·k), где k ≪ m – средняя позиция срабатывания во внутреннем цикле.
Забыли «обслужить» счётчики/итераторы до continue (в ручных схемах while), что ведёт к бесконечным циклам.
Лишний break вместо корректного условия заголовка – теряется ясность инварианта.
Наращивание результата перед проверкой «неподходящих» – логическая ошибка, которую пытались «исправить» continue поздно. Проверка фильтра должна предшествовать модификации агрегата.
Множественные break без симметрии – усложняют доказательство корректности; лучше выделить предикат завершения и использовать одно место выхода.
Забыли закрыть ресурс перед break – теоретически отражается как «утечка ресурса» в модели.
Алгоритмический псевдоязык
maxpos := -1; maxv := -∞
for i in 0..n-1 do
if A[i] < 0 then continue
if A[i] > maxv then
maxv := A[i]; maxpos := i
end
Семейство C/Java
// поиск индекса первого нуля
int pos = -1;
for (int i = 0; i < n; i++) {
if (A[i] != 0) continue;
pos = i;
break;
}
Python (особенность: else у цикла)
for x in data:
if not valid(x):
continue
if is_target(x):
found = True
break
else:
# выполнится только если break не сработал
found = False
Упражнение 1. Трассировка с continue
Условие. Дана программа (псевдокод):
s := 0
for i in 1..10 do
if i mod 3 = 0 then continue
s := s + i
end
print s
Выпишите значения i, на которых выполняется сложение.
Укажите итоговое значение s.
Критерии проверки. Корректный пропуск кратных 3; правильная сумма оставшихся.
Подсказки. Диапазон 1..10 без {3,6,9}.
Упражнение 2. Ранний выход при поиске
Условие. Массив A[0..n-1] содержит целые. Требуется найти индекс первого отрицательного. Если отрицательных нет – вывести -1. Заполните пропуски:
pos := -1
for i in 0..n-1 do
if A[i] < 0 then
______ := i
end
print pos
Критерии проверки. Находится первое
вхождение; цикл корректно завершён.
Подсказки. На место пропусков – присваивание pos := i и break.
Упражнение 3. Двухуровневая проверка с «двойным разрывом»
Условие. Даны два массива A[0..n-1] и B[0..m-1]. Определите, существует ли пара (i, j), такая что A[i] * B[j] = 0. Оптимизируйте среднюю сложность.
Требуется. Написать псевдокод с двумя for и использованием break так, чтобы при обнаружении нулевой пары выполнение останавливалось максимально рано.
Критерии проверки. Корректная логика двух вложенных циклов, флаг found, «двойной разрыв».
Подсказки. Внутри – if A[i]*B[j]==0 then found:=true; break; снаружи – if found then break.
Упражнение 4. Фильтрация входного потока
Условие. Входной поток содержит целые числа, завершающиеся «сторожом» 999999. Требуется посчитать сумму только положительных чётных, игнорируя все остальные, и остановиться при встрече сторожа. Напишите псевдокод с continue и break.
Критерии проверки. Чёткая проверка сторожа до использования значения; корректный пропуск «лишних» элементов; отсутствие логических гонок.
Подсказки. Сначала проверка на сторожа → break; затем фильтр (x <= 0 or x mod 2 != 0) → continue.
Упражнение 5. Подсчёт операций при раннем выходе
Условие. Рассмотрим:
cnt := 0
for i in 1..n do
cnt := cnt + 1
if i*i >= n then break
end
Выразите итоговое значение cnt через n.
Дайте асимптотику по n.
Критерии проверки. Осознание, что break срабатывает при i ≥ ⌈√n⌉; значит, cnt = ⌈√n⌉. Асимптотика – Θ(√n).
Подсказки. Подумайте о наименьшем i, где i^2 ≥ n.
break и continue – не просто «удобные прыжки», а строго определённые средства управления потоком исполнения, позволяющие компактно выражать раннее завершение и фильтрацию итераций. Корректное применение всегда опирается на инвариант цикла, явные предикаты и оценку сложности. В задачах ЕГЭ это даёт конкурентное преимущество: программы становятся короче, понятнее, быстрее в среднем случае; легче проводится трассировка и подсчёт операций. Освоив предложенные правила и отработав пять упражнений, выпускник уверенно решает классы задач «найти первое», «проверить существование/для всех», «фильтровать поток», «обработать до сторожа», показывая зрелую алгоритмическую культуру и аккуратность рассуждений.