#include"stdafx.h"
#include<math.h>
#include<stdio.h>
#include"PriorityQueue.h"
#include<iostream>
#include<set>
#include<vector>
using namespace std;
//Node:
//Pointer: Left, Right, Parent, Child
//bool mark, ElemType elem, int degree
class Node {
public:
Node();
Node(ElemType elem);
Node *left, *right, *parent, *child;
bool mark;
ElemType elem;
int degree;
};
//FibonacciHeap
//Size
//Pointer: rootlist, min
class FibHeap {
public:
FibHeap();
void Insert(ElemType elem);
void Insert(Node *t);
Node* ExtractMin();
void DecreaseKey(Node *e, int key);
void FibHeapDelete(Node *e);
set<Node*> FibHeapNodes;
vector<Node *>FibHeapNodesVector; //For delete
~FibHeap();
protected:
void Consolidate();
void Cut(Node *cutnode, Node *parent);
void CascadingCut(Node *node);
int MaxDegree(); //Return the max degree of node in the FibHeap
void FibLink(Node *y, Node *x);
private:
Node* rootlist;
Node* min;
int size;
};
void TestFib();
int main() {
//freopen("input.txt", "r", stdin);
TestFib();
int i = 0;
cin>>i;
}
/* 1 2 1 3 1 4 1 5 2 2 2 */
void TestFib() {
FibHeap *fib = new FibHeap();
int i;
ElemType elem;
Node *ret = 0;
set<Node *>::reverse_iterator it;
while(true) {
cin>>i;
switch(i) {
case 1:
//Insert
cin>>elem.key;
fib->Insert(elem);
break;
case 2:
//ExtractMin
ret = fib->ExtractMin();
if(ret == 0) cout<<"error"<<endl;
else cout<<ret->elem.key<<endl;
break;
case 3:
for(it = fib->FibHeapNodes.rbegin(); it != fib->FibHeapNodes.rend(); it++) {
fib->DecreaseKey(*it, (*it)->elem.key - 1);
}
break;
case 4:
break;
case 5:
delete fib;
return;
}
}
}
Node::Node() { //这段重复代码如何去除
left = right = parent = child = 0;
mark = false;
degree = 0;
}
Node::Node(ElemType elem) {
this->elem = elem;
left = right = parent = child = 0;
mark = false;
degree = 0;
}
FibHeap::FibHeap(){
this->min = this->rootlist = 0;
this->size = 0;
}
void FibHeap::Insert(ElemType elem) {
Node *e = new Node(elem);
Insert(e);
}
void FibHeap::Insert(Node *t) {
FibHeapNodes.insert(t);
t->left = t->right = t;
if(rootlist == 0) {
this->min = this->rootlist = t;
} else{
t->right = rootlist;
t->left = rootlist->left;
t->left->right = t->right->left = t;
if(Less(t->elem, this->min->elem)) this->min = t;
}
this->size++;
}
Node *FibHeap::ExtractMin() {
Node* ret = this->min;
//Add all the child of this->min to the rootlist of Heap
if(ret == 0) return 0;
if(ret->child != 0) {
//Add all the child of this->min to the rootlist
//at this time, rootlist != NIL<Because of the existence of ret>
Node *prev = ret->child, *next;
do {
//Add the node of prev to the rootlist
next = prev->right;
prev->right = rootlist;
prev->left = rootlist->left;
prev->left->right = prev->right->left = prev;
rootlist = prev; //rootlist可改可不改
prev->parent = 0;
prev = next;
} while(next != ret->child);
}
//Remove this->min
ret->right->left = ret->left;
ret->left->right = ret->right;
if(rootlist == ret) rootlist = ret->right;
if(ret == ret->right)this->rootlist = this->min = 0;
else {
this->min = ret->right;
Consolidate();
}
//Consolidate the FibHeap
this->size--;
FibHeapNodes.erase(ret);
return ret;
}
void FibHeap::Consolidate() {
int maxDegree = this->MaxDegree();
//数组一定要初始化
Node **aux = new Node* [maxDegree + 1]; //Auxiliary Array< aux[d]: tree with degree d>
for(int i = 0; i <= maxDegree; i++) aux[i] = 0;
//Iterate over the rootlist
Node *iter = rootlist, *next;
if(iter == 0) return;//It means the list is empty
do {
Node *x = iter; //FibLink Will change Iter
int degree = x->degree;
next = iter->right;
while(aux[degree] != 0) {
Node *y = aux[degree];
if(Less(y->elem, x->elem)) {
//SWAP X AND Y 可以考虑用宏实现
Node *temp = x;
x = y;
y = temp;
}
FibLink(y, x); //Let y be a child of x //此处改变了next->right
aux[degree] = 0;
degree++;
}
aux[degree] = x;
iter = next; //iter can't be zero
}while(iter != rootlist);
//Reconstruct the list
this->min = this->rootlist = 0;
for(int i = 0; i <= maxDegree; i++) { //Add the list to the rootlist
if(aux[i] != 0) { //代码可以更加简洁
if(rootlist == 0){
this->min = this->rootlist = aux[i]->left = aux[i]->right = aux[i]; // When rootlist is empty
}
else {
//Add aux[i];
aux[i]->right = rootlist;
aux[i]->left = rootlist->left;
aux[i]->left->right = aux[i]->right->left = aux[i];
if(Less(aux[i]->elem, this->min->elem)) this->min = aux[i];
}
}
}
delete[] aux;
}
void FibHeap::FibLink(Node *y, Node *x) {
//Remove y from the rootlist, may no need 这一个决定删去,因为会影响正确性
//y->left->right = y->right;//这一段话导致了next值出错 if y is the rootlist
//y->right->left = y->left;
//if(y == rootlist) rootlist = y->right; 加上这一句话也未必是对的
//Make y a child of x, add the degree of x 双向链表的表头。 对指针的引用存在不?
y->parent = x;
if(x->child == 0) x->child = y->left = y->right = y;
else {
y->left = x->child->left;
y->right = x->child;
y->left->right = y->right->left = y;
}
x->degree++;
//Mark y = false why? y的度已经改变了。然后重新加入到rootlist中的,所以mark可以为负值
y->mark = false;
}
void FibHeap::DecreaseKey(Node *e, int key) {
if(e == 0) return;
if(e->elem.key <= key) return;
e->elem.key = key;
Node *p = e->parent;
if(p != 0 && Less(e->elem, p->elem)) {
Cut(e, p);
CascadingCut(p);
}
if(Less(e->elem, this->min->elem)) this->min = e;
}
void FibHeap::Cut(Node *cutNode, Node *parent) {
//Remove cutNode from parent list
if(parent->child == cutNode) {
if(parent->degree == 1) //Only one child
parent->child = 0;
else
parent->child = cutNode->right;
}
cutNode->right->left = cutNode->left;
cutNode->left->right = cutNode->right;
parent->degree--;
//Add cutNode to the rootlist
//rootlist can't be empty!
cutNode->right = rootlist;
cutNode->left = rootlist->left;
cutNode->left->right = cutNode->right->left = cutNode;
//Pointer:mark parent
cutNode->mark = false; //?? why?? 还是无法理解mark商标
cutNode->parent = 0;
}
void FibHeap::CascadingCut(Node *node) {
Node *parent = node->parent;
if(parent != 0)
if(parent->mark == false) parent->mark = true;
else{
Cut(node, parent);
CascadingCut(parent);
}
}
void FibHeap::FibHeapDelete(Node *e) {
this->DecreaseKey(e, -9999);
free(this->ExtractMin());
}
int FibHeap::MaxDegree() {
if(this->size == 0) return 0;
int max = (int) (2 * log((float)this->size) / log((float)2)) + 2;
return max;
}
FibHeap::~FibHeap() {
set<Node*>::iterator it;
for(it = FibHeapNodes.begin(); it != FibHeapNodes.end(); it++) FibHeapNodesVector.push_back(*it);
for(int i = 0; i < FibHeapNodesVector.size(); i++) {
cout<<"Clearing: "<<FibHeapNodesVector[i]->elem.key<<endl;
FibHeapDelete(FibHeapNodesVector[i]);
}
}
Fibonacci堆的代码-欢迎斧正并且报告Bug
最新推荐文章于 2025-04-26 16:36:54 发布