Commit 48aa4c31 authored by WAAutoMaton's avatar WAAutoMaton
Browse files

fix: 排版

parent 01017346
Loading
Loading
Loading
Loading
+13 −13
Original line number Diff line number Diff line
@@ -61,11 +61,11 @@ Node* merge(Node* a,Node* b)

  到这里我们会发现,前面的几个操作都十分偷懒,几乎完全没有对数据结构进行维护,所以删除最小值是配对堆最重要的(也是最复杂)的一个操作。  
  考虑我们拿掉根节点之后会发生什么,根节点原来的所有儿子构成了一片森林,所以我们要把他们合并起来。  
  一个很自然的想法是使用merge函数把儿子们一个一个并在一起,这样做的话正确性是显然的,但是会导致复杂度退化到$ O(n)$。为了保证删除操作的均摊复杂度为$ O(\log n)$,我们需要:把儿子们两两配成一对,先用merge操作把被配成同一对的2个儿子合并到一起(见下图1),再按上述方法将新产生的堆暴力合并在一起(见下图2)。
  一个很自然的想法是使用 ``merge`` 函数把儿子们一个一个并在一起,这样做的话正确性是显然的,但是会导致复杂度退化到 $O(n)$。为了保证删除操作的均摊复杂度为 $O(\log n)$,我们需要:把儿子们两两配成一对,先用 ``merge`` 操作把被配成同一对的个儿子合并到一起(见下图1),再按上述方法将新产生的堆暴力合并在一起(见下图2)。
![](./images/pairingheap4.jpg)
![](./images/pairingheap5.jpg)	

  先实现一个辅助函数~~(实际上是主要函数)~~``merges``,作用是合并一个节点的所有兄弟。  
  先实现一个辅助函数``merges``,作用是合并一个节点的所有兄弟。  

##### 递归版本的 merges(推荐)

@@ -132,7 +132,7 @@ struct Node

```

  merge操作修改为:
  ``merge`` 操作修改为:

```cpp
Node* merge(Node* a,Node* b)
@@ -148,7 +148,7 @@ Node* merge(Node* a,Node* b)
}
```

  merges操作修改为:
  ``merges`` 操作修改为:

```cpp
Node* merges(Node* x) 
@@ -162,9 +162,9 @@ Node* merges(Node* x)
}
```

  现在我们来考虑如何实现decrease-key操作。
  首先我们发现,当我们对节点x进行dec-key操作后,以x为根的子树仍然满足配对堆性质,但x的父亲和x之间可能不再满足堆性质。
  因此我们可以把整棵以x为根的子树剖出来,这样现在两棵树都符合配对堆性质了,再把他们merge起来就做完了。
  现在我们来考虑如何实现 ``decrease-key`` 操作。  
  首先我们发现,当我们对节点x进行 ``decrease-key`` 操作后,以 $x$ 为根的子树仍然满足配对堆性质,但 $x$的父亲和 $x$ 之间可能不再满足堆性质。  
  因此我们可以把整棵以 $x$ 为根的子树剖出来,这样现在两棵树都符合配对堆性质了,再把他们 ``merge`` 起来就做完了。  
  这个操作本身复杂度显然为 $O(1)$,但会破坏原有的势能分析过程,因此均摊复杂度难以证明(目前学术界还无法给出复杂度的精确值),通常可以简单的认为复杂度为 $o(\log n)$(注意这里为小o)。

```cpp