Когда N=2
, вы объединяете два списка, итеративно выдвигая переднюю часть списка, который является наименьшим.Таким образом, вы создаете виртуальный список, который поддерживает операцию pop_front
, реализованную как:
pop_front(a, b): return if front(a) <= front(b) then pop_front(a) else pop_front(b)
. Вы можете очень хорошо организовать древовидную схему слияния, в которой такие виртуальные списки объединяются в пары:
pop_front(a, b, c, d): return if front(a, b) <= front(c, d) then pop_front(a, b) else pop_front(c, d)
Каждый поп будет включать каждый уровень в дереве один раз, что приводит к стоимости O(Log k)
за поп.
Приведенные выше рассуждения неверны, поскольку они не учитываютfront
операции, которые включают сравнение между двумя элементами, которые будут каскадно и, в конечном итоге, потребуют всего k-1
сравнений на выходной элемент.
Это можно обойти, "запоминая" передний элемент, т.е. сохраняяэто рядом с двумя списками после сравнения.Затем, когда элемент извлекается, этот передний элемент обновляется.
Это напрямую ведет к двоичному устройству минимальной кучи, как предлагает @ trincot.
5 7 32 21
5
6 4 8 23 40
2
7 7 20 53
2
2 4 6 8 10