同じ質問をしている可能性のある他の人のために、これまでに見つけたことで自分自身に答えます。
最小/最大ヒープは、基本的に3 つのヒープを 1 つにまとめたもので、リーフ レベルを共有します。
min1 <--- one min heap, first level
/ \
mi2 mi3 <--- third level
/ \ / \
m5 m6 m7 m8 <--- fifth level
/\ /\ /\ /\
a b c d e f g h <--- leaf level (here: sixth level)
\/ \/ \/ \/
x1 x2 x3 x4 <--- fourth level
\ / \ /
max1 max2 <--- two max heaps, second level
(重要な注意: ヒープのファンアウトは 4 であるため、これは正確ではありません! さらに、これは論理的な順序であり、ヒープをレベルごとにインターリーブするメモリ レイアウトではありません) リーフ レベルのオブジェクトはすべてに属します。 3 つのヒープ。これは要素がヒープの最小部分から最大部分に移行する場所です。
これで、最小ヒープと最大ヒープのサイズを計算し、quickselect などの部分的な並べ替えを使用してデータを分割し、3 つの部分を個別に一括読み込みできます。ただし、quickselect は、一括読み込み全体(データ セットの部分的な順序付け)と同じくらいコストがかかります。ヒープの一括読み込みと一括修復 (!) のもう 1 つの明白な方法は、より小さなサブヒープを調べることです。通常の最小ヒープでは、a、b、c の 3 つの要素のアトミック ヒープを見て、a が最小であることを確認します。ここでは、高さ 4、つまり 15 要素のヒープを見ることができます。
min1
/ \
max1 max2
/ \ / \
m1 m2 m3 m4
/\ /\ /\ /\
a b c d e f g h
そして、min1 が最小、max1 と max2 が 2 つの最大値、m1-m4 が次の 4 つの最大値であることを確認し、2 つのレベルのステップでツリーを登ります (つまり、最小レベルのみ)。
または、サイズ 7 (3 レベル) のヒープを見て、最小タイプと最大タイプを識別することができます
min1 max1
/ \ / \
max1 max2 min1 min2
/\ /\ /\ /\
a b c d a b c d
最小レベルには最初のタイプがあり、最大レベルには 2 番目のタイプがあることを確認します。次に、すべてのレベルを通過する必要があります。
しかし、さらに優れた解決策は、interval heapsを使用することです。これも本質的に、インターリーブされた最小ヒープと最大ヒープです。ただし、それらは対称的にインターリーブされ、同じサイズです。それらは実装がはるかに簡単なようで、次のようなヒープとして解釈できます。
min1,max1
/ \
min2,max2 min3,max3
一括読み込みの詳細については、元のインターバル ヒープの出版物を参照してください。
したがって、一括読み込み可能な min-max-heap に興味がある場合は、代わりにインターバル ヒープを検討することを検討してください。とにかく、最小最大ヒープよりも優れていると言う人もいます。それらは密接に関連しており、実装がより簡単になるはずです。特に、min-max-heap のパフォーマンスが向上する明確な理由はありません。詳細な複雑さの分析により、必要な比較とスワップの一定の要因によってパフォーマンスが低下することが示されても、私は驚かないでしょう (私が知る限り、ヒープの正しさを検証するために、min-max-heap ではより多くの比較が必要であることが単純にわかります)。