C++ 两堆合并算法

C++ 两堆合并算法,c++,data-structures,binomial-heap,C++,Data Structures,Binomial Heap,据我所知,存在一个二项式堆或所谓的可合并堆,用于合并两个堆。我的问题是,如果我将这两个堆复制到一个大数组中,然后执行堆构建过程,而不是动态地将它们合并到一个堆中,那么这是一个好方法还是一个坏方法 因为我不知道如何使用两个堆来创建一个堆,而只使用堆操作。如果这不是一个好方法,请告诉我,或者如果可以,请给我一些链接,其中实现了带有合并操作的二项式堆。如果您仔细想想,通过丢弃其他堆的顺序中嵌入的所有信息来创建一个堆不可能是最优的。最糟糕的情况是,您应该将堆2中的所有项添加到堆1中,而这仅仅是从头创建一

据我所知,存在一个二项式堆或所谓的可合并堆,用于合并两个堆。我的问题是,如果我将这两个堆复制到一个大数组中,然后执行堆构建过程,而不是动态地将它们合并到一个堆中,那么这是一个好方法还是一个坏方法


因为我不知道如何使用两个堆来创建一个堆,而只使用堆操作。如果这不是一个好方法,请告诉我,或者如果可以,请给我一些链接,其中实现了带有合并操作的二项式堆。

如果您仔细想想,通过丢弃其他堆的顺序中嵌入的所有信息来创建一个堆不可能是最优的。最糟糕的情况是,您应该将堆2中的所有项添加到堆1中,而这仅仅是从头创建一个全新堆的一半工作量


但事实上,你们可以做得更好。合并两个格式良好的堆只需要在另一个堆的树中找到一个根的插入点并将其插入该点即可。不需要进一步的工作,您只做了
ln
工作!有关详细的算法,请参阅。

它将解决问题,并为您提供正确的堆-但效率不高


从头开始创建
n
元素的[二进制]堆是
O(n)
,而现有的两个二项式堆是
O(logn)
合并两个二项式堆的过程与合并排序中的合并操作非常相似。如果不知道合并堆过程是问题所在,那么以下步骤可能会有所帮助

重复步骤1到4,直到其中一个堆为空

  • 如果两个堆的头(二叉树)具有相同的阶数,则可以将具有较大键的堆头指定为具有较小键的堆头的子级。因此,后一堆的头的阶数将增加1,并使前一堆的头成为其当前头的下一个元素,然后转到步骤2。否则,如果它们的阶数不同,则转到步骤4

  • 如果步骤1中后一堆中的头和下一棵二叉树的阶数相同,则转至步骤3,否则转至步骤1

  • 以与步骤1相同的方式组合堆头和堆中的下一个元素,并将新的组合二叉树指定为堆头,然后转到步骤2

  • 查看2个堆中哪一个具有较低度数的堆头。将此堆的头指定为其他堆的头,并将其从最初存在的堆中删除


  • Brodal队列和Brodal Okasaki队列(自举斜二项堆)给出了可合并堆的最佳最坏情况渐近界,支持O(1)insert、merge和findMin,以及O(log n)deleteMin。Brodal队列是短暂的,并且支持高效的删除和减少密钥。Brodal Okasaki队列是合流持久性的(实际上纯粹是功能性的),但不支持delete或decreaseKey。不幸的是,Brodal和Okasaki说这两种实现在实践中都是低效的,Brodal认为他的队列太复杂,在任何情况下都不实用


    斐波那契堆给出了类似的摊销(但不是最坏情况)界限,在摊销环境中可能更有效、更实用。配对堆是另一个不错的选择:根据Wikipedia的说法,它们的确切界限未知,但它们在实践中表现得非常好。

    是的,但因为我从未编写过将两个堆合并在一起的程序,所以实现它对我来说是个问题Wikipedia页面上有非常清晰的伪代码——试试看!伪代码是清楚的,但是我如何将它翻译成C++?我很清楚地理解了它的伪代码,很显然,没有人可以为你编写实际代码,因为我们没有你的堆实现来查看。我可以使用标准的程序创建两个堆,你能帮助我合并吗?除非你需要复制数据(例如,因为你使用数组存储)。,此时您不能进行低于
    O(n)
    的操作(只有较少的比较)。