Алгоритм слияния двух максимальных куч?

Есть ли эффективный алгоритм для слияния 2 max-heaps, которые хранятся в виде массивов?

Ответ 1

Это зависит от типа кучи.

Если это стандартная куча, в которой каждый node имеет до двух дочерних элементов и которая заполняется тем, что листья находятся на максимум двух разных строках, вы не можете стать лучше, чем O (n) для слияния.

Просто поместите два массива вместе и создайте из них новую кучу, которая берет O (n).

Для лучшей производительности слияния вы можете использовать другой вариант кучи, такой как Fibonacci-Heap, который может объединиться в O (1), амортизированном.

Update: Обратите внимание: хуже всего вставлять все элементы первой кучи один за другим во вторую кучу или наоборот, так как вставка принимает O (log (n)). Как указано в вашем комментарии, вы, похоже, не знаете, как куча оптимально построена в начале (опять же для стандартной двоичной кучи)

  • Создайте массив и поместите элементы обеих куч в произвольном порядке
  • теперь начинаются с самого низкого уровня. Самый низкий уровень содержит тривиальные максимальные кучи размера 1, поэтому этот уровень выполнен.
  • переместите уровень вверх. Когда состояние кучи одной из "субапов" нарушается, замените корень "кучи" на него большим ребенком. Затем выполняется уровень 2.
  • перейдите на уровень 3. Когда состояние кучи будет нарушено, обработайте, как и раньше. Поменяйте его на более крупный ребенок и обработайте рекурсивно, пока все не достигнет уровня 3
  • ...
  • когда вы достигнете вершины, вы создали новую кучу в O (n).

Я опускаю здесь доказательство, но вы можете это объяснить, так как вы сделали большую часть кучи на нижних уровнях, где вам не пришлось менять большое количество контента, чтобы восстановить состояние кучи. Вы работали на гораздо меньших "кучах", которые намного лучше, чем вы делали бы, если бы вы вставляли каждый элемент в одну из кучек = > , тогда вы будете запускать каждый раз всю кучу, которая принимает O (n) каждый раз.

Обновление 2: Двучленная куча позволяет слить в O (log (n)) и будет соответствовать вашему требованию O (log (n) ^ 2).

Ответ 3

Я думаю, что в этом случае вы ищете биномиальную кучу.

Двучленная куча представляет собой набор биномиальных деревьев, являющийся членом семейства кучи слияния. В худшем случае для объединения (слияния) в 2+ биномиальных кучах с n суммарными элементами в кучах O (lg n).

Подробнее см. http://en.wikipedia.org/wiki/Binomial_heap.