实现斐波拉契堆并与二叉堆比较效率(Dijkstra算法)
template <class T>
class MinHeap{
private:
T *mHeap; // 数据
int mCapacity; // 总的容量
int mSize; // 实际容量
private:
// 最小堆的向下调整算法
void filterdown(int start, int end);
// 最小堆的向上调整算法(从start开始向上直到0,调整堆)
void filterup(int start);
public:
MinHeap();
MinHeap(int capacity);
~MinHeap();
int getIndex(T data);// 返回data在二叉堆中的索引
int remove(T data);// 即extract_min
int insert(T data);// 将data插入到二叉堆中
int decrease_key(T pos,T data);
int empty();
T find_min();
};
decrease_key
template <class T>
int MinHeap<T>::decrease_key(T pos,T data){
int index = getIndex(pos);
if(index == -1)return -1;
if(mHeap[index] <= data)return -1;
mHeap[index] = data;
filterup(index);
return 0;
}
filterdown
template <class T>
void MinHeap<T>::filterdown(int start, int end)
{
T temp;
int left = 2*start + 1;
int right = 2*start + 2;
if(left > end)return;
if(right > end)
{
if(mHeap[left] < mHeap[start])
{
temp = mHeap[left];
mHeap[left] = mHeap[start];
mHeap[start] = temp;
filterdown(left,end);
return;
}else{
return;
}
}else{
if(mHeap[right] <= mHeap[left]&&mHeap[right] < mHeap[start])
{
temp = mHeap[right];
mHeap[right] = mHeap[start];
mHeap[start] = temp;
filterdown(right,end);
return;
}else if(mHeap[left] < mHeap[right]&&mHeap[left] < mHeap[start])
{
temp = mHeap[left];
mHeap[left] = mHeap[start];
mHeap[start] = temp;
filterdown(left,end);
return;
}
else
{
return;
}
}
}
filterup
template <class T>
void MinHeap<T>::filterup(int start){
int father = (start - 1 ) / 2;
while(father >= 0 && mHeap[father] > mHeap[start] )
{
T temp = mHeap[father];
mHeap[father] = mHeap[start];
mHeap[start] = temp;
start = father;
father = (start - 1) / 2;
}
}
基本按照给的模板完成,略作修改,将map
并在一些函数的参数中作了修改。
struct Node {
T key;
int degree;
bool mark;
Node *p, *child, *left, *right;
Node(T k) : key(k), degree(0), mark(false) {
p = child = nullptr;
left = right = this;
}
};
用Node* Min来寻找根链表
用vector
n记录节点个数
template <class T>
class Fibonacci_Heap {
private:
struct Node {
T key;
int degree;
bool mark;
Node *p, *child, *left, *right;
Node(T k) : key(k), degree(0), mark(false) {
p = child = nullptr;
left = right = this;
}
};
Node *Min;
int n;
//map mp;
vector<Node*>mp;
void Del_Tree(Node *root);
void Consolidate();
void Link(Node *y, Node *x);
void Cut(Node *x, Node *y);
void Cascading_Cut(Node *y);
public:
Fibonacci_Heap();
~Fibonacci_Heap();
void Push(int id,T x);
bool Empty();
T Top();
void Pop();
void Decrease_Key(int id, T k);
};
template <class T>
void Fibonacci_Heap<T>::Push(int id,T x) {
while(id >= mp.size()){
mp.push_back(nullptr);
}
Node* point = new Node(x);
mp[id] = point;
if(n == 0){
Min = point;
}else{
Node* tmp = Min->left;
tmp->right = point;
Min->left = point;
point->left = tmp;
point->right = Min;
if(Min->key > point->key)
{
Min = point;
}
}
n++;
}
Pop
template <class T>
void Fibonacci_Heap<T>::Pop() {
if(n == 0) return;
n--;
if(n == 0) {
delete Min;
Min = nullptr;
return;
}
Node *tmp = Min -> child;
vector <Node *> chdlist;
if(tmp != nullptr)
do{
chdlist.push_back(tmp);
tmp = tmp -> right;
}while(tmp != Min -> child);
for(int i = 0; i < chdlist.size(); i++){
Node *iterat = chdlist[i];
Node *Mleft = Min -> left;
iterat -> p = nullptr;
Mleft -> right = iterat; Min -> left = iterat;
iterat -> left = Mleft; iterat -> right = Min;
}
Node *l = Min -> left;
Node *r = Min -> right;
l -> right = r;
r -> left = l;
delete Min;
Min = l;
Consolidate();
}
Decrease_key
template<class T>
void Fibonacci_Heap<T>::Decrease_Key(int id, T k) {
if(id>=mp.size()||mp[id] == nullptr){
cout<<"The target doesn't exit"<<endl;
return;
}
if(mp[id]->key < k){
cout<<"The key of target is higher than you thought"<<endl;return;
}
Node* target = mp[id];
target->key = k;
Node* fa = target->p;
if(fa!=nullptr && target->key < fa->key)
{
Cut(target,fa);
Cascading_Cut(fa);
}
if(target->key < Min->key)
Min = target;
}
Consolidate
用vector
几处的while循环是为了保证vector足够大,能够满足度数不会大于A.size()
while(cur->degree+1 > A.size())
{
A.push_back(nullptr); }
将根链表中每一个元素取出,放在root_listl里面
用for循环实现 对每一个root_list中元素进行判断:是否有元素具有与它相同的degree
用A中的元素创建一个新的根链表
template <class T>
void Fibonacci_Heap<T>::Consolidate() {
//cout<<"consolidate"<
vector<Node*>root_list;
vector<Node*>A;
Node* cur = Min->right;
root_list.push_back(Min);
while(cur != Min)
{
while(cur->degree+1 > A.size())
{
A.push_back(nullptr); }
root_list.push_back(cur);
cur = cur->right;
}
for(int i = 0;i < root_list.size();i++)
{
Node* x = root_list[i];
int d = x->degree;
while(d + 10>A.size()){
A.push_back(nullptr);}
//cout<
//cout<
while(A[d] != nullptr)
{
Node* y = A[d];
if(x->key > y->key)
{
Node* swap = x;
x = y;
y = swap;
}
Link(y,x);
A[d] = nullptr;
d++;
}
while(d+5 > A.size()){
A.push_back(nullptr);}
A[d] = x;
}
Min = nullptr;
for(int j = 0;j < A.size();j++)
{
if(A[j]!=nullptr){
if(Min == nullptr)
{
Min = A[j];
Min->left = Min;Min->right = Min;
}
else
{
Node* le = Min->left;
le -> right = A[j];
Min -> left = A[j];
A[j]->right = Min;
A[j]->left = le;
if(Min->key > A[j]->key)Min = A[j];
}
}
}
}
Link
template <class T>
void Fibonacci_Heap<T>::Link(Node *y, Node *x) {
//remove y from the root list
Node* l = y->left;
Node* r = y->right;
l->right = r;
r->left = l;
//make y a child of x, incrementing x.degree
x->degree++;
y->p = x;
y->mark = false;
if(x->child != nullptr){
Node* t = x->child->right;
t->left = y;
y->left = x->child;
y->right = t;
x->child->right = y;
}else
{
x->child = y;
y->left = y;y->right = y;
}
}
Cut
template <class T>
void Fibonacci_Heap<T>::Cut(Node *x, Node *y) {
y->degree--;
//remove x from child list of y
Node* tmp = x;
if(y->degree == 0){
y->child = nullptr;}
else{
if(y->child == x)
y->child = x->right;
Node* left = x->left;
Node* right = x->right;
right->left = left;
left->right = right;
}
//add x to the root list
x->p = nullptr;
x->mark = false;
Node* temp = Min->left;
temp->right = x;
Min->left = x;
x->left = temp;
x->right = Min;
}
Cascading_Cut
template <class T>
void Fibonacci_Heap<T>::Cascading_Cut(Node *y) {
Node* z = y->p;
if(z!=nullptr){
if(y->mark == false)
{
y->mark = true;
}else
{
Cut(y,z);
Cascading_Cut(z);
}
}
斐波那契堆的时间复杂度小于二项堆的时间复杂度。但是斐波那契堆的编程复杂性远高于二项堆的编程复杂性。
#ifndef BINARY_HEAP_H
#define BINARY_HEAP_H
#include
#include
using namespace std;
template <class T>
class MinHeap{
private:
T *mHeap; // 数据
int mCapacity; // 总的容量
int mSize; // 实际容量
private:
// 最小堆的向下调整算法
void filterdown(int start, int end);
// 最小堆的向上调整算法(从start开始向上直到0,调整堆)
void filterup(int start);
public:
MinHeap();
MinHeap(int capacity);
~MinHeap();
int getIndex(T data);// 返回data在二叉堆中的索引
int remove(T data);// 即extract_min
int insert(T data);// 将data插入到二叉堆中
int decrease_key(T pos,T data);
int empty();
T find_min();
};
/*
* 构造函数
*/
template <class T>
MinHeap<T>::MinHeap()
{
new (this)MinHeap(100000);
}
template <class T>
MinHeap<T>::MinHeap(int capacity){
mSize = 0;
mCapacity = capacity;
mHeap = new T[mCapacity];
}
/*
* 析构函数
*/
template <class T>
MinHeap<T>::~MinHeap()
{
mSize = 0;
mCapacity = 0;
delete[] mHeap;
}
/*
* 返回data在二叉堆中的索引
*
* 返回值:
* 存在 -- 返回data在数组中的索引
* 不存在 -- -1
*/
template <class T>
int MinHeap<T>::getIndex(T data)
{
for(int i=0; i<mSize; i++)
if (data == mHeap[i])
return i;
return -1;
}
/*
* 最小堆的向下调整算法
*
* 注:数组实现的堆中,第N个节点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。
*
* 参数说明:
* start -- 被下调节点的起始位置(一般为0,表示从第1个开始)
* end -- 截至范围(一般为数组中最后一个元素的索引)
*/
template <class T>
void MinHeap<T>::filterdown(int start, int end)
{
T temp;
int left = 2*start + 1;
int right = 2*start + 2;
if(left > end)return;
if(right > end)
{
if(mHeap[left] < mHeap[start])
{
temp = mHeap[left];
mHeap[left] = mHeap[start];
mHeap[start] = temp;
filterdown(left,end);
return;
}else{
return;
}
}else{
if(mHeap[right] <= mHeap[left]&&mHeap[right] < mHeap[start])
{
temp = mHeap[right];
mHeap[right] = mHeap[start];
mHeap[start] = temp;
filterdown(right,end);
return;
}else if(mHeap[left] < mHeap[right]&&mHeap[left] < mHeap[start])
{
temp = mHeap[left];
mHeap[left] = mHeap[start];
mHeap[start] = temp;
filterdown(left,end);
return;
}
else
{
return;
}
}
}
/*
* 删除最小堆中的data
*
* 返回值:
* 0,成功
* -1,失败
*/
template <class T>
int MinHeap<T>::remove(T data)
{
if(getIndex(data) == -1)return -1;
mHeap[0] = mHeap[--mSize];
filterdown(0,mSize-1);
return 0;
}
/*
* 最小堆的向上调整算法(从start开始向上直到0,调整堆)
* 注:数组实现的堆中,第N个节点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。
* 参数说明:start -- 被上调节点的起始位置(一般为数组中最后一个元素的索引)
*/
template <class T>
void MinHeap<T>::filterup(int start){
int father = (start - 1 ) / 2;
while(father >= 0 && mHeap[father] > mHeap[start] )
{
T temp = mHeap[father];
mHeap[father] = mHeap[start];
mHeap[start] = temp;
start = father;
father = (start - 1) / 2;
}
}
/*
* 将data插入到二叉堆中
* 返回值:
* 0,表示成功
* -1,表示失败
*/
template <class T>
int MinHeap<T>::insert(T data){
if(mSize == mCapacity)return -1;
mHeap[mSize] = data;
filterup(mSize++);
return 0;
}
template <class T>
int MinHeap<T>::decrease_key(T pos,T data){
int index = getIndex(pos);
if(index == -1)return -1;
if(mHeap[index] <= data)return -1;
mHeap[index] = data;
filterup(index);
return 0;
}
template <class T>
T MinHeap<T>::find_min(){
return mHeap[0];
}
template <class T>
int MinHeap<T>::empty(){
if(mSize == 0)return 1;
else return 0;
}
#endif
fibonnaci
#pragma once
#include
#include
#include
#include
#include
using namespace std;
template <class T>
class Fibonacci_Heap {
private:
struct Node {
T key;
int degree;
bool mark;
Node *p, *child, *left, *right;
Node(T k) : key(k), degree(0), mark(false) {
p = child = nullptr;
left = right = this;
}
};
Node *Min;
int n;
//map mp;
vector<Node*>mp;
void Del_Tree(Node *root);
void Consolidate();
void Link(Node *y, Node *x);
void Cut(Node *x, Node *y);
void Cascading_Cut(Node *y);
public:
Fibonacci_Heap();
~Fibonacci_Heap();
void Push(int id,T x);
bool Empty();
T Top();
void Pop();
void Decrease_Key(int id, T k);
};
template <class T>
Fibonacci_Heap<T>::Fibonacci_Heap() {
Min = nullptr;
n = 0;
}
template <class T>
void Fibonacci_Heap<T>::Del_Tree(Node *root) {
if(root -> child != nullptr) {
Node *ptr = root -> child;
do {
Del_Tree(ptr);
ptr = ptr -> right;
} while(ptr != root -> child);
}
delete root;
}
template <class T>
Fibonacci_Heap<T>::~Fibonacci_Heap() {
mp.clear();
Node *ptr = Min;
if(ptr == nullptr)return;
do {
Del_Tree(ptr);
ptr = ptr -> right;
} while(ptr != Min);
}
template <class T>
void Fibonacci_Heap<T>::Push(int id,T x) {
while(id >= mp.size()){
mp.push_back(nullptr);
}
Node* point = new Node(x);
mp[id] = point;
if(n == 0){
Min = point;
}else{
Node* tmp = Min->left;
tmp->right = point;
Min->left = point;
point->left = tmp;
point->right = Min;
if(Min->key > point->key)
{
Min = point;
}
}
n++;
}
template <class T>
bool Fibonacci_Heap<T>::Empty() {
if(n == 0)return true;
else return false;
}
template <class T>
T Fibonacci_Heap<T>::Top() {
return Min->key;
}
template <class T>
void Fibonacci_Heap<T>::Pop() {
if(n == 0) return;
n--;
if(n == 0) {
delete Min;
Min = nullptr;
return;
}
Node *tmp = Min -> child;
vector <Node *> chdlist;
if(tmp != nullptr)
do{
chdlist.push_back(tmp);
tmp = tmp -> right;
}while(tmp != Min -> child);
for(int i = 0; i < chdlist.size(); i++){
Node *iterat = chdlist[i];
Node *Mleft = Min -> left;
iterat -> p = nullptr;
Mleft -> right = iterat; Min -> left = iterat;
iterat -> left = Mleft; iterat -> right = Min;
}
Node *l = Min -> left;
Node *r = Min -> right;
l -> right = r;
r -> left = l;
delete Min;
Min = l;
Consolidate();
}
template <class T>
void Fibonacci_Heap<T>::Consolidate() {
//cout<<"consolidate"<
vector<Node*>root_list;
vector<Node*>A;
Node* cur = Min->right;
root_list.push_back(Min);
while(cur != Min)
{
while(cur->degree+1 > A.size())
{
A.push_back(nullptr); }
root_list.push_back(cur);
cur = cur->right;
}
for(int i = 0;i < root_list.size();i++)
{
Node* x = root_list[i];
int d = x->degree;
while(d + 10>A.size()){
A.push_back(nullptr);}
//cout<
//cout<
while(A[d] != nullptr)
{
Node* y = A[d];
if(x->key > y->key)
{
Node* swap = x;
x = y;
y = swap;
}
Link(y,x);
A[d] = nullptr;
d++;
}
while(d+5 > A.size()){
A.push_back(nullptr);}
A[d] = x;
}
Min = nullptr;
for(int j = 0;j < A.size();j++)
{
if(A[j]!=nullptr){
if(Min == nullptr)
{
Min = A[j];
Min->left = Min;Min->right = Min;
}
else
{
Node* le = Min->left;
le -> right = A[j];
Min -> left = A[j];
A[j]->right = Min;
A[j]->left = le;
if(Min->key > A[j]->key)Min = A[j];
}
}
}
}
template <class T>
void Fibonacci_Heap<T>::Link(Node *y, Node *x) {
//remove y from the root list
Node* l = y->left;
Node* r = y->right;
l->right = r;
r->left = l;
//make y a child of x, incrementing x.degree
x->degree++;
y->p = x;
y->mark = false;
if(x->child != nullptr){
Node* t = x->child->right;
t->left = y;
y->left = x->child;
y->right = t;
x->child->right = y;
}else
{
x->child = y;
y->left = y;y->right = y;
}
}
template<class T>
void Fibonacci_Heap<T>::Decrease_Key(int id, T k) {
if(id>=mp.size()||mp[id] == nullptr){
cout<<"The target doesn't exit"<<endl;
return;
}
if(mp[id]->key < k){
cout<<"The key of target is higher than you thought"<<endl;return;
}
Node* target = mp[id];
target->key = k;
Node* fa = target->p;
if(fa!=nullptr && target->key < fa->key)
{
Cut(target,fa);
Cascading_Cut(fa);
}
if(target->key < Min->key)
Min = target;
}
template <class T>
void Fibonacci_Heap<T>::Cut(Node *x, Node *y) {
y->degree--;
//remove x from child list of y
Node* tmp = x;
if(y->degree == 0){
y->child = nullptr;}
else{
if(y->child == x)
y->child = x->right;
Node* left = x->left;
Node* right = x->right;
right->left = left;
left->right = right;
}
//add x to the root list
x->p = nullptr;
x->mark = false;
Node* temp = Min->left;
temp->right = x;
Min->left = x;
x->left = temp;
x->right = Min;
}
template <class T>
void Fibonacci_Heap<T>::Cascading_Cut(Node *y) {
Node* z = y->p;
if(z!=nullptr){
if(y->mark == false)
{
y->mark = true;
}else
{
Cut(y,z);
Cascading_Cut(z);
}
}
}