斐波那契堆的实现和比较(相对二项堆)

Fibonacci Heap(简称F-Heap)是一种基于二项堆的非常灵活的数据结构。它与二项堆不同的地方在于:

1)root list和任何结点的child list使用双向循环链表,而且这些lists中的结点不再有先后次序(Binomial Heap中root list的根结点按degree从小到大顺序,child list的结点按degree从大到小顺序);

2)二项堆中任何一颗Binomial Tree中根结点的degree是最大的,而F-Heap中由于decrease-key操作(cut和cascading cut)的缘故,并不能保证根结点的degree最大;

3)二项堆中任何结点(degree等于k的)为根的子树中,结点总数为2^k;F-Heap中相应的结点总数下界为F{k+2},上界为2^k(如果没有Extract-Min和Delete两类操作的话)。其中F{k+2}表示Fibonacci数列(即0,1,1,2,3,5,8,11...)中第k+2个Fibonacci数,第0个Fibonacci数为0,第1个Fibonacci数为1。注意不像二项堆由二项树组成那样,F-Heap的root list中的每棵树并不是Fibonacci树(Fibonacci树属于AVL树),而F-Heap名称的由来只是因为Fibonacci数是结点个数的一个下界值。

4)基于上面的区别,若F-Heap中结点总数为n,那么其中任何结点(包括非根结点)的degree最大值不超过D(n) = floor(lgn/lg1.618),这里1.618表示黄金分割率(goldren ratio),即方程x^2=x+1的一个解。所以在Extract-Min的consolidate操作之后,root list中的结点最多有D(n)+1。而二项堆中degree最大值不超过floor(lgn),从而root list中最多有floor(lgn)+1颗二项树。

5)另外一个与二项堆的最大不同之处在于:F-Heap是一种具有平摊意义上的高性能数据结构。除了Extract-Min和Delete两类操作具有平摊复杂度O(lgn),其他的操作(insert,union,find-min,decrease-key)的平摊复杂度都是常数级。因此如果有一系列的操作,其中Extract-min和delete操作个数为p,其他操作个数为q,p


以下是基于CLRS第三版的伪代码的Fibonacci Heap的实现。以下几点值得注意一下:

1)Decrease-Key操作中通过添加变量cascade消除CLRS中Cascading Cut函数的tail recursion;

2)Extract-Min的consolidate函数中每处理一个root结点就将该结点从root list中删除,然后在寻找新的min结点时按照degree从小到大次序(实际上在F-Heap中不用关心节点之间的相对顺序)恢复root list;

3)consolidate函数中的link操作和二项堆中的操作类似,只不过这里不用考虑child list中结点的顺序;

4)Extract-Min中涉及mark属性的代码:在Extract-Min中将min的所有孩子结点添加到root list时不需要清除mark属性,等到consolidate的link操作以及寻找新的min结点时再分别设置:linked child的mark = false,root的mark=false。


/**
 * 
 * Fibonacci Heap   
 *  
 * Copyright (c) 2011 ljs (http://blog.csdn.net/ljsspace/)
 * Licensed under GPL (http://www.opensource.org/licenses/gpl-license.php) 
 * 
 * @author ljs
 * 2011-09-05
 *
 */
public class FibonacciHeap {
	static class Node{
		private int key;
		private Node parent=null;
		
		private int degree=0;
		private Node child=null;
		
		private Node left;
		private Node sibling;
		
		private boolean mark=false;
		 
		public Node(int key){
			this.key = key;
		}
		public String toString(){
			return this.key + "(degree=" + this.degree + ",mark=" + this.mark + ")";
		}
	}
	//the head of root list
	private Node min;
	private int n;
	
	//insert a single node
	public void insert(Node node){
		addToRootList(node);
		n++;	
	}
	
	private void addToRootList(Node node){			
		if(min==null){					
			node.left=node.sibling=node;
			
			min = node;
		}else{
			//insert node in root list as node's left neighbor
			Node prev = min.left;
			
			prev.sibling = node;
			node.sibling = min;
			
			min.left = node;
			node.left = prev;
			
			if(node.keyrhs.key){
				min = rhs;
			}
		}
		n += h.n;
	}
	
	public Node extractMin(){
		Node z = this.min;
		if(z!=null){
			//insert z's children in the root list
			Node x = z.child;			
			while(x!=null){
				Node next = x.sibling;
				this.addToRootList(x);
				x.parent = null;
				//x.mark = false; //delay updating mark until linking and finding new min
				x = (next != z.child)?next:null;
			}
			
			//remove z from root list
			n--;
			
			Node prev = z.left;			
			if(prev==z){
				//z is the only node in root list
				min = null;
			}else{
				Node next = z.sibling;
				prev.sibling = next;
				next.left = prev;
				//set min to a temporary value as an entry pointer of the heap, 
				//later we will update it
				this.min = next;
				consolidate();
			}			
		}
		return z;
	}
	
	private void consolidate(){
		double goldratio = (Math.sqrt(5)+1)/2.0;
		int maxdegree = (int)(Math.log(n) / Math.log(goldratio));
		
		Node[] A = new Node[maxdegree+1];
		//iterate all nodes in root list
		Node w = this.min;
		while(w!=null){
			Node prev = w.left;
			Node next = w.sibling;
			
			Node x = w;
			int d = x.degree;
			while(A[d] != null){
				Node y = A[d];
				//link x and y
				if(x.key


测试输出:

F-Heap(n=15):
|1
 |-9(x)
  |--10
  |--11
   |---12
 |-2
 |-3
  |--4
|6
|7
 |-8
|8
 |-16
 |-9
  |--13
min:1

F-Heap(n=7):
|7
 |-21
 |-20
  |--39
|18
|38
 |-40(x)
F-Heap(n=22):
|1
 |-9(x)
  |--10
  |--11
   |---12
 |-2
 |-3
  |--4
|7
 |-21
 |-20
  |--39
|18
|38
 |-40(x)
|6
|7
 |-8
|8
 |-16
 |-9
  |--13
1 2 3 4 6 7 7 8 8 9 9 10 11 12 13 16 18 20 21 38 39 40

你可能感兴趣的:(数据结构和算法)