堆:Binary Heap, Fibonacci Heaps资料+总结

来源:互联网 发布:怎样使用农村淘宝 编辑:程序博客网 时间:2024/05/01 21:50


最大堆实现堆排序

最小堆实现优先级队列

三大优先队列利器:

         二项堆

         Fibonacci堆

         Paring堆



一, 堆:http://blog.csdn.net/zhang20072844/article/details/10286997


           堆的特性:

      n个关键字序列Kl,K2,…,Kn称为(Heap),当且仅当该序列满足如下性质(简称为堆性质):

(1)ki<=k(2i)且ki<=k(2i+1)(1≤i≤ n),当然,这是小根堆,大根堆则换成>=号。//k(i)相当于二叉树的非叶结点,K(2i)则是左孩子,k(2i+1)是右孩子


1:最大堆实现堆排序

创建堆http://wenku.baidu.com/view/0b8cc38ecc22bcd126ff0c62.html  von unten nach oben 调整堆(reparieren)

(1)用最大堆排序的基本思想

① 先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区(Create ein MaxHeap ---unsortiert Array

② 再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新的无序区R[1..n-1]和有序区(sortiert Array)R[n],且满足R[1..n-1].keys≤R[n].key

③由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区R[1..n-2]和有序区R[n-1..n],且仍满足关系R[1..n-2].keys≤R[n-1..n].keys,同样要将R[1..n-2]调整为堆,直到无序区只有一个元素为止。

(2)大根堆排序算法的基本操作: 

① 初始化操作:将R[1..n]构造为初始堆;

② 每一趟排序的基本操作:将当前无序区的堆顶记录R[1]和该区间的最后一个记录交换,然后将新的无序区调整为堆(亦称重建堆)。

注意: 

①只需做n-1趟排序,选出较大的n-1个关键字即可以使得文件递增有序。

②用小根堆排序与利用大根堆类似,只不过其排序结果是递减有序的。堆排序和直接选择排序相反:在任何时刻堆排序中无序区总是在有序区之前,且有序区是在原向量的尾部由后往前逐步扩大至整个向量为止。

(实现代码:http://www.cnblogs.com/dolphin0520/archive/2011/10/06/2199741.html

 其中一段:

void HeapSort(int *a,int size)    //堆排序 
{
int i;
BuildHeap(a,size);
for(i=size;i>=1;i--)
{
//cout<<a[1]<<" ";
swap(a[1],a[i]); //交换堆顶和最后一个元素,即每次将剩余元素中的最大者放到最后面
//BuildHeap(a,i-1); //将余下元素重新建立为大顶堆
HeapAdjust(a,1,i-1); //重新调整堆顶节点成为大顶堆
}
}

2:最小堆实现优先级队列

实现优先队列结构主要是通过堆完成,主要有:二叉堆、d堆、左式堆、斜堆、二项堆、斐波那契堆、pairing 堆等。(http://blog.csdn.net/yangtrees/article/details/8252760)

 http://blog.csdn.net/gls_jia/article/details/6767207


二,优先队列三大利器(结构)

(1)二项堆   

(2)斐波那契堆

(3)Pairing 堆


(1)http://blog.csdn.net/yangtrees/article/details/8141698

(2)

http://www-i1.informatik.rwth-aachen.de/Lehre/SS05/PSAuD/Handout_HurtzSchiffel.pdf

http://blog.csdn.net/mishifangxiangdefeng/article/details/7823588

mark的作用

   为了防止堆太宽,需要策略来调整堆,使根结点成为别的根结点的孩子,该策略就是CONSOLIDATE,同理,为了防止堆太深,也需要有相应的策略去调整,在适当的时候,把某个结点的孩子变成根。这一策略就是CUT和CASCADING-CUT,mark在实现这一策略的过程中起到辅助作用。

   原理:当一个非根结点被切掉了2个孩子,就把它升为根结点

在删除一个结点时,怎么区分是第一个被删除的孩子,还是第二个?此时需要用mark来标记。


(摘自http://www.haodaima.net/art/2875665)

DecreaseKey:

        减少斐波那契堆中的节点的键值,这个操作的难点是:如果减少节点后破坏了'最小堆'性质,如何去维护呢?下面对一般性情况进行分析。

(1) 首先,将'被减小节点'从'它所在的最小堆'剥离出来;然后将'该节点'关联到'根链表'中。 倘若被减小的节点不是单独一个节点,而是包含子树的树根。则是将以'被减小节点'为根的子树从'最小堆'中剥离出来,然后将该树关联到根链表中。
(2) 接着,对'被减少节点'的原父节点进行'级联剪切'。所谓'级联剪切',就是在被减小节点破坏了最小堆性质,并被切下来之后;再从'它的父节点'进行递归级联剪切操作。
      而级联操作的具体动作则是:若父节点(被减小节点的父节点)的marked标记为false,则将其设为true,然后退出。否则,将父节点从最小堆中切下来(方式和'切被减小节点的方式'一样);然后递归对祖父节点进行'级联剪切'。   marked标记的作用就是用来标记'该节点的子节点是否有被删除过',它的作用是来实现级联剪切。而级联剪切的真正目的是为了防止'最小堆'由二叉树演化成链表。

斐波那契堆 代码详解:http://blog.csdn.net/xiangzhang321/article/details/7533912



斐波那契的应用包括:

          在Dijkstra 和Prim算法中用到Fibonacci 算法,其中Fibonacci-heaps作为优先队列可大大提高Laufzeit.(        Anwendungen:

Im Vortrag werden mit dem Dijkstra- und dem Prim-Algorithmus zwei Beispiel-Algorithmen betrachtet,in denen Fibonacci-Heaps als effiziente Priorit¨atswarteschlangen eingesetzt werden k¨onnen. Beim DijkstraAlgorthmus erreicht man dadurch eine Laufzeit in O(|E| + |V | log |V |), der Prim-Algorithmus verbessert sich
auf O(|V | log |V | + |E|)

斐波那契堆理论分析:http://www.cnblogs.com/rancher/p/4159570.html

证明??








0 0