哈密顿回路

图类:

#include<iomanip> 
#include<limits>
#include<time.h>
#include<iostream>
#include<fstream>
using namespace std;

template<class T,class E>  //T为顶点的数据类型,E为图中边的权值的数据类型
class Graph
{
private:
	static const int DefaultVertices=10; //默认最大顶点数

	int maxVertices; //图中最大顶点数
	int numVertices;//图中当前顶点数
	int numEdges;   //图中当前边数
	int getVertexPos(T vertex);//给出顶点vertex在图中的位置
    E **matrix;//邻接矩阵
	T *VerticesList;//顶点表

public:
	 E maxWeight; //代表无穷大的值
	Graph(int sz=DefaultVertices);//根据用户的要求,创建SZ大小的基于邻接矩阵的图
	~Graph( );//析构函数
	int NumberOfVertices(){return maxVertices;}//返回最大顶点数
	int NumberOfEdges(){return numEdges;}//返回当前边数
	T getValue(int i);               //取顶点i的值,i不合理返回0
	E getWeight(int v1,int v2);     //取边(v1,v2)上的权值
	int getFirstNeighbor(int v);//取顶点v的第一个邻接顶点
	int getNextNeighbor(int v,int w);//取顶点v的邻接顶点W的下一个邻接顶点
	bool insertVertice(const T &vertex);//插入顶点

	int Init(istream &in);//根据用户输入,获得图的邻接矩阵
	int RandInit();//随机初始化图(无向图)
	int output(ostream &out); //输出图的矩阵
	
};


template<class T,class E>
Graph<T,E>::Graph(int sz=DefaultVertices) //根据用户的要求,创建SZ大小的基于邻接矩阵的图
{
	maxWeight=std::numeric_limits<E>::max();
	maxVertices=sz;
	matrix=new E *[sz];
	for(int i=0;i<sz;i++)
	{
		matrix[i]=new E[sz];
		for(int j=0;j<sz;j++)
		{
			matrix[i][j]=maxWeight;
		}
	}
	VerticesList=new T[sz];
}
template<class T,class E>
Graph<T,E>::~Graph()
{
	for(int i=0;i<maxVertices;i++)
	{
		delete matrix[i];
	}

	delete VerticesList;
}
template<class T,class E>
T Graph<T,E>::getValue(int i)//取顶点i的值,i不合理返回0
{
	if(i>=0&&i<=numVertices)
	{
		return VerticesList[i];
	}
	
	return NULL;
}
template<class T,class E>
E Graph<T,E>::getWeight(int v1,int v2)//取边(v1,v2)上的权值
{
	if(v1>=0&&v1<maxVertices&&v2>=0&&v2<maxVertices)
	{
		return matrix[v1][v2];
	}
	return 0;
}
template<class T,class E>
int Graph<T,E>::getFirstNeighbor(int v)//取顶点v的第一个邻接顶点
{
	if(!(v>=0&&v<maxVertices))   //v不合法
		return -1;

	for(int col=0;col<maxVertices;col++)
	{
		if(matrix[v][col]!=maxWeight)
		{
			return col;          //找到
		}
	}
	return -1;                   //未找到

}
template<class T,class E>
int Graph<T,E>::getNextNeighbor(int v,int w)//取顶点v的邻接顶点W的下一个邻接顶点
{
	if(!(v>=0&&v<maxVertices)||!(w>=0&&w<maxVertices) )  //v或w不合法
		return -1;
	for(int col=w+1;col<maxVertices;col++)
	{
		if(matrix[v][col]!=maxWeight)
		{
			return col;         //找到
		}
	}
	return -1;//未找到
}
 template<class T,class E>
int Graph<T,E>::Init(istream &fin)  //根据用户输入,获得图的邻接矩阵
{
	int v1,v2;
	E edge;
	while(fin>>v1>>v2>>edge)
	{
		if(v1>=0&&v1<maxVertices&&v2>=0&&v2<maxVertices)
	    { 
		   matrix[v1][v2]=edge;
		   matrix[v2][v1]=edge;
		   numVertices++;
	    }
		if(edge==maxWeight)    //当输入边值为无穷大时停止输入
		{
			break;
		}
	}
	return 1;
}

template<class T,class E>
int Graph<T,E>::RandInit()//随机初始化图(无向图)
{
	for(int i=0;i<maxVertices;i++)
	{
		for(int j=0;j<maxVertices;j++)
		{
			matrix[i][j]=maxWeight;
		}
	}
	int rnd=maxVertices*(maxVertices-1)/2;
	int numOfEdge=rand()/RAND_MAX*rnd/4+3*rnd/4;
	int count=numOfEdge;
	int v1,v2;
	while(count)
	{
		v1=rand()%maxVertices;
		v2=rand()%maxVertices;
		if(v1!=v2&&matrix[v1][v2]==maxWeight)
		{
			matrix[v2][v1]=matrix[v1][v2]=rand()%100;
			count--;
		}
	}
	return 1;

}

template<class T,class E>
int Graph<T,E>::output(ostream &out) //输出图的矩阵
{
	for(int i=0;i<maxVertices;i++)
	{
		for(int j=0;j<maxVertices;j++)
		{
			out<<setw(15)<<matrix[i][j]<<"   ";
		}
		out<<endl;
	}
	return 1;
}



随机生成并哈密顿回路求解:

// Graph.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include"Graph.h"


#include<iostream>
#include<fstream>
#include<stack>
#include<queue>
#include<limits>
using namespace std;

template<class T,class E>
int sb(int start,Graph<T,E> &myGraph,ostream & fout)//simple backtracking 算法解决图的最小哈密顿回路问题  v为回路的起点和终点
{
	E minDistance=std::numeric_limits<E>::max();
	stack<int> myStack;
	myStack.push(start);
	

	int numVertices=myGraph.NumberOfVertices();
	bool *visited=new bool[numVertices];
	memset(visited,false,numVertices);

	int v;
	int w=-1;
	while(!myStack.empty()) //栈不为空
	{
		v=myStack.top();
		visited[v]=true;

		if(w==-1)
		{
			w=myGraph.getFirstNeighbor(v);
		}
		else
		{
			w=myGraph.getNextNeighbor(v,w);
		}
		for(;w!=-1&&visited[w]==true;w=myGraph.getNextNeighbor(v,w))
		{

		}

		if(w==-1)  //未找到可行的下一个顶点
		{
			myStack.pop();  //回溯
			w=v;
			visited[v]=false;
		}
		else      //找到可行的下一个顶点
		{
			myStack.push(w);  //放入栈中
			
			if(myStack.size()==numVertices)//走过所有的顶点
			{
				     if(myGraph.getWeight(start,w)==std::numeric_limits<E>::max()) //判断最后一个顶点有没有回到起点的边
					 {
						 myStack.pop();
						 visited[w]=false;
					 }
					 else  //成功找到回路
					 {
						 //输出回路 并记录下回路的长度
						 stack<int> temp;
						 while(!myStack.empty())
						 {
							 int n=myStack.top();
							 temp.push(n);
							 myStack.pop();
						 }
						 
						 fout<<"哈密顿回路 : ";
						 E distance=0;
						  int n=temp.top();
						  myStack.push(n);
						  temp.pop();
						  int last=n;
						   fout<<n<<"--";
						 while(!temp.empty())
						 {
							 n=temp.top();
							 myStack.push(n);
							 temp.pop();
							 distance+=myGraph.getWeight(last,n);
							 last=n;
							 fout<<n<<"--";
						 }
						 fout<<start<<"--"<<endl;
						 distance+=myGraph.getWeight(last,start);
						 fout<<"总长度为:"<<distance<<endl;
						 //记录最短长度
						 if(minDistance>distance)
						 {
							 minDistance=distance;
						 }

						 //
						  myStack.pop();
						  visited[w]=false;
					 }
					 
			}
			else
			{
				w=-1;
			}
			
		}
		 
	}
	fout<<"最短哈密顿回路的长度为:"<<minDistance<<endl;
	return 1;
}

//分支限界法求解最短哈密顿回路问题
template<class E>
struct NODE
{
	int dep;        //表示该结点在搜索树的第几层
	int *vertices;  //该节点力包含的各个顶点
	E length;       //从根到当前结点已经走过的路径长度
	NODE(int depth)
	{
		dep=depth;
		vertices=new int[dep];
	};
	void cpy(int *&des)
	{
		for(int i=0;i<dep;i++)
		{
			des[i]=vertices[i];
		}
	}
	bool find(int v)
	{
		for(int i=0;i<dep;i++)
		{
			if(vertices[i]==v)
				return true;
		}
		return false;
	}

};
template<class T,class E>
int bb(int start,Graph<T,E> & myGraph,ostream & fout)
{
	stack<NODE<E>> myStack;  //队列
	 
	E minDistance=std::numeric_limits<E>::max();

	int s=myGraph.getFirstNeighbor(start);
	for(s=myGraph.getNextNeighbor(start,s);s!=-1;s=myGraph.getNextNeighbor(start,s))
	{
		NODE<E> n(2);
		n.vertices[0]=start;n.vertices[1]=s;
		n.length=myGraph.getWeight(start,s);
		myStack.push(n);
	}
	while(!myStack.empty())   //队列不为空
	{
		NODE<E> n=myStack.top();
		myStack.pop();
		int v=n.vertices[n.dep-1];
		if(n.dep+1==myGraph.NumberOfVertices())//到了最后一层 判断是不是哈密顿回路
		{
			int w;
			for( w=myGraph.getFirstNeighbor(v);w!=-1;w=myGraph.getNextNeighbor(v,w))
		    {
				if( n.find(w)==false)
				break;
			}
			if(w!=-1)  
			{
				if(myGraph.getWeight(w,start)<std::numeric_limits<E>::max())
				{
					//形成回路
					fout<<"哈密顿回路为:";
					for(int i=0;i<n.dep;i++)
					{
						fout<<n.vertices[i]<<"   ";
					}
					fout<<w<<"   "<<start<<endl;
					E tempDistance=n.length+myGraph.getWeight(v,w)+myGraph.getWeight(w,start);
					fout<<"总长度为:  "<<tempDistance<<endl;
					if(minDistance>tempDistance)
					{
						minDistance=tempDistance;
					}
				}
			}
		}
		
		for(int w=myGraph.getFirstNeighbor(v);w!=-1;w=myGraph.getNextNeighbor(v,w))
		{
			if(n.find(w)==false)
			{

			NODE<E> ne(n.dep+1);
			ne.length=n.length+myGraph.getWeight(v,w);
			if(ne.length<minDistance)
			{
				n.cpy(ne.vertices);
				ne.vertices[ne.dep-1]=w;
				myStack.push(ne);
			}

			}
		}
	}
	

	fout<<"最短长度为  "<<minDistance<<endl;
	return minDistance;
}

int _tmain(int argc, _TCHAR* argv[])
{
	Graph<char,int> myGraph(10);
	//ifstream fin("input.txt");
	//myGraph.Init(fin);
	myGraph.RandInit();//随机初始化图

	ofstream fout("outputsb.txt");
	
	//sb(0,myGraph,fout);

	ofstream fout1("outputbb.txt");
	bb(0,myGraph,fout1);
	system("pause");
	return 0;
}




 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值