Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 为什么配对堆在删除_min时需要特殊的两次传递?_Algorithm_Data Structures_Pairing Heap - Fatal编程技术网

Algorithm 为什么配对堆在删除_min时需要特殊的两次传递?

Algorithm 为什么配对堆在删除_min时需要特殊的两次传递?,algorithm,data-structures,pairing-heap,Algorithm,Data Structures,Pairing Heap,我正在看报纸 这很简单,唯一棘手的部分是delete\u min操作 唯一非平凡的基本操作是删除 堆中的最小元素。标准策略首先合并 成对的子标题(这是赋予此数据结构 名称),然后合并生成的堆列表 从右到左: 我不认为我需要在这里复制/粘贴代码,因为它位于wiki链接中 我的问题是 他们为什么要进行两次合并 为什么他们第一次合并配对?不直接将它们全部合并 为什么在合并对之后,要从右向左合并 对于配对堆,将项添加到堆是一个O(1)操作,因为它所做的只是将节点添加为新根(如果它小于当前根),或者作为当

我正在看报纸

这很简单,唯一棘手的部分是
delete\u min
操作

唯一非平凡的基本操作是删除 堆中的最小元素。标准策略首先合并 成对的子标题(这是赋予此数据结构 名称),然后合并生成的堆列表 从右到左:

我不认为我需要在这里复制/粘贴代码,因为它位于wiki链接中

我的问题是

  • 他们为什么要进行两次合并

  • 为什么他们第一次合并配对?不直接将它们全部合并

  • 为什么在合并对之后,要从右向左合并


  • 对于配对堆,将项添加到堆是一个O(1)操作,因为它所做的只是将节点添加为新根(如果它小于当前根),或者作为当前根的第一个子节点。因此,如果您创建了一个配对堆,并将数字0到9依次添加到该堆中,您将得到:

            0
            |
    -----------------
    | | | | | | | | |
    9 8 7 6 5 4 3 2 1
    
    如果然后执行delete min,则必须查看每个子项以确定最小项并构建新堆。如果使用从左到右的朴素组合方法,则会得到以下树:

           1
           |
    ---------------
    | | | | | | | |
    9 8 7 6 5 4 3 2
    
    下次执行delete min时,您必须查看剩余的8个子项等。使用此技术,创建并从堆中删除所有项将是一个O(n^2)操作

    成对组合的两次传递方法,然后组合成对的结果是更有效的结构。考虑第一种情况。删除最小项后,我们剩下9个孩子。它们从左到右成对组合,产生:

      8  6  4  2  1
     /  /  /  /
    9  7  5  3
    
    然后我们从右到左组合这些对。分步骤:

      8  6  4    1
     /  /  /    /
    9  7  5    2
              /
             3
    
      8  6    1
     /  /    / \
    9  7    2   4
           /   / 
          3   5  
    
      8     1
     /      |
    9   ---------
        6   4   2
       /   /   /
      7   5   3
    
          1
          |
      ----------
      8  6  4  2
     /  /  /  /
    9  7  5  3
    
    现在,下一次调用delete min时,只有四个节点需要检查,下一次之后将只有两个节点需要检查。使用两次组合方法可将子级的节点数减少至少一半。我的安排是最糟糕的。如果项目按升序排列,则第一个delete min操作将生成一个在根下只有两个子节点的树

    这是配对堆的摊销复杂性的一个特别好的例子。insert是O(1),但是一系列insert操作之后的第一个delete min是O(n),其中
    n
    是自上次delete-min以来插入的项目数。两次组合规则的优点在于它可以快速重新组织堆以降低O(n)的复杂性


    根据该组合规则,delete min的摊销复杂度为O(logn)。根据严格的从左到右规则,它是O(n)。

    原稿对此进行了很好的解释。为什么第二阶段是从右到左很重要?在我看来,它完全等同于从左到右的插入顺序,无论方向如何,插入顺序都可以生成相同的树结构。在您的示例中,这将产生一个基本上向左不平衡的二叉树。@Celelibi:最有可能的是,相反的顺序是组合过程递归性质的结果。提到了从左到右进行两次传递的可能性,但没有说明性能。如果使用左子级、右同级链表将堆表示为树,则第一次传递时从左到右更容易。如果您使用中间列表或队列来保存第一次传递的结果,那么第二次传递可以按任意顺序进行,但我猜从右到左可以消除结果树中的偏差,并使结果趋于均匀。@Paulchenchronch:经过一点试验,在第二次传球时,我看不到左-左与左-右在表现上有任何差异。我敢肯定,在最初的论文中描述的左右是他们对问题的递归定义的产物。基本上,它们只是在展开堆栈的同时进行合并。我转向了迭代实现,因为当您有一个大堆时,递归实现会破坏堆栈。正如你所说,左孩子右兄弟姐妹表示法使两个从左到右的过程更可取。构建一个表现出类似最坏情况行为的树不是很容易吗?还是我错过了第一关的重要内容?