# Разделяй и властвуй Разделяй и властвуй (divide and conquer) -- это важная и распространенная стратегия в алгоритмах. Обычно она реализуется с помощью рекурсии и включает два этапа: разделение и объединение. 1. **Разделение (этап разбиения)**: рекурсивное разбиение исходной задачи на две или более подзадачи до тех пор, пока не будет достигнута наименьшая подзадача. 2. **Объединение (этап слияния)**: начиная с решения наименьших подзадач, снизу вверх объединяются решения всех других подзадач, чтобы построить решение исходной задачи. Сортировка слиянием является типичным примером применения стратегии «разделяй и властвуй» (см. рис. 12.1). 1. **Разделение**: рекурсивное разбиение исходного массива (исходной задачи) на два подмассива (подзадачи) до тех пор, пока в подмассивах не останется по одному элементу (наименьшая подзадача). 2. **Объединение**: снизу вверх объединяются упорядоченные подмассивы (решения подзадач), чтобы получить упорядоченный исходный массив (решение исходной задачи). ![Стратегия «разделяй и властвуй» в сортировке слиянием](../assets/media/image719.jpeg) ## Определение задачи для метода «разделяй и властвуй» Чтобы определить, подходит ли задача для решения методом «разделяй и властвуй», можно использовать следующие критерии: 1. **Задачу можно разбить**: исходную задачу можно разбить на более мелкие, аналогичные подзадачи, которые можно рекурсивно разделить аналогичным образом. 2. **Подзадачи независимы**: подзадачи не пересекаются, не зависят друг от друга и могут быть решены независимо. 3. **Решения подзадач можно объединить**: решение исходной задачи получается путем объединения решений подзадач. Очевидно, что сортировка слиянием соответствует этим трем критериям. 1. **Задачу можно разбить**: рекурсивное разбиение массива (исходной задачи) на два подмассива (подзадачи). 2. **Подзадачи независимы**: каждый подмассив можно отсортировать независимо (подзадачи можно решить независимо). 3. **Решения подзадач можно объединить**: два упорядоченных подмассива (решения подзадач) можно объединить в один упорядоченный массив (решение исходной задачи). ## Повышение эффективности с помощью стратегии «разделяй и властвуй» **Стратегия «разделяй и властвуй» позволяет не только эффективно решать алгоритмические задачи, но и повышать эффективность алгоритмов**. Алгоритмы быстрой сортировки, сортировки слиянием и пирамидальной сортировки быстрее, чем сортировка выбором, пузырьком и вставками, именно благодаря применению стратегии «разделяй и властвуй». Возникает вопрос: **почему метод «разделяй и властвуй» повышает эффективность алгоритма, в чем его основная логика**? Иными словами, почему разбиение большой задачи на несколько подзадач, решение этих подзадач и объединение их решений в решение исходной задачи оказывается более эффективным, чем непосредственное решение исходной задачи? Этот вопрос можно обсудить с точки зрения количества операций и параллельных вычислений. ### Оптимизация количества операций Возьмем, к примеру, сортировку пузырьком, которая требует времени $O(n^2)$ для обработки массива длиной $n$. Предположим, что мы разделили массив на два подмассива, как показано на рис. 12.2. Тогда разбиение потребует времени $O(n)$, сортировка каждого подмассива -- $O((n/2)^2)$, а объединение двух подмассивов -- $O(n)$. Общая временная составит: $$ O(n + (\frac{n}{2})^2 \times 2 + n) = O(\frac{n^2}{2} + 2n) $$ ![Сортировка пузырьком до и после разбиения массива](../assets/media/image721.jpeg) Далее, решим следующее неравенство, в котором левая и правая части представляют общее количество операций до и после разбиения соответственно: $$ \begin{aligned} n^2 & > \frac{n^2}{2} + 2n \\ n^2 - \frac{n^2}{2} - 2n & > 0 \\ n(n - 4) & > 0 \end{aligned} $$ **Это означает, что при $n > 4$ количество операций после разбиения меньше, и эффективность сортировки должна быть выше**. Обратите внимание, что временная сложность после разбиения остается квадратичной $O(n^2)$, но постоянный коэффициент в сложности уменьшается. **Если продолжить разбиение подмассивов пополам, пока в них не останется по одному элементу**, то получится сортировка слиянием, временная сложность которой составляет $O(n \log n)$. А что, **если мы установим несколько дополнительных точек разделения** и равномерно разделим исходный массив на $k$ подмассивов? Эта ситуация очень похожа на блочную сортировку, которая хорошо подходит для сортировки очень больших объемов данных, и теоретически ее временная сложность может достигать $O(n + k)$. ### Оптимизация параллельных вычислений Известно, что подзадачи, созданные методом «разделяй и властвуй», независимы друг от друга, **поэтому их обычно можно решать параллельно**. Таким образом, этот метод не только снижает временную сложность алгоритма, **но и способствует параллельной оптимизации операционной системы**. Параллельная оптимизация особенно эффективна в многоядерной или многопроцессорной среде, поскольку система может одновременно обрабатывать несколько подзадач, более полно используя вычислительные ресурсы, что значительно сокращает общее время выполнения. Например, в блочной сортировке, изображенной на рис. 12.3, огромный объем данных равномерно распределяется по блокам. Задачи сортировки всех блоков можно распределить по вычислительным единицам, а затем объединить результаты. ![Параллельные вычисления в блочной сортировке](../assets/media/image723.jpeg) ## Типичные сценарии применения стратегии «разделяй и властвуй» С одной стороны, стратегию «разделяй и властвуй» можно использовать для решения многих классических алгоритмических задач. - **Поиск ближайшей пары точек**: этот алгоритм сначала делит множество точек на две части, затем находит ближайшую пару точек в каждой части, а затем находит ближайшую пару точек, охватывающую обе части. - **Умножение больших чисел**: например, алгоритм Карацубы, который разлагает умножение больших чисел на несколько операций умножения и сложения меньших чисел. - **Умножение матриц**: например, алгоритм Штрассена, который разлагает умножение больших матриц на несколько операций умножения и сложения матриц меньшего размера. - **Задача о Ханойских башнях**: эту задачу можно решить с помощью рекурсии, что является типичным применением стратегии «разделяй и властвуй». - **Задача о количестве инверсий**: если в последовательности предыдущее число больше последующего, то эти два числа образуют инверсию. Задачу о количестве инверсий можно решить с помощью подхода «разделяй и властвуй» и сортировки слиянием. С другой стороны, стратегия «разделяй и властвуй» широко применяется в разработке алгоритмов и структур данных. - **Двоичный поиск**: такой поиск делит отсортированный массив на две части по индексу среднего элемента. Затем, в зависимости от результата сравнения целевого значения со средним элементом, решает, какую половину исключить, и выполняет ту же операцию на оставшейся части. - **Сортировка слиянием**: уже была рассмотрена в начале этого раздела, не будем еще раз повторяться. - **Быстрая сортировка**: эта сортировка выбирает опорное значение, затем делит массив на два подмассива, элементы одного из которых меньше опорного значения, а элементы другого -- больше. Затем выполняет ту же операцию с обеими частями, пока в подмассиве не останется один элемент. - **Блочная сортировка**: основная идея этой сортировки заключается в распределении данных по нескольким блокам и сортировке элементов в каждом из них. Затем происходит последовательное извлечение элементов из каждого блока для построения отсортированного массива. - **Деревья**: например, двоичные деревья поиска, АВЛ-дерево, красно-черное дерево, B-дерево, дерево B+ и т. д. Операции поиска, вставки и удаления в них можно рассматривать как применение стратегии «разделяй и властвуй». - **Кучи**: куча -- это особый вид полного двоичного дерева, и такие операции, как вставка, удаление и упорядочивание, фактически подразумевают использование метода «разделяй и властвуй». - **Хеш-таблицы**: хотя хеш-таблицы напрямую не применяют подход «разделяй и властвуй», некоторые решения для разрешения коллизий в хешировании косвенно используют эту стратегию. Например, длинные цепочки в методе цепной адресации преобразуются в красно-черные деревья для повышения эффективности поиска. Можно сказать, **что стратегия «разделяй и властвуй» -- это своего рода «скрытая» алгоритмическая идея**, присутствующая в различных алгоритмах и структурах данных.