比较实用的堆有二叉堆(完全二叉树),因为其空间需求最小(可用数组实现),编程复杂度最低。
但是,在特殊情况时,需要常用合并操作并且n较大时,二叉堆的合并操作的复杂度是o(n),如果n是较大的值,可能是比较难以接受的,所以就有了可并堆。
本文主要学习可并堆的理论上的知识点。
定义:
各种操作的时间复杂度
定义
合并A,B链两个斜堆
2)删除:
将要删除的结点的左右儿子合并即可
小根堆合并伪代码:
Struct Node { int key,lch,rch;//值,左节点索引,右节点索引 } ..merge(A,B) { if (A == NULL) return B; if (B == NULL) return A; if (A.key > B.key)swap(A,B);//如果A的值较大,则交换A和B节点 A.rch = merge(A.rch,B);//把A的右子树与B合并(递归进行)当做A的新的右子树 swap(A.rch,A.lch);//交换A的左右子树 return A; }
(3)Insert() Delete() 中都只调用了一次merge()因此他们的复杂度与merge()相同
时间复杂度
合并操作,伪代码
Merge(A, B) { If (A== NULL) return B; If (B== NULL) return A; If key[B] < key[A] Then swap(A, B); rch[A] = Merge(rch[A],B); If ( NPL[ rch[A] ] > NPL[ lch[A] ] )//一直向右儿子走,到达空结点的距离的值的比较 swap( lch[A], rch[A]); NPL[A] = NPL[rch[A]] + 1;//Merge操作时维护NPL的值 return A }
二项树:节点数为2k,k=0,1,2,3……,如下图
定义:Bk是有2k个结点的二项树
则:Bk+1 = Bk+Bk
二项树->二项堆
二项树增加结点
时间复杂度
实现方式:用左儿子右兄弟的方法存储树。更多操作及具体实现:《算法导论》
#include <iostream> #include <ctime> using namespace std; struct node { int value; node *ch[2], *pre; } tree[1000001], *tmp[1000001], *root, *Null; int top = 0; node *New_Node(int x) { node *p = &tree[top ++]; p->value = x, p->ch[0] = p->ch[1] = p->pre = Null; return p; } node *Link(node *a, node *b) { if (a->value > b->value) swap(a, b); if (b == Null) return a; b->ch[1] = a->ch[0]; if (a->ch[0] != Null) a->ch[0]->pre = b; a->ch[0] = b, b->pre = a; return a; } node *Combine(node *x) { int total = 0, i; node *y, *z, *res; if (x == Null) return Null; for ( ; x != Null; x = z) { y = x->ch[1], z = y->ch[1]; x->ch[1] = y->ch[1] = y->pre = z->pre = Null; tmp[++ total] = Link(x, y); } for (res = tmp[total], i = total-1; i; i --) res = Link(res, tmp[i]); return res; } int main() { int n, i; freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout); root = Null = New_Node(INT_MAX); Null->ch[0] = Null->ch[1] = Null->pre = Null; scanf("%d", &n), srand(time(0)); for (i = 1; i <= n; i ++) root = Link(root, New_Node((rand()<<16)+rand())); for (i = 1; i <= n; i ++) printf("%d ", root->value), root = Combine(root->ch[0]); printf("\n"); return 0; }
参考:http://en.wikipedia.org/wiki/Fibonacci_Heap
简单介绍