代码实现:
输入:按顶点之间的指向输入一个有向图 如ch[0]=‘A’指向ch[3]=‘D’ 则输入 0 3
输出:由代码中指定顶点开始的深度遍历与广度遍历以及拓扑排序
#include <iostream>
using namespace std;
const int MaxSize=10; //图的最大顶点数
int visited[MaxSize] = {0};
struct EdgeNode //定义边表结点
{
int adjvex; //邻接点域
EdgeNode *next;
};
template <class DataType>
struct VertexNode //定义顶点表结点
{
DataType vertex;
EdgeNode *firstEdge;
int In;
};
template <class DataType>
class ALGraph
{
public:
ALGraph(DataType a[ ], int n, int e); //构造函数,建立一个有n个顶点e条边的图
~ALGraph( ); //析构函数,释放邻接表中各边表结点的存储空间
void DFTraverse(int v); //深度优先遍历图
void BFTraverse(int v); //广度优先遍历图
void TopSort();
private:
VertexNode<DataType> adjlist[MaxSize]; //存放顶点表的数组
int vertexNum, edgeNum; //图的顶点数和边数
};
template <class DataType>
ALGraph<DataType>::ALGraph(DataType a[ ], int n, int e)
{
int i,j,k;
EdgeNode *s = NULL;
vertexNum = n; //顶点数量赋值
edgeNum = e; //边数量赋值
for(i = 0;i<vertexNum;i++)//初始化顶点表信息
{
adjlist[i].vertex = a[i];//在表中存放所有顶点信息
adjlist[i].firstEdge = NULL; //将所有邻边点指针置空
adjlist[i].In = 0; //将所有顶点入度初始化为 0
}
for(k = 0;k<edgeNum;k++)//初始化指向边信息
{
cout << "请输入两个边顶点的序号:";
cin>>i>>j;//输入i号指向j号
adjlist[j].In += 1 ;
s = new EdgeNode;//新建边表
s->adjvex = j;//边表的邻顶点序号
s->next = adjlist[i].firstEdge; //头插法
adjlist[i].firstEdge = s;
}
}
template <class DataType>
ALGraph<DataType>::~ALGraph( )
{
EdgeNode *p = NULL, *q = NULL;
for(int i=0;i<vertexNum;i++) //释放所有边表结点的存储空间
{
p=q=adjlist[i].firstEdge;
while(p!=NULL)
{
p = p->next;
delete q;
q = p;
}
}
}
template <class DataType>
void ALGraph<DataType>::DFTraverse(int v)//有向图深度遍历
{
int j;
EdgeNode *p = NULL;
cout<<adjlist[v].vertex;
visited[v] = 1;
p = adjlist[v].firstEdge; //p指向顶点v的边表
while(p!=NULL)//依次搜索v点的邻接点j点
{
j = p->adjvex; //j指向v的第一个邻点
if(visited[j]==0)DFTraverse(j);
p = p->next;
}
}
template <class DataType>
void ALGraph<DataType>::BFTraverse(int v)//有向图广度遍历
{
int w, j, Q[MaxSize];
int front = -1, rear = -1;
EdgeNode *p = NULL;
cout<<adjlist[v].vertex; //输出v点信息
visited[v] = 1; //标记v点
Q[++rear] = v; //v点入队
while(front!=rear)
{
w = Q[++front]; //v点出队 w=v
p = adjlist[w].firstEdge; //p指向顶点v的边表
while(p!=NULL)
{
j = p->adjvex; //j点是v点的邻点
if(visited[j]==0) //若j点未被访问,将j点入队
{
cout<<adjlist[j].vertex;
visited[j] = 1;
Q[++rear] = j;
}
p = p->next;
}
}
}
template <class DataType>
void ALGraph<DataType>::TopSort()
{
int i,j,k,count = 0;
int S[MaxSize],top = -1;
EdgeNode *p = NULL;
for(i = 0;i<vertexNum;i++)
{
if(adjlist[i].In==0) S[++top] = i; //寻找初始状态下入度为 0 的点
}
while(top!=-1)
{
j = S[top--];
cout<<adjlist[j].vertex;
count++; //计数有多少个点已输出
p = adjlist[j].firstEdge;
while(p!=NULL) //将j点指向的所有点入度减 1,用边表遍历寻找j点通向的邻点
{
k = p->adjvex; //k为邻点
adjlist[k].In--; //k的入度减 1
if(adjlist[k].In==0) S[++top] = k; //如果k点入度为 0,入队
p = p->next;
}
}
if(count<vertexNum) cout<<"有回路"<<endl; //如果输出的顶点个数与存在顶点个数不相等
//说明AOV网中存在回路
}
int main()
{
char ch[ ]={'A','B','C','D','E','F'};
int i;
ALGraph<char> ALG(ch, 6, 9);
for (int i = 0; i < MaxSize; i++)
{
visited[i] = 0;
}
cout<<"从顶点"<<ch[0]<<"进行深度优先遍历序列是:";
ALG.DFTraverse(0);
for (int i = 0; i < MaxSize; i++)
{
visited[i] = 0;
}
cout<<""<<endl;
cout<<"从顶点"<<ch[2]<<"进行广度优先遍历序列是:";
ALG.BFTraverse(2);
cout<<""<<endl;
cout<<"其拓扑排序是:";
ALG.TopSort();
cout<<endl;
return 0;
}
示例:
输入:
请输入两个边顶点的序号:1 0
请输入两个边顶点的序号:1 3
请输入两个边顶点的序号:2 0
请输入两个边顶点的序号:2 3
请输入两个边顶点的序号:3 0
请输入两个边顶点的序号:3 5
请输入两个边顶点的序号:4 2
请输入两个边顶点的序号:4 3
请输入两个边顶点的序号:4 5
输出:
从顶点A进行深度优先遍历序列是:A
从顶点C进行广度优先遍历序列是:CDAF
其拓扑排序是:ECBDAF