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;
}