用C++写的图的算法。

1.用到了设计模式里的template method,首先定义了一个图的虚基类GRAPH,在里面定义了一些虚方法的接口,然后在GRAPH里用这些虚方法实现了图的各个算法(BFS,DFS,Prim,Kruskal,Dijkstra,Floyd)。然后在GRAPH的子类AdjMatrixGRAPH和AdjListGRAPH里分别用邻接表和邻接矩阵表示图,并实现GRAPH中定义的接口,这样图的算法与图的表示进行了分离,并且后面再加别种图的表示只需要增加新的子类。

2.其中的图的算法跟各大教科书没任何区别,,里面有很多可以优化或者让代码更漂亮的地方。

3.为了把各算法的结果与结果的显示分离,在各算法中都传入了引用作为参数。

#include <iostream>
#include <vector>
#include <deque>
#include <algorithm>

using namespace std;



struct Edge//边
{
	int v,w;//

	Edge( int v = -1, int w = -1 ):
		v( v ), w( w ){}

	void SetEdge( int vx, int wx )
	{
		v = vx;
		w = wx;
	}

	virtual void SetWeight( int wt )
	{
	}

	virtual int GetWeight() const
	{
		return 1;//默认权值为1
	}
};

struct WEdge:public Edge//加权边
{
	int weight;

	WEdge( int v = -1, int w = -1, int wt = 1 ):
		Edge( v, w ),weight( wt ){}

	virtual void SetWeight( int wt )
	{
		weight = wt;
	}

	virtual int GetWeight() const
	{
		return weight;
	}
};

bool LessWedge( const WEdge  & we1, const WEdge & we2 )
{
	return we1.GetWeight() < we2.GetWeight();
}

class GRAPH
{
private:

	void DFSearch( vector<bool> & vec, int n, vector< int > &Rslt )//
	{
		//cout << n <<" ";
		Rslt.push_back( n );
		vec[n] = true;

		for( int i = 0; i < VCnt; i++ )
		{
			if( edge( n, i ) && ( !vec[i] ) )
			{
				DFSearch( vec, i, Rslt );
			}
		}
	}

	void GenEVex( vector<WEdge> & vec )//生成边集数组
	{
		for( int v = 0; v < VCnt; v++ )
		{
			for( int w = v + 1; w < VCnt; w++ )
			{
				if( edge(  v, w ) )
				{
					WEdge eg( v , w, getweight( v, w ) );
					vec.push_back( eg  );
				}
			}
		}
	}

	//从一条边都一个顶点出发查找可达的最深节点
	int find( const vector<int> &vec, int m )
	{
		while( vec[m] != 0 )
		{
			m = vec[m];
		}
		return m;
	}

	//参数合法性判断
	bool IsLegal( int v )
	{
		return ( ( v > 0 ) && ( v < ( V() - 1 ) ) ) ? true:false;
	}

	bool IsLegal( vector< vector<int> > & vec )
	{
		if( vec.size() != V() )
		{
			return false;
		}

		for( vector< vector< int > >::iterator it = vec.begin(); it != vec.end(); it++ )
		{
			if( it->size() != V() )
			{
				return false;
			}
		}
		return true;
	}


	void DijkstraShortPath( int v0, vector<int> & p, vector<int> & pathlen )
	{
		vector<int> final;

		for( int i = 0; i < VCnt; i++ )
		{
			p.push_back( v0 );
			pathlen.push_back( INT_MAX );

			final.push_back( 0 );
		}
		
		pathlen[v0] = 0;
		final[v0] = 1;

		for( int i = 0; i < VCnt; i++ )
		{
			if( edge( v0 ,i ) )//v0与i之间有边,则把边的权值初始化pathlen
			{
				pathlen[i] = getweight( v0, i );
			}
		}

		//初始化结束,开始算法主体
		for( int v = 1; v < VCnt; v++ )
		{
			int min = INT_MAX;
			int k = 0;
			for( int w = 0; w < VCnt; w++ )
			{
				if( ( final[w] != 1 ) && ( min > pathlen[w] ) )
				{
					min = pathlen[w];
					k = w;
				}
			}
			final[k] = 1;
			int wt = 0;
			for( int w = 0; w < VCnt; w++ )
			{
				wt = getweight( k ,w );
				if(  ( final[w] != 1 ) &&  edge( k ,w ) &&( pathlen[w] > pathlen[k] + wt ) )
				{
					pathlen[w] = pathlen[k] + wt;
					p[w] = k;
				}
			}
		}
	}
protected:
	int VCnt;
	int ECnt;
	bool digraph;

public:

	GRAPH( int V, bool dig = false ):
	  VCnt( V ),ECnt( 0 ),digraph( dig ){}

	int V()
	{
		return VCnt;
	}

	int E()
	{
		return ECnt;
	}

	bool Directed()
	{
		return digraph;
	}

	virtual void insert( const Edge &e ) = 0;
	virtual void remove( const Edge & e ) = 0;
	virtual void setweight( int v, int w, int weight ) = 0;
	void setweight( const Edge & e, int weight )
	{
		return setweight( e.v, e.w, weight );
	}
	virtual int getweight( int v, int w ) = 0;
	virtual bool edge( int v, int w ) = 0;

	void BFS( vector< int > & Rslt )//Breadth-First-Search
	{
		vector<bool> visited;
		for( int i =0; i < VCnt; i++ )
		{
			visited.push_back( false );
		}
		deque<int> queue;

		for( int i = 0; i < VCnt; i++ )
		{
			if( !visited[i] )
			{
				queue.push_back( i );
				visited[i] = true;
			}
			while( !queue.empty() )
			{
				int node = queue.front();
				queue.pop_front();
				Rslt.push_back( node );

				for( int j = 0; j < VCnt; j++ )
				{
					if( edge( node, j ) && ( !visited[j] ) )
					{
						queue.push_back( j );
						visited[j] = true;
					}
				}
			}
		}
	}

	void DFS( vector< int > & Rslt )//Depth-First-Search
	{
		vector<bool> visited;
		for( int i = 0; i < VCnt; i++ )
		{
			visited.push_back( false );
		}

		for( int i = 0; i < VCnt; i++ )
		{
			if( ! visited[i] )
			{
				DFSearch( visited, i, Rslt );
			}
		}
	}

	void Prim( vector< Edge > & Rslt )
	{
		if( Directed() )
		{
			return;//只针对无向图
		}

		vector<int> vex;
		vector<int> lowcost;

		for( int i = 0; i < VCnt; i++ )
		{
			vex.push_back( 0 );//先放入第0个节点
			lowcost.push_back( INT_MAX );
		}

		lowcost[0] = 0;

		for( int i = 1; i< VCnt; i++ )
		{
			if( edge( 0, i ) )
			{
				lowcost[i] = getweight( 0, i );
			}
		}

		Edge e;
		for( int i = 1; i < VCnt; i++ )
		{
			int min = INT_MAX;
			int k = 0;
			for( int j = 1; j < VCnt; j++ )
			{
				if( ( lowcost[j] != 0 ) && ( lowcost[j] < min ) )
				{
					min = lowcost[j];
					k = j;
				}
			}

			lowcost[k] = 0;

			e.SetEdge( vex[k], k );
			Rslt.push_back( e );

			for( int i = 1; i < VCnt; i++ )
			{
				int wt = getweight( k ,i );
				if( ( lowcost[i] != 0 ) && edge( k , i ) &&( lowcost[i] > wt ) )
				{
					lowcost[i] = wt;
					vex[i] = k;
				}
			}
		}
	}

	void Kruskal( vector< Edge > &Rslt )
	{
		if( Directed() )
		{
			return;//只针对无向图
		}

		//此处把生成边集数组的过程提取重构成一个成员函数
		vector<WEdge> we;
		GenEVex( we );

		sort( we.begin(), we.end(), LessWedge );//把边按权值从小到大排序

		vector<int> evex;
		for( int v = 0; v < VCnt; v++ )
		{
			evex.push_back( 0 );
		}

		for( vector<WEdge>::iterator it = we.begin(); it != we.end(); it++ )
		{
			int m = find( evex, it->v );
			int n = find( evex, it->w );
			if( m != n )
			{
				Rslt.push_back( *it );
				evex[m] = n;
			}
		}

	}

	//path和pathlen都必须是V*V的二维数组
	void Dijkstra( vector< vector< int > > &path, vector< vector< int > > &pathlen )
	{
		if( ! IsLegal( path ) || ! IsLegal( pathlen ) )
		{
			cout << "Please input the right para!" << endl;
			return;
		}

		for( int v = 0; v < VCnt; v++ )
		{
			DijkstraShortPath( v, path[v], pathlen[v] );
		}
	}

	//path和pathlen都是V*V的二维数组
	void Floyd( vector< vector< int > > &path, vector< vector< int > > &pathlen )
	{
		if( ! IsLegal( path ) || ! IsLegal( pathlen ) )
		{
			cout << "Please input the right para!" << endl;
			return;
		}
		
		for( int v = 0; v < VCnt; v++ )
		{
			path[v].assign( VCnt, 0 );
			pathlen[v].assign( VCnt, 0 );
			for( int w = 0; w < VCnt; w++ )
			{
				path[v][w] = w;
				pathlen[v][w] = getweight( v, w );
			}
		}

		for( int k = 0; k < VCnt; k++ )
		{
			for( int v = 0; v  < VCnt; v++ )
			{
				for( int w = 0; w < VCnt; w++ )
				{
					if(  ( pathlen[v][w] > pathlen[v][k] + pathlen[k][w] ) && ( pathlen[v][k] != INT_MAX ) &&( pathlen[k][w] != INT_MAX ) )
					{
						pathlen[v][w] = pathlen[v][k] + pathlen[k][w];
						path[v][w] = path[v][k];
					}
				}
			}
		}
	}

};

class AdjMatrixGRAPH:public GRAPH
{
private:
	vector< vector<int> > adj;

public:

	AdjMatrixGRAPH( int V, bool dig = false ):
		GRAPH( V, dig ),adj(V)
		{
			for( int i = 0; i < V; i++  )
			{
				adj[i].assign( V, INT_MAX );
				adj[i][i] = 0;
			}
		}

	void insert( const Edge &e )
	{
		if( !edge( e.v, e.w ) )
		{
			ECnt++;//add an edge
		
			adj[e.v][e.w] = e.GetWeight();

			if( !Directed() )
			{
				adj[e.w][e.v] = e.GetWeight();
			}
		}
		else
		{
			cout << "edge " << e.v << "-" << e.w << " already exist" << endl;
			return;
		}
	}


	void remove( const Edge & e )
	{
		if( adj[e.v][e.w] != INT_MAX )
		{
			ECnt--;
		}
		adj[e.v][e.w] = INT_MAX;

		if( !Directed() )
		{
			adj[e.w][e.v] = INT_MAX;
		}
	}

	void setweight( int v, int w, int weight )
	{
		if( edge( v, w ) )
		{
			adj[v][w] = weight;

			if( !Directed() )//无向图
			{
				adj[w][v] = weight;
			}
		}
		else
		{
			cout << "Add weight error,edge "<< v <<","<< w <<" not exist" << endl;
			return;
		}
	}

	int getweight( int v, int w )
	{
		return adj[v][w];
	}

	bool edge( int v, int w )
	{
		return adj[v][w] == INT_MAX?false:true;
	}
};

struct node
{
	int v;
	int weight;
	node * next;

	node( int x = 0, node * t = 0, int wt = 0 ):
		v( x ),next( t ),weight( wt ){}
};

class AdjListGRAPH:public GRAPH
{
private:
	vector< node * > adj;

	node * get( int v, int w )//查找边v-w所在节点
	{
		node * t = adj[v];
		while( t != NULL )
		{
			if( t->v == w )
			{
				return t;
			}
			else
			{
				t = t->next;
			}
		}

		return NULL;
	}

public:
	AdjListGRAPH( int V, bool dig = false ):
		GRAPH( V, dig )
		{
			adj.assign( V, ( node * )NULL );
		}

	void insert(const Edge &e )
	{
		if( !edge( e.v, e.w ) )
		{
			node * t = new node;
			t->v = e.w;
			t->weight = e.GetWeight();
			t->next = NULL;

			if( adj[e.v] == NULL )
			{
				adj[e.v] = t;
			}
			else
			{
				t->next = adj[e.v];
				adj[e.v] = t;
			}

			ECnt++;

			if( !Directed() )
			{
				node * t = new node;
				t->v = e.v;
				t->weight = e.GetWeight();
				t->next = NULL;

				if( adj[e.w] == NULL )
				{
					adj[e.w] = t;
				}
				else
				{
					t->next = adj[e.w];
					adj[e.w] = t;
				}
			}
		}
		else
		{
			cout << "edge "<< e.v << "-" << e.w << "already exists!" << endl;
		}
	}

	void remove( const Edge & e )
	{
		node * t = adj[e.v];
		node * prev = t;
		while( t != NULL )
		{
			if( t->v == e.w )
			{
				prev->next = t->next;
				delete t;

				ECnt--;
			}
			else
			{
				prev = t;
				t = t->next;
			}
		}

		if( !Directed() )
		{
			node * t = adj[e.w];
			node * prev = t;
			while( t != NULL )
			{
				if( t->v == e.v )
				{
					prev->next = t->next;
					delete t;
				}
				else
				{
					prev = t;
					t = t->next;
				}
			}
		}
	}

	void setweight( int v, int w, int weight )
	{
		node * t = get( v, w );
		if( t != NULL )
		{
			t->weight = weight;
		}
		else
		{
			cout << "edge " << v << "-" << w << " not exist!" << endl;
		}

		if( !Directed() )
		{
			t = get( w, v );
			if( t != NULL )
			{
				t->weight = weight;
			}
		}
	}

	int getweight( int v, int w )
	{
		if( v == w )//同一个点,距离为0
		{
			return 0;
		}
		node * t = get( v, w );
		if( t != NULL )
		{
			return t->weight;
		}
		return INT_MAX;
	}

	bool edge( int v, int w )
	{
		node * t = get( v, w );
		if( t != NULL )
		{
			return true;
		}
		return false;
	}
};



int main()
{

	//GRAPH *g = new AdjMatrixGRAPH( 9 );
	GRAPH *g = new AdjListGRAPH( 9 );


	Edge e( 0,1 );
	g->insert( e );

	e.SetEdge( 1,2 );
	g->insert( e );

	e.SetEdge(2,3);
	g->insert( e );

	e.SetEdge(3,4);
	g->insert( e );

	e.SetEdge(4,5);
	g->insert( e );

	e.SetEdge(5,0);
	g->insert( e );

	e.SetEdge(1,8);
	g->insert( e );

	e.SetEdge(2,8);
	g->insert( e );

	e.SetEdge(1,6);
	g->insert( e );

	e.SetEdge(3,8);
	g->insert( e );

	e.SetEdge(3,6);
	g->insert( e );

	e.SetEdge(3,7);
	g->insert( e );

	e.SetEdge(4,7);
	g->insert( e );

	e.SetEdge(5,6);
	g->insert( e );

	e.SetEdge(6,7);
	g->insert( e );
	

	vector< int > Rslt;
	//g->BFS( Rslt );
	//g->DFS( Rslt );



	g->setweight( 0,1,10 );
	g->setweight( 0,5,11 );
	g->setweight( 1,2,18 );
	g->setweight( 1,6,16 );
	g->setweight( 1,8,12 );
	g->setweight( 2,3,22 );
	g->setweight( 2,8,8 );
	g->setweight( 3,4,20 );
	g->setweight( 3,6,24 );
	g->setweight( 3,7,16 );
	g->setweight( 3,8,21 );
	g->setweight( 4,5,26 );
	g->setweight( 4,7,7 );
	g->setweight( 5,6,17 );
	g->setweight( 6,7,19 );


	vector< Edge > ERslt;
	g->Prim( ERslt );
	g->Kruskal( ERslt );

/*
	WEdge e( 0,1,1 );
	g->insert( e );

	e.SetEdge( 0,2 );
	e.SetWeight( 5 );
	g->insert( e );

	e.SetEdge( 1,2 );
	e.SetWeight( 3 );
	g->insert( e );

	e.SetEdge( 1,3 );
	e.SetWeight( 7 );
	g->insert( e );

	e.SetEdge( 1,4 );
	e.SetWeight( 5 );
	g->insert( e );

	e.SetEdge(2,4);
	e.SetWeight( 1 );
	g->insert( e );

	e.SetEdge(2,5);
	e.SetWeight( 7 );
	g->insert( e );

	e.SetEdge(3,4);
	e.SetWeight( 2 );
	g->insert( e );

	e.SetEdge(3,6);
	e.SetWeight( 3 );
	g->insert( e );

	e.SetEdge(4,5);
	e.SetWeight( 3 );
	g->insert( e );

	e.SetEdge(4,6);
	e.SetWeight( 6 );
	g->insert( e );

	e.SetEdge(4,7);
	e.SetWeight( 9 );
	g->insert( e );

	e.SetEdge(5,7);
	e.SetWeight( 5 );
	g->insert( e );

	e.SetEdge(6,7);
	e.SetWeight( 2 );
	g->insert( e );

	e.SetEdge(6,8);
	e.SetWeight( 7 );
	g->insert( e );

	e.SetEdge(7,8);
	e.SetWeight( 4 );
	g->insert( e );



	vector< vector< int > > pathvec( g->V() );
	for( vector< vector< int > >::iterator it = pathvec.begin(); it != pathvec.end(); it++ )
	{
		it->assign( g->V(), 0 );
	}

	vector< vector< int > > pathlenvec( g->V() );
	for( vector< vector< int > >::iterator it = pathlenvec.begin(); it != pathlenvec.end(); it++ )
	{
		it->assign( g->V(), 0 );
	}
	//g->Dijkstra( pathvec, pathlenvec );
	g->Floyd( pathvec, pathlenvec );
*/
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值