求一个无向图G的连通分量的个数Word文档格式.docx
《求一个无向图G的连通分量的个数Word文档格式.docx》由会员分享,可在线阅读,更多相关《求一个无向图G的连通分量的个数Word文档格式.docx(16页珍藏版)》请在冰豆网上搜索。
//图的邻接表存储表示
#defineMAX_NAME3//顶点字符串的最大长度+1
#defineMAX_VERTEX_NUM20
#defineSTACK_INIT_SIZE10//存储空间初始分配量
#defineSTACKINCREMENT2//存储空间分配增量
typedefintInfoType;
//存放网的权值
typedefcharVertexType[MAX_NAME];
//字符串类型
typedefenum{DG,DN,AG,AN}GraphKind;
//{有向图,有向网,无向图,无向网}
typedefstructArcNode
{
intadjvex;
//该弧所指向的顶点的位置
structArcNode*nextarc;
//指向下一条弧的指针
InfoType*info;
//网的权值指针)
}ArcNode;
//表结点
typedefstructVNode
VertexTypedata;
//顶点信息
ArcNode*firstarc;
//第一个表结点的地址,指向第一条依附该顶点的弧的指针
}VNode,AdjList[MAX_VERTEX_NUM];
//头结点
typedefstruct
AdjListvertices;
intvexnum,arcnum;
//图的当前顶点数和弧数
intkind;
//图的种类标志
}ALGraph;
//若G中存在顶点u,则返回该顶点在图中位置;
否则返回-1。
intLocateVex(ALGraphG,VertexTypeu)
inti;
for(i=0;
i<
G.vexnum;
++i)
if(strcmp(u,G.vertices[i].data)==0)
returni;
return-1;
}
//采用邻接表存储结构,构造没有相关信息的图G(用一个函数构造4种图)。
intCreateGraph(ALGraph*G)
inti,j,k;
intw;
//权值
VertexTypeva,vb;
ArcNode*p;
printf("
请输入图的类型(有向图:
0,有向网:
1,无向图:
2,无向网:
3):
"
);
scanf("
%d"
&
(*G).kind);
请输入图的顶点数和边数:
(空格)\n"
%d%d"
&
(*G).vexnum,&
(*G).arcnum);
请输入%d个顶点的值(小于%d个字符):
\n"
(*G).vexnum,MAX_NAME);
for(i=0;
i<
(*G).vexnum;
++i)//构造顶点向量
{
scanf("
%s"
(*G).vertices[i].data);
(*G).vertices[i].firstarc=NULL;
}
if((*G).kind==1||(*G).kind==3)//网
printf("
请顺序输入每条弧(边)的权值、弧尾和弧头(以空格作为间隔):
else//图
请顺序输入每条弧(边)的弧尾和弧头(以空格作为间隔):
for(k=0;
k<
(*G).arcnum;
++k)//构造表结点链表
if((*G).kind==1||(*G).kind==3)//网
scanf("
%d%s%s"
w,va,vb);
else//图
%s%s"
va,vb);
i=LocateVex(*G,va);
//弧尾
j=LocateVex(*G,vb);
//弧头
p=(ArcNode*)malloc(sizeof(ArcNode));
p->
adjvex=j;
if((*G).kind==1||(*G).kind==3)//网
{
p->
info=(int*)malloc(sizeof(int));
*(p->
info)=w;
}
else
info=NULL;
//图
nextarc=(*G).vertices[i].firstarc;
//插在表头
(*G).vertices[i].firstarc=p;
if((*G).kind>
=2)//无向图或网,产生第二个表结点
p=(ArcNode*)malloc(sizeof(ArcNode));
adjvex=i;
if((*G).kind==3)//无向网
{
p->
info=(int*)malloc(sizeof(int));
*(p->
}
else
//无向图
nextarc=(*G).vertices[j].firstarc;
(*G).vertices[j].firstarc=p;
return1;
voidDisplay(ALGraphG)//输出图的邻接表G。
switch(G.kind)
caseDG:
有向图\n"
break;
caseDN:
有向网\n"
caseAG:
无向图\n"
caseAN:
无向网\n"
%d个顶点:
G.vexnum);
G.vexnum;
++i)
%s"
G.vertices[i].data);
\n%d条弧(边):
G.arcnum);
i++)
p=G.vertices[i].firstarc;
while(p)
if(G.kind<
=1)//有向
printf("
%s→%s"
G.vertices[i].data,
G.vertices[p->
adjvex].data);
if(G.kind==DN)//网
printf("
:
%d"
*(p->
info));
else//无向(避免输出两次)
if(i<
p->
adjvex)
{
%s-%s"
G.vertices[p->
if(G.kind==AN)//网
printf("
*(p->
}
p=p->
nextarc;
voidFindInDegree(ALGraphG,intindegree[])//求顶点的入度。
{
i++)
indegree[i]=0;
//赋初值
p=G.vertices[i].firstarc;
indegree[p->
adjvex]++;
typedefintSElemType;
//栈类型
typedefstructSqStack//栈的顺序存储表示
SElemType*base;
//在栈构造之前和销毁之后,base的值为NULL
SElemType*top;
//栈顶指针
intstacksize;
//当前已分配的存储空间,以元素为单位
}SqStack;
//顺序栈
intInitStack(SqStack*S)//构造一个空栈S
//为栈底分配一个指定大小的存储空间
(*S).base=(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));
if(!
(*S).base)
exit(0);
//存储分配失败
(*S).top=(*S).base;
//栈底与栈顶相同表示一个空栈
(*S).stacksize=STACK_INIT_SIZE;
//若栈S为空栈(栈顶与栈底相同的),则返回1,否则返回0。
intStackEmpty(SqStackS)
if(S.top==S.base)
return1;
else
return0;
intPush(SqStack*S,SElemTypee)//插入元素e为新的栈顶元素。
if((*S).top-(*S).base>
=(*S).stacksize)//栈满,追加存储空间
(*S).base=(SElemType*)realloc((*S).base,
((*S).stacksize+STACKINCREMENT)*sizeof(SElemType));
if(!
exit(0);
//存储分配失败
(*S).top=(*S).base+(*S).stacksize;
(*S).stacksize+=STACKINCREMENT;
*((*S).top)++=e;
//这个等式的++*优先级相同,但是它们的运算方式,是自右向左
//若栈不空,则删除S的栈顶元素,用e返回其值,并返回1;
否则返回0。
intPop(SqStack*S,SElemType*e)
if((*S).top==(*S).base)
*e=*--(*S).top;
//有向图G采用邻接表存储结构。
若G无回路,则输出G的顶点的一个拓扑序
//列并返回1,否则返回0。
intTopologicalSort(ALGraphG)
inti,k,count,indegree[MAX_VERTEX_NUM];
SqStackS;
FindInDegree(G,indegree);
//对各顶点求入度indegree[0..vernum-1]
InitStack(&
S);
//初始化栈
++i)//建零入度顶点栈S
if(!
indegree[i])
Push(&
S,i);
//入度为0者进栈
count=0;
//对输出顶点计数
while(!
StackEmpty(S))
//栈不空
Pop(&
S,&
i);
//输出i号顶点并计数
++count;
for(p=G.vertices[i].firstarc;
p;
p=p->
nextarc)
//对i号顶点的每个邻接点的入度减1
k=p->
adjvex;
if(!
(--indegree[k]))//若入度减为0,则入栈
S,k);
if(count<
G.vexnum)
此有向图有回路\n"
无回路,此图的拓扑序\n"
intmain()
ALGraphf;
请选择有向图\n"
CreateGraph(&
f);
Display(f);
TopologicalSort(f);
system("
pause"
return0;
//无向图的邻接表存储表示
#defineMAX_NAME3//顶点字符串的最大长度+1
#defineTRUE1
#defineFALSE0
intvisited[MAX_VERTEX_NUM];
//访问标志数组
//第一个表结点的地址,指向第一条依附该顶点的弧的指针
请输入无向图的顶点数和边数:
(*G).vertices[i].firstarc=p;
//无向图产生第二个表结点
p=(ArcNode*)malloc(sizeof(ArcNode));
(*G).vertices[j].firstarc=p;
//输出图的邻接表G。
voidDisplay(ALGraphG)
if(i<
adjvex)//无向(避免输出两次)
G.vertices[p->
voidDFS(ALGraphG,intv)//从第v个顶点出发递归地深度优先遍历图G。
visited[v]=TRUE;
//访问第v个顶点
for(p=G.vertices[v].firstarc;
if(!
visited[p->
adjvex])DFS(G,p->
adjvex);
//对v尚未访问的邻接点递归调用DFS
voidDFSTraverse(ALGraphG)//对图G作深度优先遍历。
intv,count=0;
for(v=0;
v<
++v)
visited[v]=FALSE;
++v)
visited[v])
DFS(G,v);
count++;
//对连通分量进行计数
无向图G的连通分量的个数为:
count);
DFSTraverse(f);
五、运行输出结果:
请选择有向图
0
(空格)
44
请输入4个顶点的值(小于3个字符):
1
2
3
02
01
23
30
有向图
4个顶点:
0123
4条弧(边):
0→10→2
2→3
3→0
此有向图有回路
请按任意键继续...
54
请输入5个顶点的值(小于3个字符):
4
5
12
24
14
35
无向图
5个顶点:
12345
1-41-2
2-4
3-5
六、心得与体会:
这次上机实验,难度较大,但是经过自己的不懈努力,收获还是颇多的。
首先是对于图的有了更加清晰认识,其次,在程序设计上面也有了很大程度的提高。
对于栈、队等也有了进一步的系统化认