Алгоритм Гарсиа–Вакса — эффективный метод для компьютеров, позволяющий строить оптимальные двоичные деревья поиска и алфавитные коды Хаффмана за линейное время. Он назван в честь Адриано Гарсиа и Мишель Л. Вакс .
Входные данные для задачи, для целого числа , состоят из последовательности неотрицательных весов . Выходные данные представляют собой корневое бинарное дерево с внутренними узлами, каждый из которых имеет ровно два потомка. Такое дерево имеет ровно листовых узлов, которые могут быть идентифицированы (в порядке, заданном бинарным деревом) с входными весами. Цель задачи состоит в том, чтобы найти дерево среди всех возможных деревьев с внутренними узлами, которое минимизирует взвешенную сумму длин внешних путей . Эти длины путей представляют собой количество шагов от корня до каждого листа. Они умножаются на вес листа, а затем суммируются, чтобы получить качество всего дерева. [1]
Эту задачу можно интерпретировать как задачу построения бинарного дерева поиска для упорядоченных ключей, предполагая, что дерево будет использоваться только для поиска значений, которых еще нет в дереве. В этом случае ключи разбивают пространство значений поиска на интервалы, и вес одного из этих интервалов можно принять за вероятность поиска значения, которое попадает в этот интервал. Взвешенная сумма длин внешних путей контролирует ожидаемое время поиска по дереву. [1]
В качестве альтернативы, вывод задачи может быть использован как код Хаффмана , метод для однозначного кодирования заданных значений с использованием последовательностей двоичных значений переменной длины . В этой интерпретации код для значения задается последовательностью левых и правых шагов от родителя к потомку на пути от корня к листу в дереве (например, с 0 для левого и 1 для правого). В отличие от стандартных кодов Хаффмана, те, которые построены таким образом, являются алфавитными , что означает, что отсортированный порядок этих двоичных кодов совпадает с входным порядком значений. Если вес значения - это его частота в сообщении, которое должно быть закодировано, то вывод алгоритма Гарсии-Вакса - это алфавитный код Хаффмана, который сжимает сообщение до максимально возможной длины. [1]
В целом алгоритм состоит из трех фаз: [1]
Первую фазу алгоритма легче описать, если входные данные дополнены двумя контрольными значениями ( или любым достаточно большим конечным значением) в начале и конце последовательности. [2]
Первая фаза поддерживает лес деревьев, изначально одноузловое дерево для каждого не-сторожевого входного веса, которое в конечном итоге станет бинарным деревом, которое оно строит. Каждое дерево связано со значением, сумма весов его листьев создает узел дерева для каждого не-сторожевого входного веса. Алгоритм поддерживает последовательность этих значений с двумя сторожевыми значениями на каждом конце. Начальная последовательность — это просто порядок, в котором веса листьев были заданы в качестве входных данных. Затем он многократно выполняет следующие шаги, каждый из которых уменьшает длину входной последовательности, пока не останется только одно дерево, содержащее все листья: [1]
Для эффективной реализации этой фазы алгоритм может поддерживать свою текущую последовательность значений в любой самобалансирующейся структуре двоичного дерева поиска. Такая структура позволяет удалять и и повторно вставлять их нового родителя за логарифмическое время. На каждом шаге веса до в четных позициях массива образуют убывающую последовательность, а веса в нечетных позициях образуют другую убывающую последовательность. Таким образом, позиция для повторной вставки может быть найдена за логарифмическое время с помощью сбалансированного дерева для выполнения двух двоичных поисков , по одному для каждой из этих двух убывающих последовательностей. Поиск первой позиции для которой может быть выполнен за линейное общее время с помощью последовательного поиска , который начинается с из предыдущей тройки. [1]
Нетривиально доказать, что на третьем этапе алгоритма существует другое дерево с теми же расстояниями, и что это дерево обеспечивает оптимальное решение задачи. Но если предположить, что это правда, то второй и третий этапы алгоритма легко реализовать за линейное время. Таким образом, общее время алгоритма на входе длины составляет .
Алгоритм Гарсии–Вакса назван в честь Адриано Гарсии и Мишель Л. Вакс , опубликовавших его в 1977 году. [1] [3] Их алгоритм упростил более ранний метод TC Hu и Алана Таккера , [1] [4] и (хотя он отличается во внутренних деталях) в конечном итоге делает те же сравнения в том же порядке, что и алгоритм Ху–Таккера. [5] Первоначальное доказательство корректности алгоритма Гарсии–Вакса было сложным и позднее было упрощено Кингстоном (1988) [1] [2] и Карпински, Лармором и Риттером (1997). [6]