#ifndef _GRAPHCLASS_H_
#define _GRAPHCLASS_H_
const int MaxSize = 100;
const int INF = 9999;
int visited[MaxSize];
template<class T>
struct ArcNode //边结点类型
{
int adjvex; //该边的终点编号
ArcNode<T> *nextarc;//指向下一条边的指针
T weight;
};
//
template<class T>
struct VNode //表头结点类型
{
char data[MaxSize];
ArcNode<T> *firstarc;
};
//
template<class T>
struct ALGraph //图的邻接表类型
{
VNode<T> adjlist[MaxSize]; //邻接表数组
int n,e; //图中顶点数n和边数e
};
//
template<class T>
class GraphClass
{
public:
GraphClass(); //构造函数
~GraphClass(); //析构函数
void CreateALGraph(T a[][MaxSize], int n, int e);//建立邻接链表
void DFSA(); //深度优先遍历非连通图无向图
void BFSA(); //广度优先遍历非连通图无向图
bool Connect(); //判断一个无向图是否连通
bool HasPath(int u,int v); //判断u与v之间是否是连通的
void FindPath(int u,int v); //输出u到 v的简单路径
void FindAllPath(int u, int v); //输出u到v的所有路径
void FindAllLengthPath(int u, int v, int l);//输出u到v的所有路径长度为l的路径
bool Cycle(); //判断图中是否有回路
private:
ALGraph<T> *G;
void DestroyGraph(); //销毁图的邻接表
void DFS1(int v); //深度优先遍历调用函数
void BFS1(int v); //广度优先遍历调用函数
void HasPath1(int u, int v, bool &has);//判断连通调用函数
void FindPath1(int u, int v, int path[], int d);
void FindAllPath1(int u, int v, int path[], int d);
void FindAllLengthPath1(int u, int v, int path[], int d, int l);
void Cycle1(int u, int v,int d,bool &has);
};
//
template<class T>
GraphClass<T>::GraphClass()
{
G = NULL;
}
//
template<class T>
GraphClass<T>::~GraphClass()
{
if(G != NULL)
{
DestroyGraph();
}
}
//
template<class T>
void GraphClass<T>::DestroyGraph()
{
int i;
ArcNode<T> *p,*pre;
for(i = 0;i < G->n;i++) //遍历所有头结点
{
pre = G->adjlist[i].firstarc;
if(pre != NULL)
{
p = pre->nextarc;
while(p != NULL)
{
delete pre;
pre = p;
p = p->nextarc;
}
delete pre;
}
}
delete G; //释放G所指的头结点数组的内存空间
}
//通过边数组a,顶点数n和边数e来建立图的邻接表
template<class T>
void GraphClass<T>::CreateALGraph(T a[][MaxSize], int n, int e)
{
int i,j;
ArcNode<T> *p;
G = new ALGraph<T>;
G->n = n;
G->e = e;
for(i = 0;i < G->n;i++) //给邻接表中所有头结点的指针域置初值
{
G->adjlist[i].firstarc = NULL;
}
for(i = 0;i < G->n;i++) //检查边数组中a中的每个元素
{
for(j = G->n - 1;j >= 0;j--)
{
if(a[i][j] != 0 && a[i][j] != INF)
{
p = new ArcNode<T>;
p->adjvex = j;
p->weight = a[i][j];
p->nextarc = G->adjlist[i].firstarc;
G->adjlist[i].firstarc = p;
}
}
}
}
//
template<class T>
void GraphClass<T>::DFS1(int v)
{
int w;
ArcNode<T> *p;
visited[v] = 1; //置已访问标记
std::cout<<v<<" ";
p = G->adjlist[v].firstarc; //p指向v的第一个邻接点
while(p != NULL)
{
w = p->adjvex;
if(visited[w] == 0) //若w顶点未被访问,递归访问它
{
DFS1(w);
}
p = p->nextarc; //p置为下一个邻接点
}
}
//
template<class T>
void GraphClass<T>::BFS1(int v)
{
ArcNode<T> *p;
int w;
int qu[MaxSize];
int rear = 0, front = 0;
std::cout<<v<<" ";
visited[v] = 1; //已访问标志
rear = (rear + 1) % MaxSize;
qu[rear] = v;
while(rear != front)
{
front = (front + 1) % MaxSize;
w = qu[front];
p = G->adjlist[w].firstarc;
while(p != NULL)
{
if(visited[p->adjvex] == 0)
{
std::cout<<p->adjvex<<" ";
visited[p->adjvex] = 1;
rear = (rear + 1) % MaxSize;
qu[rear] = p->adjvex;
}
p = p->nextarc; //找下一个临界顶点
}
}
}
//若无向图是非连通图,则只能访问到初始点所在连通分量中的所有顶点,其他连通分量中的顶点不可能访问到
//需要在每个连通分量中选择初始结点,分别进行遍历
template<class T>
void GraphClass<T>::DFSA()
{
int i;
ArcNode<T> *p;
for(i = 0;i < G->n;i++)
{
visited[i] = 0;
}
for(i = 0;i < G->n;i++)
{
if(visited[i] == 0)
{
DFS1(i);
}
}
}
//
template<class T>
void GraphClass<T>::BFSA()
{
int i;
for(i = 0;i < G->n;i++)
{
visited[i] = 0;
}
for(i = 0;i < G->n;i++)
{
if(visited[i] == 0)
{
BFS1(i);
}
}
}
//判断连通性
template<class T>
bool GraphClass<T>::Connect()
{
int i;
bool flag = true;
for(i = 0;i < G->n;i++) //将visited数组元素均置为0
{
visited[i] = 0;
}
DFS1(0); //深度优先遍历
for(i = 0;i < G->n;i++)
{
if(visited[i] == 0) //若有没有被访问到的结点
{
flag = false;
break;
}
}
return flag;
}
//
template<class T>
bool GraphClass<T>::HasPath(int u,int v)
{
int i;
bool has = false;
for(i = 0;i < G->n;i++) //将访问数组元素置为0
{
visited[i] = 0;
}
HasPath1(u,v,has); //深度优先遍历
return has;
}
//
template<class T>
void GraphClass<T>::HasPath1(int u, int v, bool &has)
{
ArcNode<T> *p;
int w;
visited[u] = 1;
p = G->adjlist[u].firstarc;//p指向u的第一个相邻点
while(p != NULL)
{
w = p->adjvex; //相邻点的编号是w
if(w == v) //找到目标点后返回
{
has = true;
return;
}
if(visited[w] == 0)
{
HasPath1(w,v,has);
}
p = p->nextarc; //p指向下一个相邻点
}
}
//
template<class T>
void GraphClass<T>::FindPath(int u, int v)
{
int i, path[MaxSize], d = -1;
for(i = 0;i < G->n;i++)
{
visited[i] = 0;
}
FindPath1(u,v,path,d);
}
//
template<class T>
void GraphClass<T>::FindPath1(int u, int v, int path[], int d)
{
ArcNode<T> *p;
int w, i;
visited[u] = 1;
d++;
path[d] = u;
if(u == v)
{
for(i = 0;i < d;i++)
{
std::cout<<path[i]<<" ";
}
std::cout<<std::endl;
return;
}
p = G->adjlist[u].firstarc;
while(p != NULL)
{
w = p->adjvex;
if(visited[w] == 0)
{
FindPath1(w,v,path,d);
}
p = p->nextarc;
}
}
//
template<class T>
void GraphClass<T>::FindAllPath(int u, int v)
{
int path[MaxSize],d = -1,i;
for(i = 0;i < G->n;i++) //未访问标记
{
visited[i] = 0;
}
FindAllPath1(u,v,path,d);
}
//
template<class T>
void GraphClass<T>::FindAllPath1(int u, int v, int path[], int d)
{
ArcNode<T> *p;
int w,i;
visited[u] = 1;
d++;
path[d] = u; //将顶点u加入到路径中去
if(u == v) //如果找到路径
{
for(i = 0;i < d;i++)
{
std::cout<<path[i]<<" ";
}
std::cout<<std::endl;
}
p = G->adjlist[u].firstarc;
while(p != NULL)
{
w = p->adjvex; //相邻结点的编号
if(visited[w] == 0)
{
FindAllPath1(w,v,path,d);//递归调用
}
p = p->nextarc;
}
visited[u] = 0; //回溯,重置为0,和找单一路径的唯一区别
}
//
template<class T>
void GraphClass<T>::FindAllLengthPath(int u, int v, int l)
{
int path[MaxSize],i,d = -1;
for(i = 0;i < G->n;i++)
{
visited[i] = 0;
}
FindAllLengthPath1(u,v,path,d,l);
}
//
template<class T>
void GraphClass<T>::FindAllLengthPath(int u, int v, int path[], int d, int l)
{
ArcNode<T> *p;
int w,i;
visited[u] = 1; //加入到路径中
d++;
path[d] = u;
if((u == v) && (d == l))//找到一条路径长度为l的输出路径
{
for(i = 0;i < d;i++)
{
std::cout<<path[i]<<" ";
}
std::cout<<std::endl;
}
p = G->adjlist[u].firstarc;
while(p != NULL)
{
w = p->adjvex;
if(visited[w] == 0)
{
FindAllLengthPath1(w,v,path,d,l);
}
p = p->nextarc;
}
visited[u] = 0;
}
//
template<class T>
bool GraphClass<T>::Cycle()
{
int i,j;
bool has = false;
int d = -1;
for(i = 0;i < G->n;i++)
{
visited[i] = 0;
Cycle1(i,i,d,has);
if(has)
{
return true;
}
}
return false;
}
//
template<class T>
void GraphClass<T>::Cycle1(int u, int v, int d,bool &has)
{
ArcNode<T> *p;
int w;
d++;
visited[u] = 1;
if((u == v)&&(d > 0))
{
has = true;
return;
}
p = G->adjlist[u];
while(p != NULL)
{
w = p->adjvex;
if(visited[w] == 0)
{
Cycle1(w,v,d,has);
}
p = p->nextarc;
}
visited[u] = 0;
}
#endif // _GRAPHCLASS_H_