斐波那契堆

以下是实现的程序

肯定可以再优化的。。

//#include <vld.h>
#include <iostream>
#include <stdio.h>
#include <vector>

using namespace std;

class Node
{
public:
	int m_key;
	Node *m_parent;
	Node *m_left;
	Node *m_right;
	Node *m_child;//只要指向一个孩子结点
	int m_degree;//孩子数量
	bool m_mark;

	Node(int key):m_key(key),m_degree(0),m_parent(NULL),m_child(NULL),m_right(this),m_left(this),m_mark(false)
	{
		//cout<<this<<endl;
	}
	~Node()//node只管把自己所有的孩子删除,不管兄弟;如果是普通的树,也是把自己的孩子删除,不管兄弟结点
	{
		if(m_child!=NULL)
		{
			Node *child = m_child;
			Node *rchild = child->m_right;
			while (rchild!=m_child)//左右指针肯定不会为null
			{
				Node *rrchild = rchild->m_right;
				delete rchild;
				rchild = rrchild;
			}
			delete m_child;
			m_child = NULL;
		}
		

	}
};

class FibonacciHeap
{
public:
	//vector<Node *> m_heap;//only need m_min as head
	Node *m_min;
	int m_numNode;
	FibonacciHeap():m_min(NULL),m_numNode(0)
	{

	}
	Node* Insert(int key)
	{
		Node *nd = new Node(key);
		++m_numNode;
		Insert(nd);
		return nd;
	}

	void Insert(Node *nd)//将结点nd插入到root list中
	{
		
		//cout<<nd<<endl;
		if(m_min==NULL)
		{
			m_min = nd;
			nd->m_right = nd;
			nd->m_left = nd;
		}
		else
		{
			Node *tmpRight = m_min->m_right;
			m_min->m_right = nd;
			nd->m_right = tmpRight;

			tmpRight->m_left=nd;
			nd->m_left = m_min;

			if(nd->m_key<m_min->m_key)
				m_min = nd;
		}
	}

	void Union(FibonacciHeap &f)
	{
		Node *head = f.m_min;
		Node *right = head->m_right;
		while(right!=head)
		{
			Insert(right);
			right->m_parent = NULL;
			right = right->m_right;
		}
		Insert(head);
		head->m_parent = NULL;

		if(m_min->m_key>head->m_key)
			m_min = head;

		f.m_min = NULL;//删除f
	}

	Node *ExtractMin()//要在外面删除min
	{
		Node *minNode = m_min;
		if (minNode!=NULL)
		{
			Node *child = minNode->m_child;
			if(child!=NULL)
			{

				/*Node *right = child->m_right;
				while (right!=child)
				{
					right->m_parent = NULL;
					Node *t = right->m_right;
					Insert(right);
					right = t;
				}
				child->m_parent = NULL;
				Insert(child);*/

				/*Node *tchild = child;
				vector<Node *> children;
				while (tchild!=NULL)
				{
					tchild->m_parent = NULL;
					children.push_back(tchild);
					tchild = (tchild->m_right!=child) ?tchild->m_right :NULL;
				}
				for (int i=0;i<children.size();++i)
				{
					Insert(children[i]);
				}*/
				Node *tchild = child;
				while (tchild!=NULL)
				{
					Node * next = tchild->m_right;
					tchild->m_parent = NULL;
					Insert(tchild);
					tchild = (next!=child) ?next:NULL;
				}

			}
			if(minNode == minNode->m_right)
				m_min = NULL;
			else
			{
				Node *left = minNode->m_left;
				Node *right = minNode->m_right;

				left->m_right = right;
				right->m_left = left;

				m_min = right;//随便找一个点作为min,主要是确定Head。因为min另一个作用是head
				Consolidate();
			}

			minNode->m_child = NULL;
			minNode->m_right = minNode;
			minNode->m_left = minNode;
			--m_numNode;

		}
		
		

		return minNode;
	}

	void Consolidate()//;用数组A来检查root list上重复degree的结点;因为此时的minNode是上步中随意指定的,所以不能拿minNode 作为锚点
	{
		vector<Node *> A(m_numNode,NULL);
		Node *right = m_min;
		if(right->m_right==right)//如果root list只有一个结点则不用处理
			return;
		vector<Node *> rootList;
		rootList.push_back(m_min);
		

		for(right = m_min->m_right;right!=m_min;right = right->m_right)
			rootList.push_back(right);
		m_min = NULL;//将原root list打散


		for(int i=0;i<rootList.size();++i)
		{
			Node *curr = rootList[i];
			
			int d = curr->m_degree;
			while (A[d]!=NULL)//有重复
			{
				Node *y = A[d];
				if (curr->m_key>y->m_key)//要让curr所指向的节点是头
				{
					Node *t = y;
					y = curr;
					curr = t;
				}
				Link(y,curr);
				A[d] = NULL;//curr的度数为degree+1,所以degree暂时没有对应的根
				++d;

			}
			A[d] = curr;
		}
		for (int i=0;i<A.size();++i)
		{
			if(A[i]!=NULL)
				Insert(A[i]);
		}
		
	}

	void Link(Node *child,Node *parent)//child 属于root list
	{
		Node *right = child->m_right;
		Node *left = child->m_left;

		right ->m_left = left;
		left->m_right = right;

		Node *mchild = parent->m_child;
		if(mchild==NULL)
		{
			parent->m_child = child;
			child->m_parent = parent;
			child->m_right = child;
			child->m_left = child;

		}
		else
		{
			Node *rightChild = mchild->m_right;
			mchild->m_right = child;
			child->m_right = rightChild;

			rightChild->m_left = child;
			child->m_left = mchild;
		}

		child->m_mark = false;
		++parent->m_degree;
	}
	
	void DecreaseKey(Node *x,int key)
	{
		if(key >x->m_key)
		{
			cerr<<"new key is greater than original\n";
			return;
		}

		x->m_key = key;
		Node *y = x->m_parent;

		if (y!=NULL && x->m_key <y->m_key)
		{
			Cut(x,y);
			CascadingCut(y);
		}
	}
	void CascadingCut(Node *y)
	{
		Node* parent;
		while ((parent = y->m_parent)!=NULL)
		{
			if(y->m_mark == false)
			{
				y->m_mark = true;
				break;
			}

			Cut(y,parent);
			y = parent;
		}
	}
	void Cut(Node *x,Node *y)//x是y的孩子,将x上提为root 
	{
		if(x->m_right == x)
		{
			y->m_child = NULL;
		}
		else
		{
			Node *left = x->m_left;
			Node *right = x->m_right;
			y->m_child = right;

			left->m_right = right;
			right->m_left = left;
		}

		x->m_parent = NULL;
		x->m_mark = false;
		Insert(x);
	}
	
	void print()
	{
		Node *minNode = m_min;
		while (minNode!=NULL)
		{
			print(0,minNode);
			minNode = (minNode->m_right!=m_min)?minNode->m_right:NULL;
		}
	}
	
	void print(int level,Node *nd)
	{
		for (int i=0;i<level;++i)
		{
			cout<<"-";
		}
		cout<<nd->m_key<<endl;
		Node *right = nd->m_child;
		while (right!=NULL)
		{
			print(level+1,right);
			right = (right->m_right!=nd->m_child) ?right->m_right:NULL;
		}
	}

	~FibonacciHeap()
	{
		if(m_min!=NULL)
		{
			Node *right=m_min->m_right;
			while (right!=m_min)
			{
				Node *rright = right->m_right;
				delete right;
				right = rright;
			}
			delete m_min;
		}
	}

};

int main()
{

	FibonacciHeap f;
	//f.Insert(5);
	int a[17] = {1,5,2,3,7,8,0,12,10,11,9,15,17,4,18,16,13};
	Node *n5,*n10,*n16;
	for (int i=0;i<17;++i)
	{
		Node *t = f.Insert(a[i]);
		if(a[i] == 5) 
			n5 = t;
		if(a[i] == 10)
			n10 = t;
		if(a[i]==16)
			n16 = t;
	}
	/*Node *t = f.ExtractMin();
	cout<<t->m_key<<endl;
	delete t;*/

	//Node *t = f.ExtractMin();
	//while(t!=NULL)
	//{
	//	cout<<"min:"<<t->m_key<<"\n";
	//	
	//	delete t;
	//	//f.print();

	//	t = f.ExtractMin();
	//}
	//cout<<endl;
	f.print();
	f.DecreaseKey(n5,1);
	cout<<endl;
	f.print();

	f.DecreaseKey(n10,5);
	f.print();
	cout<<endl;

	f.DecreaseKey(n16,7);
	f.print();
	cout<<endl;
	
	Node *t = f.ExtractMin();
	while(t!=NULL)
	{
		cout<<"min:"<<t->m_key<<"\n";
		
		delete t;
		//f.print();

		t = f.ExtractMin();
	}

	return 0;
}


貌似有个黄金度数什么的可以优化

要用prim检测下


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值