一、实验目的:
1.掌握图的存储定义;
2.掌握图的遍历操作;
3.掌握图的拓扑排序算法。
二、实验内容:
1. 利用图的邻接矩阵,实现图的深度优先遍历搜索。图结构如下
结果输出
2. 采用邻接表作为有向图的存储结构,编写图的拓扑排序程序实现下图的拓扑排序输出;
实验一:图的深度优先遍历操作
定义邻接矩阵
typedef struct{
int vex[MaxVertexNum];
int Edge[MaxVertexNum][MaxVertexNum];
int vexnum,arcnum; //顶点数和边数
}MGraph;
寻找v的位置
int LocateVex(int vex,MGraph G)
{
for(int i=0;i<G.vexnum;i++)
{
if(vex==G.vex[i])
return i;
}
return -1;
}
创建无向图
void CreateGraph(MGraph &G)
{
int i,j;
cout <<"请输入总顶点数和总边数:";
cin >> G.vexnum >> G.arcnum;
//初始化数组Edge;
for(i=0;i<G.vexnum;i++)
{
for(j=0;j<G.vexnum;j++)
G.Edge[i][j]=0;
}
cout<<"请输入点的名称 "<<endl;
for(i=0;i<G.vexnum;i++)
{
cout<<"请输入第" << (i+1) << "个点的名称:";
cin>>G.vex[i];
}
for(i=0;i<G.arcnum;i++)
{
int v1,v2,n,m;
cout<<"请输入第"<<(i+1)<<"个边的依附点的名称: ";
cin>>v1>>v2;
n=LocateVex(v1, G);
m=LocateVex(v2, G);
G.Edge[n][m]=1;
G.Edge[m][n]=1;
}
}
无向图的深度优先遍历
bool visit[MaxVertexNum];
void DFS(MGraph G,int v)
{
int k;
cout<<G.vex[v]<<" ";
visit[v]=true;
for(k=0;k<G.vexnum;k++)
{
if((!visit[k]) && G.Edge[v][k]!=0)
{
DFS(G,k);
}
}
}
主函数
int main() {
MGraph G;
CreateGraph(G);
cout<<"无向图创建完成"<<endl;
int v;
cout<<"请输入无向遍历的起始点:";
cin>>v;
//初始化辅助数组visit
for(int i=0;i<G.vexnum;i++)
{
visit[i]=false;
}
DFS(G,v);
return 0;
}
结果输出
实验二:拓扑排序算法
#define MaxVertexNum 100
//定义边表
typedef struct ArcNode{
int adjvex; //下一个结点的关键字
struct ArcNode *nextarc; //指向下一个结点的指针
}ArcNode;
//创建图结点
typedef struct VNode{
int data;
ArcNode *firstedge; //边表的头指针
}VNood;
//定义邻接表
typedef struct{
VNode adjmulist[MaxVertexNum];
VNode converse_adjmulist[MaxVertexNum];
int vexnum,arcnum;
}AMLGraph;
//定义顺序栈
typedef struct{
int *top,*base;
int stacksize;
} spStack;
//定义入度矩阵
int Indegree[MaxVertexNum];
//定义栈
spStack S;
栈的系列操作
//初始化顺序栈
void InitStack(spStack &S)
{
S.base = new int[MaxVertexNum];
if(!S.base) exit(1);
S.top = S.base;
S.stacksize = MaxVertexNum;
}
// 进栈
void Push(spStack &S,int i)
{
// 满栈
if(S.top-S.base == S.stacksize)
return;
*S.top++ = i;
}
//出栈
void Pop(spStack &S,int &i)
{
//栈空
if(S.top == S.base)
return;
i = *--S.top;
}
//判断栈是否为空栈
bool IsEmptyStack(spStack S)
{
if(S.base == S.top)
return true;
return false;
}
//找到位置
int LocateVex(AMLGraph G,int v)
{
for(int i = 0;i < G.vexnum; i++)
{
if(v == G.adjmulist[i].data)
return i;
}
return -1;
}
//寻找入度
void FindIndegree(AMLGraph G)
{
int i,count;
for(i = 0 ; i < G.vexnum ; i++)
{
count = 0;
ArcNode *p = G.converse_adjmulist[i].firstedge;
while(p){
p = p->nextarc;
count++;
}
Indegree[i] = count;
}
}
创建有向图的邻接表
void CreateUDG(AMLGraph &G)
{
int i;
cout<<"请输入总顶点数和总边数: ";
cin>>G.vexnum>>G.arcnum;
for(i = 0; i < G.vexnum; i++)
{
cout<<"请输入第"<<(i+1)<<"个点的名称: ";
cin>>G.adjmulist[i].data;
G.converse_adjmulist[i].data = G.adjmulist[i].data;
G.adjmulist[i].firstedge=NULL;
G.converse_adjmulist[i].firstedge=NULL;
}
for(i = 0; i < G.arcnum; i++)
{
int v1,v2,m,n;
cout<<"请输入第"<<(i+1)<<"个点的依附点: ";
cin>>v1>>v2;
m = LocateVex(G, v1);
n = LocateVex(G, v2);
ArcNode *p1 = new ArcNode; //生成新结点p1
p1->adjvex = n;
p1->nextarc = G.adjmulist[m].firstedge;
G.adjmulist[m].firstedge = p1; //将新结点插入边表头部,头插法
ArcNode *p2 = new ArcNode; //生成新结点p2
p2->adjvex = m;
p2->nextarc = G.converse_adjmulist[n].firstedge;
G.converse_adjmulist[n].firstedge = p2; //将新结点插入逆序边表的头部
}
}
拓扑排序
bool TopologicalSort(AMLGraph G,int topo[])
{
int i,count;
InitStack(S);
FindIndegree(G);
for(i = 0 ; i < G.vexnum ; i++)
{
if(Indegree[i] == 0)
Push(S, i);
}
count = 0;
while(!IsEmptyStack(S))
{
Pop(S, i);
topo[count] = i;
++count;
ArcNode *p = new ArcNode;
for(p = G.adjmulist[i].firstedge ; p ; p = p->nextarc)
{
int k = p->adjvex;
--Indegree[k];
if(Indegree[k] == 0) Push(S,k);
}
}
//输出结点个数与图的结点个数做比较
if(count < G.vexnum) return false;
else return true;
}
主函数
int main() {
AMLGraph G;
CreateUDG(G);
cout<<"有向图的邻接表、逆序邻接表创建完成"<<endl<<endl;
int *topo = new int[MaxVertexNum];
if(TopologicalSort(G, topo))
{
cout<<"该有向图的拓扑排序为:"<<endl;
for(int i = 0 ; i<G.vexnum; i++)
{
cout<<G.adjmulist[topo[i]].data<<", ";
}
cout<<endl;
}
else cout<<"图中存在环,无法输出拓扑排序";
return 0;
}