2014-10-05 5 views
0

Предположим, вам предоставлена ​​функция слияния, которая объединит (найдет объединение) два списка L1 и L2 размера s1 и s2 в O (s1 + s2). Каков оптимальный способ слияния k-списков размером s1, s2, ..., sk?Каков оптимальный способ слияния списков k?

Я думаю, что мы должны сначала отсортировать s1, ..., sk и отсортировать первые два списка, которые соответствуют самым низким двум размерам. Когда они объединены, мы находим положение их размера в списке отсортированных размеров и продолжаем процесс до тех пор, пока не получим один список.

У меня возникли проблемы с двумя вещами: 1. действительно ли это оптимально (есть ли другой метод, который вернется быстрее)? 2. как мы анализируем время работы, когда размер списка изменяется при слиянии?

ответ

1

Это точно та же проблема, как найти оптимальную переменной длины битового кодирования для строки, образованной из алфавита k символов с известными частотами s1, s2, … sk. Ваш алгоритм - это точно Huffman algorithm, и вы найдете доказательство оптимальности в любом учебнике по алгоритмам (и многих онлайновых ресурсах), потому что это классический случай жадного алгоритма с простым доказательством корректности.

Повторное применение двухстороннего слияния индуцирует двоичное дерево, в котором каждый узел является слиянием. Учитывая это дерево, вклад любого листа в общую стоимость общего слияния - это вес этого листа, умноженный на его глубину в дереве. (Каждый узел является слиянием, а значения в листе участвуют точно в слияниях по пути от листа к корню, число таких слияний - это глубина листа в дереве.) Аналогично - или тождественно - -, общая длина битовой строки, кодированной Хаффманом, является суммой продуктов веса (частоты) символа с глубиной листа, соответствующей этому символу в дереве конструкции.

Небольшое усовершенствование вашего алгоритма (который часто пропускают люди, пишущие строители дерева Хаффмана): необходимо отсортировать весы s1, s2, … sk, но это единственный вид, который вам нужен. Оттуда алгоритм всегда выбирает два нижних узла и добавляет их. Полученные суммы должны быть монотонно неубывающими по размеру (если сумма меньше предыдущей суммы, предыдущая сумма не могла быть суммой двух наименьших элементов). Таким образом, вы можете поместить суммы в очередь; на каждом шаге вы выбираете два наименьших элемента из отсортированного массива листьев или (неявно) отсортированную очередь узлов.

Это может быть оптимизировано далее, переписывая массив листьев в очередь узлов. (Затем очередь растет со дна массива вверху, довольно просто доказать, что верхняя часть очереди никогда не догонит нижнюю часть массива.)

+0

Отличный ответ! Спасибо. Не могли бы вы просто рассказать о том, почему нам нужно только разобраться в весах? Предположим, что отсортированный список весов равен s1, s2, ..., sk. Затем алгоритм будет объединять списки, соответствующие s1 и s2, для создания s12, а отсортированный список теперь будет выглядеть как s12, s3, ..., sk. Но s12 + s3 может быть больше s3 + s4. –

+0

Или это: если наши отсортированные размеры равны s1, s2, ..., sk, соответствующие спискам L1, L2, ... Lk, тогда мы сначала объединяем L1 и L2 в L12, затем L3 и L4 в L34, чтобы получить L12 , L34, ..., Lk-1Lk и просто продолжить эту работу до тех пор, пока нам не останется один список? Если да, что нам делать, когда количество списков нечетное? Например, если мы имеем L1, L2, L3, L4, L5, то итерации выглядят так: L12, L34, L5 -> L1234, L5 -> L12345? –

+0

@BobJonas: Есть два списка: список листьев (который постоянно уменьшается) и список соединений (которые растут). Первоначально соединения пусты. Начнем с s1, s2, s3, s4; -. После первого шага мы имеем '(s1, s2), s3, s4, ...; s12'. (Удаленные элементы в круглых скобках.) Если 's3' и' s4' являются наименьшими ('s12> s4'), тогда мы имеем' (s1, s2, s3, s4), s5, s6, ...; s12 , s34'. В противном случае 's3' и' s12' являются двумя наименьшими, и мы будем иметь '(s1, s2, s3), s4, s5, ...; (s12), s123'.Мы также должны рассмотреть три элемента, чтобы выбрать наименьшие два: самый маленький из каждого списка и ... – rici

Смежные вопросы