结构之美——优先队列基本结构(四)——二叉堆、d堆、左式堆、斜堆

实现优先队列结构主要是经过堆完成,主要有:二叉堆、d堆、左式堆、斜堆、二项堆斐波那契堆pairing 堆等。php

 

1. 二叉堆 

1.1. 定义

彻底二叉树,根最小。数据结构

存储时使用层序。svg

 

1.2. 操做

(1). insert(上滤)

插入末尾 26,不断向上比较,大于26则交换位置,小于则中止。性能

 

(2). deleteMin(下滤)

提取末尾元素,放在堆顶,不断下滤:spa

 

(3). 其余操做:

都是基于insert(上滤)与deleteMin(下滤)的操做。.net

减少元素:减少节点的值,上滤调整堆。blog

增大元素:增长节点的值,下滤调整堆。排序

删除非顶点节点:直接删除会出问题。方法:减少元素的值到无穷小,上滤后删除。递归

Merge:insert one by one队列

 

2. d叉堆

2.1. 定义

彻底d叉树,根最小。

存储时使用层序。

 

2.2. 操做:

操做跟二叉堆基本一致:insert,deleteMin,增大元素,减少元素,删除非顶元素,merge。

 

2.3 二叉堆与d叉堆的对比:

 

3. 左式堆

3.1. 定义

零路径长度:到没有两个儿子的节点最短距离
左式堆:
1.一棵二叉树
2.零路径长:左儿子≧右儿子,父节点= min{儿子} +1(这条性质致使了左式堆的严重左偏)
 
零路径长度:
 
 

 

3.2. 操做:

(1) merge :

原则:根值大的堆与根值小的堆的右子堆合并(根值:根位置的元素值,并不是零路径长度)
 
 
具体分三种状况(设堆H1的根值小于H2)
H1只有一个节点
H1根无右孩子
H1根有右孩子
 
(1.1).H1只有一个节点,若出现不知足:零路径长:左儿子≧右儿子,交换左右孩子。
 
(1.2).H1根无右孩子,若出现不知足:零路径长:左儿子≧右儿子,交换左右孩子。
 

 

(1.3).H1根有右孩子

1.初始状态,H1的根6,H2的根为8,将H2合并到H1。

2.将H1构形成根无右孩子的形式:

3.将元素10, merge到H2,要首先将H2构形成根无右孩子的形式,递归,merge,若出现不知足:零路径长:左儿子≧右儿子,交换左右孩子……

——》——》——》

4.

5.

3.3. 性质分析:

insert:merge
deleteMin:delete root,merge
时间复杂度:merge与右路径长度之和成正比;最坏O(logN)
缺点:交换需判断;维护零路径长

 

4. 斜堆

 

4.1. 定义

二叉树,根最小。因而可知:
 
 
 
特色:merge无条件交换。
 
时间复杂度:最坏O(N);最好Ω(1);平均O(logN)

 

4.2性能比较:

定義

  • 僅有一個節點的樹為斜堆;
  • 兩個斜堆合併的結果仍為斜堆。

合併操做

斜堆合併操做的遞歸合併過程和左偏樹彻底一樣。假設我們要合併 A 和 B兩個斜堆,且 A 的根節點比 B 的根節點小,我們只须要把 A 的根節點做為合併後新斜堆的根節點,並將 A 的右子樹與 B 合併。由於合併都是沿著最右路徑進行的,經過合併之後,新斜堆的最右路徑長度必然增长,這會影響下一次合併的效率。因此合併後,通過交換左右子樹,使整棵樹的最右路徑長度很是小(這是啟發規則)。然而斜堆不記錄節點的距離,在操做時,從下往上,沿著合併的路徑,在每個節點處都交換左右子樹。通過不斷交換左右子樹,斜堆把最右路徑甩向左邊了。

遞歸實現合併

  • 比較兩個堆; 設p是具备更小的root的鍵值的堆,q是另外一個堆,r是合併後的結果堆。
  • 令r的root是p(具备最小root鍵值),r的右子樹為p的左子樹。
  • 令r的左子樹為p的右子樹與q合併的結果。

舉例。合併前: SkewHeapMerge1.svg


合併後 SkewHeapMerge7.svg

非遞歸合併實現

  • 把每個堆的每棵(遞歸意義下)最右子樹切下來。這使得获得的每棵樹的右子樹均為空。
  • 按root的鍵值的升序排列這些樹。
  • 迭代合併具备最大root鍵值的兩棵樹:
    • 具备次大root鍵值的樹的右子樹一定為空。把其左子樹與右子樹交換。現在該樹的左子樹為空。
    • 具备最大root鍵值的樹做為具备次大root鍵值樹的左子樹。

舉例: SkewHeapMerge1.svg

SkewHeapMerge2.svg

SkewHeapMerge3.svg

SkewHeapMerge4.svg

SkewHeapMerge5.svg

SkewHeapMerge6.svg

SkewHeapMerge7.svg

5. 总结

 

若是是不支持所谓的合并操做union的话,普通的堆数据结构就是一种很理想的数据结构(堆排序)。 可是若是想要支持集合上的合并操做的话,最好是使用二项堆或者是斐波那契堆,普通的堆在union操做上最差的状况是O(n),可是二项堆和斐波那契堆是O(lgn)。

相关文章
相关标签/搜索