插入 n个随机数据,取m次最小值并pop掉
n=10000000(一千万),m=0 (纯插入,一个o1,一个logn)
fib:耗时8377ms
stl:耗时5086ms
n = 5000000(五百万), m=20000(2万)
fib:耗时4945ms
stl:耗时2605ms
n = 5000000(五百万), m=2000000(2百万)
fib:耗时15148ms
stl:耗时6069ms
n = 5000000(五百万), m=0()
fib:耗时4290ms
stl:耗时2590ms
以上的随机数据用rand()函数生成,测试环境是WIN7+I5笔记本
可以看出 在 这个规模下的 即使斐波那契堆的插入是 o(1),也并不能带来特别明显的优势
原因可能如下,
1.这个fib是用 分散式内存实现的,(新加入的加点是用new获取内存,这可能是一大原因)
2.fib堆本身操作常数因子就比较大,所以这个小规模下的数据并不能体现出复杂度的优势 (o1 - lgn)
3.代码写得太挫了。。。有时间自己再实现一遍吧
以下附上所用的fib代码: (网上找的+自己修改勉强跑起来的)
//说明:
//代码中Fibonacci Heap 用变量heap表示
//结点通常用x,y等表示
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<climits>
#include<windows.h>
#include<time.h>
#include<vector>
using namespace std;
struct node
{
int ff;
int x,v;
node(){}
node( int a,int b)
{ x=a;v=b;}
node(int c,int a,int b)
{ff=c;x=a;v=b;}
bool operator<(const node&b )const
{
return v<b .v;
}
bool operator>(const node&b )const
{ return v>b.v;
}
bool operator==(const node&b )const
{
return (v==b.v)&&(x==b.x);
}
};
node int_MIN;
//斐波那契结点ADT
struct FibonacciHeapNode {
node key; //结点
int degree; //度
FibonacciHeapNode * left; //左兄弟
FibonacciHeapNode * right; //右兄弟
FibonacciHeapNode * parent; //父结点
FibonacciHeapNode * child; //第一个孩子结点
bool marked; //是否被删除第1个孩子
};
typedef FibonacciHeapNode FibNode;
//斐波那契堆ADT
struct FibonacciHeap {
int keyNum; //堆中结点个数
FibonacciHeapNode * min;//最小堆,根结点
int maxNumOfDegree; //最大度
FibonacciHeapNode * * cons;//指向最大度的内存区域
};
typedef FibonacciHeap FibHeap;
/*****************函数申明*************************/
//将x从双链表移除
inline void FibNodeRemove(FibNode * x);
//将x堆结点加入y结点之前(循环链表中)
void FibNodeAdd(FibNode * x, FibNode * y);
//初始化一个空的Fibonacci Heap
FibHeap * FibHeapMake() ;
//初始化结点x
FibNode * FibHeapNodeMake();
//堆结点x插入fibonacci heap中
void FibHeapInsert(FibHeap * heap, FibNode * x);
//将数组内的值插入Fibonacci Heap
void FibHeapInsertKeys(FibHeap * heap, int keys[], int keyNum);
//将值插入Fibonacci Heap
static void FibHeapInsertKey(FibHeap * heap, node key);
//抽取最小结点
FibNode * FibHeapExtractMin(FibHeap * heap);
//合并左右相同度数的二项树
void FibHeapConsolidate(FibHeap * heap);
//将x根结点链接到y根结点
void FibHeapLink(FibHeap * heap, FibNode * x, FibNode *y);
//开辟FibHeapConsolidate函数哈希所用空间
static void FibHeapConsMake(FibHeap * heap);
//将堆的最小结点移出,并指向其有兄弟
static FibNode *FibHeapMinRemove(FibHeap * heap);
//减小一个关键字
void FibHeapDecrease(FibHeap * heap, FibNode * x, node key);
//切断x与父节点y之间的链接,使x成为一个根
static void FibHeapCut(FibHeap * heap, FibNode * x, FibNode * y);
//级联剪切
static void FibHeapCascadingCut(FibHeap * heap, FibNode * y);
//修改度数
void renewDegree(FibNode * parent, int degree);
//删除结点
void FibHeapDelete(FibHeap * heap, FibNode * x);
//堆内搜索关键字
FibNode * FibHeapSearch(FibHeap * heap, node key);
//被FibHeapSearch调用
static FibNode * FibNodeSearch(FibNode * x, node key);
//销毁堆
void FibHeapDestory(FibHeap * heap);
//被FibHeapDestory调用
static void FibNodeDestory(FibNode * x);
//输出打印堆
static void FibHeapPrint(FibHeap * heap);
//被FibHeapPrint调用
static void FibNodePrint(FibNode * x);
/************************************************/
//将x从双链表移除
inline void FibNodeRemove(FibNode * x) {
x->left->right = x->right;
x->right->left = x->left;
}
/*
将x堆结点加入y结点之前(循环链表中)
a …… y
a …… x …… y
*/
inline void FibNodeAdd(FibNode * x, FibNode * y) {
x->left = y->left;
y->left->right = x;
x->right = y;
y->left = x;
}
//初始化一个空的Fibonacci Heap
FibHeap * FibHeapMake() {
FibHeap * heap = NULL;
heap = (FibHeap *) malloc(sizeof(FibHeap));
if (NULL == heap) {
puts("Out of Space!!");
exit(1);
}
memset(heap, 0, sizeof(FibHeap));
return heap;
}
//初始化结点x
FibNode * FibHeapNodeMake() {
FibNode * x = NULL;
x = (FibNode *) malloc(sizeof(FibNode));
if (NULL == x) {
puts("Out of Space!!");
exit(1);
}
memset(x, 0, sizeof(FibNode));
x->left = x->right = x;
return x;
}
//堆结点x插入fibonacci heap中
void FibHeapInsert(FibHeap * heap, FibNode * x) {
if (0 == heap->keyNum) {
heap->min = x;
} else {
FibNodeAdd(x, heap->min);
x->parent = NULL;
if (x->key < heap->min->key) {
heap->min = x;
}
}
heap->keyNum++;
}
//将数组内的值插入Fibonacci Heap
void FibHeapInsertKeys(FibHeap * heap, int keys[], int keyNum) {
// for (int i = 0; i < keyNum; i++) {
// FibHeapInsertKey(heap, keys[i]);
// }
}
//将值插入Fibonacci Heap
static void FibHeapInsertKey(FibHeap * heap, node key) {
FibNode * x = NULL;
x = FibHeapNodeMake();
x->key = key;
FibHeapInsert(heap, x);
}
//抽取最小结点
FibNode * FibHeapExtractMin(FibHeap * heap) {
FibNode * x = NULL, * z = heap->min;
if (z != NULL) {
//删除z的每一个孩子
while (NULL != z->child) {
x = z->child;
FibNodeRemove(x);
if (x->right == x) {
z->child = NULL;
} else {
z->child = x->right;
}
FibNodeAdd(x, z);//add x to the root list heap
x->parent = NULL;
}
FibNodeRemove(z);
if (z->right == z) {
heap->min = NULL;
} else {
heap->min = z->right;
FibHeapConsolidate(heap);
}
heap->keyNum--;
}
return z;
}
//合并左右相同度数的二项树
void FibHeapConsolidate(FibHeap * heap) {
int D, d;
int i;
FibNode * w = heap->min, * x = NULL, * y = NULL;
FibHeapConsMake(heap);//开辟哈希所用空间
D = heap->maxNumOfDegree + 1;
for ( i = 0; i < D; i++) {
*(heap->cons + i) = NULL;
}
//合并相同度的根节点,使每个度数的二项树唯一
while (NULL != heap->min) {
x = FibHeapMinRemove(heap);
d = x->degree;
while (NULL != *(heap->cons + d)) {
y = *(heap->cons + d);
if (x->key > y->key) {//根结点key最小
swap(x, y);
}
FibHeapLink(heap, y, x);
*(heap->cons + d) = NULL;
d++;
}
*(heap->cons + d) = x;
}
heap->min = NULL;//原有根表清除
//将heap->cons中结点都重新加到根表中,且找出最小根
for ( i = 0; i < D; i++) {
if (*(heap->cons + i) != NULL) {
if (NULL == heap->min) {
heap->min = *(heap->cons + i);
} else {
FibNodeAdd(*(heap->cons + i), heap->min);
if ((*(heap->cons + i))->key < heap->min->key) {
heap->min = *(heap->cons + i);
}//if(<)
}//if-else(==)
}//if(!=)
}//for(i)
}
//将x根结点链接到y根结点
void FibHeapLink(FibHeap * heap, FibNode * x, FibNode *y) {
FibNodeRemove(x);
if (NULL == y->child) {
y->child = x;
} else {
FibNodeAdd(x, y->child);
}
x->parent = y;
y->degree++;
x->marked = false;
}
//开辟FibHeapConsolidate函数哈希所用空间
static void FibHeapConsMake(FibHeap * heap) {
int old = heap->maxNumOfDegree;
heap->maxNumOfDegree = int(log(heap->keyNum * 1.0) / log(2.0)) + 1;
if (old < heap->maxNumOfDegree) {
//因为度为heap->maxNumOfDegree可能被合并,所以要maxNumOfDegree + 1
heap->cons = (FibNode **) realloc(heap->cons,
sizeof(FibHeap *) * (heap->maxNumOfDegree + 1));
if (NULL == heap->cons) {
puts("Out of Space!");
exit(1);
}
}
}
//将堆的最小结点移出,并指向其有兄弟
static FibNode *FibHeapMinRemove(FibHeap * heap) {
FibNode *min = heap->min;
if (heap->min == min->right) {
heap->min = NULL;
} else {
FibNodeRemove(min);
heap->min = min->right;
}
min->left = min->right = min;
return min;
}
//减小一个关键字
void FibHeapDecrease(FibHeap * heap, FibNode * x, node key) {
FibNode * y = x->parent;
if (x->key < key) {
puts("new key is greater than current key!");
exit(1);
}
x->key = key;
if (NULL != y && x->key < y->key) {
//破坏了最小堆性质,需要进行级联剪切操作
FibHeapCut(heap, x, y);
FibHeapCascadingCut(heap, y);
}
if (x->key < heap->min->key) {
heap->min = x;
}
}
//切断x与父节点y之间的链接,使x成为一个根
static void FibHeapCut(FibHeap * heap, FibNode * x, FibNode * y) {
FibNodeRemove(x);
renewDegree(y, x->degree);
if (x == x->right) {
y->child = NULL;
} else {
y->child = x->right;
}
x->parent = NULL;
x->left = x->right = x;
x->marked = false;
FibNodeAdd(x, heap->min);
}
//级联剪切
static void FibHeapCascadingCut(FibHeap * heap, FibNode * y) {
FibNode * z = y->parent;
if (NULL != z) {
if (y->marked == false) {
y->marked = true;
} else {
FibHeapCut(heap, y, z);
FibHeapCascadingCut(heap, z);
}
}
}
//修改度数
void renewDegree(FibNode * parent, int degree) {
parent->degree -= degree;
if (parent-> parent != NULL) {
renewDegree(parent->parent, degree);
}
}
//删除结点
void FibHeapDelete(FibHeap * heap, FibNode * x) {
FibHeapDecrease(heap, x, int_MIN);
FibHeapExtractMin(heap);
}
//堆内搜索关键字
FibNode * FibHeapSearch(FibHeap * heap, node key) {
return FibNodeSearch(heap->min, key);
}
//被FibHeapSearch调用
static FibNode * FibNodeSearch(FibNode * x, node key) {
FibNode * w = x, * y = NULL;
if (x != NULL) {
do {
if (w->key == key) {
y = w;
break;
} else if (NULL != (y = FibNodeSearch(w->child, key))) {
break;
}
w = w->right;
} while (w != x);
}
return y;
}
//销毁堆
void FibHeapDestory(FibHeap * heap) {
FibNodeDestory(heap->min);
free(heap);
heap = NULL;
}
//被FibHeapDestory调用
static void FibNodeDestory(FibNode * x) {
FibNode * p = x, *q = NULL;
while (p != NULL) {
FibNodeDestory(p->child);
q = p;
if (p -> left == x) {
p = NULL;
} else {
p = p->left;
}
free(q->right);
}
}
//输出打印堆
static void FibHeapPrint(FibHeap * heap) {
printf("The keyNum = %d\n", heap->keyNum);
FibNodePrint(heap->min);
puts("\n");
};
//被FibHeapPrint调用
static void FibNodePrint(FibNode * x) {
FibNode * p = NULL;
if (NULL == x) {
return ;
}
p = x;
do {
printf(" (");
printf("%d", p->key);
if (p->child != NULL) {
FibNodePrint(p->child);
}
printf(") ");
p = p->left;
}while (x != p);
}
const int inf=1147483647;;
int aaa[20000000+5];
int bbb[20000000+5];
int main()
{
freopen( "1.in","r",stdin );
freopen( "5.out","w",stdout );
int_MIN.ff=int_MIN.v=int_MIN.x=-1;
int i,j;
int n,m,x,y;
cin>>n;
FibHeap * heap = NULL;
heap = FibHeapMake();
for (i=1;i<=n;i++)
{
scanf("%d %d" ,&aaa[i],&bbb[i]);
}
DWORD dwStartTime = GetTickCount();
for (i=1;i<=n;i++)
{
FibHeapInsertKey(heap, node(aaa[i],bbb[i]));
}
cin>>m;
for (i=1;i<=m;i++)
{
FibHeapExtractMin(heap)->key;
}
cout<<"耗时"<<GetTickCount()-dwStartTime<<"ms"<<endl;
return 0;
}