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);
printf("请输入图的顶点数和边数:
(空格)\n");
scanf("%d%d",&(*G).vexnum,&(*G).arcnum);
printf("请输入%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("请顺序输入每条弧(边)的权值、弧尾和弧头(以空格作为间隔):
\n");
else//图
printf("请顺序输入每条弧(边)的弧尾和弧头(以空格作为间隔):
\n");
for(k=0;k<(*G).arcnum;++k)//构造表结点链表
{
if((*G).kind==1||(*G).kind==3)//网
scanf("%d%s%s",&w,va,vb);
else//图
scanf("%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
p->info=NULL;//图
p->nextarc=(*G).vertices[i].firstarc;//插在表头
(*G).vertices[i].firstarc=p;
if((*G).kind>=2)//无向图或网,产生第二个表结点
{
p=(ArcNode*)malloc(sizeof(ArcNode));
p->adjvex=i;
if((*G).kind==3)//无向网
{
p->info=(int*)malloc(sizeof(int));
*(p->info)=w;
}
else
p->info=NULL;//无向图
p->nextarc=(*G).vertices[j].firstarc;//插在表头
(*G).vertices[j].firstarc=p;
}
}
return1;
}
//销毁图G。
voidDestroyGraph(ALGraph*G)
{
inti;
ArcNode*p,*q;
for(i=0;i<(*G).vexnum;++i)
{
p=(*G).vertices[i].firstarc;
while(p)
{
q=p->nextarc;
if((*G).kind%2)//网
free(p->info);
free(p);
p=q;
}
}
(*G).vexnum=0;
(*G).arcnum=0;
}
//返回v的值。
VertexType*GetVex(ALGraphG,intv)
{
if(v>=G.vexnum||v<0)
exit(0);
return&G.vertices[v].data;
}
//对v赋新值value。
intPutVex(ALGraph*G,VertexTypev,VertexTypevalue)
{
inti;
i=LocateVex(*G,v);
if(i>-1)//v是G的顶点
{
strcpy((*G).vertices[i].data,value);
return1;
}
return0;
}
//返回v的第一个邻接顶点的序号。
若顶点在G中没有邻接顶点,则返回-1。
intFirstAdjVex(ALGraphG,VertexTypev)
{
ArcNode*p;
intv1;
v1=LocateVex(G,v);//v1为顶点v在图G中的序号
p=G.vertices[v1].firstarc;
if(p)
returnp->adjvex;
else
return-1;
}
//返回v的(相对于w的)下一个邻接顶点的序号。
若w是v的最后一个
//邻接点,则返回-1。
intNextAdjVex(ALGraphG,VertexTypev,VertexTypew)
{
ArcNode*p;
intv1,w1;
v1=LocateVex(G,v);//v1为顶点v在图G中的序号
w1=LocateVex(G,w);//w1为顶点w在图G中的序号
p=G.vertices[v1].firstarc;
while(p&&p->adjvex!
=w1)//指针p不空且所指表结点不是w
p=p->nextarc;
if(!
p||!
p->nextarc)//没找到w或w是最后一个邻接点
return-1;
else//p->adjvex==w
//返回v的(相对于w的)下一个邻接顶点的序号
returnp->nextarc->adjvex;
}
//在图G中增添新顶点v(不增添与顶点相关的弧,留待InsertArc()去做)。
voidInsertVex(ALGraph*G,VertexTypev)
{
strcpy((*G).vertices[(*G).vexnum].data,v);//构造新顶点向量
(*G).vertices[(*G).vexnum].firstarc=NULL;
(*G).vexnum++;//图G的顶点数加1
}
//删除G中顶点v及其相关的弧。
intDeleteVex(ALGraph*G,VertexTypev)
{
inti,j;
ArcNode*p,*q;
j=LocateVex(*G,v);//j是顶点v的序号
if(j<0)//v不是图G的顶点
return0;
p=(*G).vertices[j].firstarc;//删除以v为出度的弧或边
while(p)
{
q=p;
p=p->nextarc;
if((*G).kind%2)//网
free(q->info);
free(q);
(*G).arcnum--;//弧或边数减1
}
(*G).vexnum--;//顶点数减1
for(i=j;i<(*G).vexnum;i++)//顶点v后面的顶点前移
(*G).vertices[i]=(*G).vertices[i+1];
//删除以v为入度的弧或边且必要时修改表结点的顶点位置值
for(i=0;i<(*G).vexnum;i++)
{
p=(*G).vertices[i].firstarc;//指向第1条弧或边
while(p)//有弧
{
if(p->adjvex==j)//是以v为入度的边。
{
if(p==(*G).vertices[i].firstarc)//待删结点是第1个结点
{
(*G).vertices[i].firstarc=p->nextarc;
if((*G).kind%2)//网
free(p->info);
free(p);
p=(*G).vertices[i].firstarc;
if((*G).kind<2)//有向
(*G).arcnum--;//弧或边数减1
}
else
{
q->nextarc=p->nextarc;
if((*G).kind%2)//网
free(p->info);
free(p);
p=q->nextarc;
if((*G).kind<2)//有向
(*G).arcnum--;//弧或边数减1
}
}
else
{
if(p->adjvex>j)
p->adjvex--;//修改表结点的顶点位置值(序号)
q=p;
p=p->nextarc;
}
}
}
return1;
}
//在G中增添弧,若G是无向的,则还增添对称弧。
intInsertArc(ALGraph*G,VertexTypev,VertexTypew)
{
ArcNode*p;
intw1,i,j;
i=LocateVex(*G,v);//弧尾或边的序号
j=LocateVex(*G,w);//弧头或边的序号
if(i<0||j<0)
return0;
(*G).arcnum++;//图G的弧或边的数目加1
if((*G).kind%2)//网
{
printf("请输入弧(边)%s→%s的权值:
",v,w);
scanf("%d",&w1);
}
p=(ArcNode*)malloc(sizeof(ArcNode));
p->adjvex=j;
if((*G).kind%2)//网
{
p->info=(int*)malloc(sizeof(int));
*(p->info)=w1;
}
else
p->info=NULL;
p->nextarc=(*G).vertices[i].firstarc;//插在表头
(*G).vertices[i].firstarc=p;
if((*G).kind>=2)//无向,生成另一个表结点
{
p=(ArcNode*)malloc(sizeof(ArcNode));
p->adjvex=i;
if((*G).kind==3)//无向网
{
p->info=(int*)malloc(sizeof(int));
*(p->info)=w1;
}
else
p->info=NULL;
p->nextarc=(*G).vertices[j].firstarc;//插在表头
(*G).vertices[j].firstarc=p;
}
return1;
}
//在G中删除弧,若G是无向的,则还删除对称弧。
intDeleteArc(ALGraph*G,VertexTypev,VertexTypew)
{
ArcNode*p,*q;
inti,j;
i=LocateVex(*G,v);//i是顶点v(弧尾)的序号
j=LocateVex(*G,w);//j是顶点w(弧头)的序号
if(i<0||j<0||i==j)
return0;
p=(*G).vertices[i].firstarc;//p指向顶点v的第一条出弧
while(p&&p->adjvex!
=j)//p不空且所指之弧不是待删除弧
{//p指向下一条弧
q=p;
p=p->nextarc;
}
if(p&&p->adjvex==j)//找到弧
{
if(p==(*G).vertices[i].firstarc)//p所指是第1条弧
(*G).vertices[i].firstarc=p->nextarc;//指向下一条弧
else
q->nextarc=p->nextarc;//指向下一条弧
if((*G).kind%2)//网
free(p->info);
free(p);//释放此结点
(*G).arcnum--;//弧或边数减1
}
if((*G).kind>=2)//无向,删除对称弧
{
p=(*G).vertices[j].firstarc;//p指隙サ鉾的第一条出弧
while(p&&p->adjvex!
=i)//p不空且所指之弧不是待删除弧
{//p指向下一条弧
q=p;
p=p->nextarc;
}
if(p&&p->adjvex==i)//找到弧
{
if(p==(*G).vertices[j].firstarc)//p所指是第1条弧
(*G).vertices[j].firstarc=p->nextarc;//指向下一条弧
else
q->nextarc=p->nextarc;//指向下一条弧
if((*G).kind==3)//无向网
free(p->info);
free(p);//释放此结点
}
}
return1;
}
intvisited[MAX_VERTEX_NUM];//访问标志数组(全局量)
void(*VisitFunc)(char*v);//函数变量(全局量)
//算法7.5P169
//从第v个顶点出发递归地深度优先遍历图G。
voidDFS(ALGraphG,intv)
{
intw;
VertexTypev1,w1;
strcpy(v1,*GetVex(G,v));
visited[v]=1;//设置访问标志为1(已访问)
VisitFunc(G.vertices[v].data);//访问第v个顶点
for(w=FirstAdjVex(G,v1);w>=0;
w=NextAdjVex(G,v1,strcpy(w1,*GetVex(G,w))))
if(!
visited[w])
DFS(G,w);//对v的尚未访问的邻接点w递归调用DFS
}
//算法7.4P169
//对图G作深度优先遍历。
voidDFSTraverse(ALGraphG,void(*Visit)(char*))
{
intv;
//使用全局变量VisitFunc,使DFS不必设函数指针参数
VisitFunc=Visit;
for(v=0;vvisited[v]=0;//访问标志数组初始化
for(v=0;vif(!
visited[v])
DFS(G,v);//对尚未访问的顶点调用DFS
printf("\n");
}
//构造一个空队列Q。
intInitQueue(LinkQueue*Q)
{
(*Q).front=(*Q).rear=(QueuePtr)malloc(sizeof(QNode));//动态分配一个空间
if(!
(*Q).front)
exit(0);
(*Q).front->next=NULL;//队头指针指向空,无数据域,这样构成了一个空队列
return1;
}
//插入元素e为Q的新的队尾元素。
intEnQueue(LinkQueue*Q,QElemTypee)
{
QueuePtrp=(QueuePtr)malloc(sizeof(QNode));
if(!
p)//存储分配失败
exit(0);
//生成一个以为e为数据域的队列元素
p->data=e;
p->next=NULL;
//将该新队列元素接在队尾的后面
(*Q).rear->next=p;
(*Q).rear=p;
return1;
}
//若队列不空,删除Q的队头元素,用e返回其值,并返回1,否则返回0。
intDeQueue(LinkQueue*Q,QElemType*e)
{
QueuePtrp;
if((*Q).front==(*Q).rear)
return0;
p=(*Q).front->next;//队头元素
*e=p->data;
(*Q).front->next=p->next;
if((*Q).rear==p)
(*Q).rear=(*Q).front;
free(p);
return1;
}
//若Q为空队列,则返回1,否则返回0。
intQueueEmpty(LinkQueueQ)
{
if(Q.front==Q.rear)
return1;
else
return0;
}
//算法7.6P170
//按广度优先非递归遍历图G。
使用辅助队列Q和访问标志数组visited。
voidBFSTraverse(ALGraphG,void(*Visit)(char*))
{
intv,u,w;
VertexTypeu1,w1;
LinkQueueQ;
for(v=0;vvisited[v]=0;//置初值
InitQueue(&Q);//置空的辅助队列Q
for(v=0;vif(!
visited[v])//v尚未访问
{
visited[v]=1;
Visit(G.vertices[v].data);
EnQueue(&Q,v);//v入队列
while(!
QueueEmpty(Q))//队列不空
{
DeQueue(&Q,&u);//队头元素出队并置为u
strcpy(u1,*GetVex(G,u));
for(w=FirstAdjVex(G,u1);w>=0;w=NextAdjVex(G,
u1,strcpy(w1,*GetVex(G,w))))
if(!
visited[w])//w为u的尚未访问的邻接顶点
{