#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<limits.h>
typedef char VertexType[20]; // 顶点类型为字符串
#define MAX_VERTEX_NUM 20
typedef enum{DG,DN,UDG,UDN}GraphKind; // {有向图,有向网,无向图,无向网}
typedef struct
{
int adjvex; // 该弧所指向的顶点的位置
int info; // 网的权值指针
}ElemType;
typedef struct ArcNode
{
ElemType data; // 除指针以外的部分都属于ElemType
struct ArcNode *nextarc; // 指向下一条弧的指针
}ArcNode; // 表结点
typedef struct
{
VertexType data; // 顶点信息
ArcNode *firstarc; // 第一个表结点的地址,指向第一条依附该顶点的弧的指针
}VNode,AdjList[MAX_VERTEX_NUM]; // 头结点
typedef struct
{
AdjList vertices;
int vexnum,arcnum; // 图的当前顶点数和弧数
GraphKind kind; // 图的种类标志
}ALGraph;
#define LNode ArcNode // 定义单链表的结点类型是图的表结点的类型
#define next nextarc // 定义单链表结点的指针域是表结点指向下一条弧的指针域
typedef ArcNode *LinkList; // 定义指向单链表结点的指针是指向图的表结点的指针
int LocateElem(LinkList L,ElemType e,int (*equal)(ElemType,ElemType));
LinkList Point(LinkList L,ElemType e,int(*equal)(ElemType,ElemType),LinkList &p);
int ListInsert(LinkList &L,int i,ElemType e);// 在不带头结点的单链线性表L中第i个位置之前插入元素e
int equal(ElemType a,ElemType b);
void visit(VertexType i);
void CreateGraphF(ALGraph &G); // 采用邻接表存储结构,由文件构造没有相关信息图或网G
void Display(ALGraph G); // 输出图的邻接表G
int LocateVex(ALGraph G,VertexType u); //若G中存在顶点u,则返回该顶点在图中位置;否则返回-1
int FirstAdjVex(ALGraph G,VertexType v); // 返回v的第一个邻接顶点的序号;否则返回-1
int NextAdjVex(ALGraph G,VertexType v,VertexType w);//v是图G中某个顶点,w是v的邻接顶点,返回v的(相对于w的)下一个邻接顶点的序号
int main()
{
ALGraph g;
VertexType v1,v2;
int k;
CreateGraphF(g); // 利用数据文件创建图
Display(g); // 输出图
//printf("请输入顶点的值: ");
scanf("%s",v1);
//printf("输出图G中顶点%s的所有邻接顶点: ",v1);
k=FirstAdjVex(g,v1);
while(k!=-1)
{
strcpy(v2,g.vertices[k].data);
visit(v2);
k=NextAdjVex(g,v1,v2);
}
printf("\n");
return 0;
}
int equal(ElemType a,ElemType b)
{
if(a.adjvex==b.adjvex)
return 1;
else
return 0;
}
void visit(VertexType i)
{
printf("%s ",i);
}
int LocateElem(LinkList L,ElemType e,int (*equal)(ElemType,ElemType))
{ // 初始条件: 不带头结点的单链表L已存在,equal()是数据元素判定函数(满足为1,否则为0)
// 操作结果: 返回L中第1个与e满足关系equal()的数据元素的位序。
// 若这样的数据元素不存在,则返回值为0
int i=0;
LinkList p=L; // L是不带头结点的单链表
while(p)
{
i++;
if(equal(p->data,e)) // 找到这样的数据元素
return i;
p=p->next;
}
return 0;
}
LinkList Point(LinkList L,ElemType e,int(*equal)(ElemType,ElemType),LinkList &p)
{ //查找表L中满足条件的结点。如找到,返回指向该结点的指针,p指向该结点的前驱(若该结点是首元结点,则p=NULL)。
//如表L中无满足条件的结点,则返回NULL,p无定义。函数equal()的两形参的关键字相等,返回OK;否则返回ERROR
int i,j;
i=LocateElem(L,e,equal);
if(i) // 找到
{
if(i==1) // 是首元结点
{
p=NULL;
return L;
}
p=L;
for(j=2;j<i;j++)
p=p->next;
return p->next;
}
return NULL; // 没找到
}
int ListInsert(LinkList &L,int i,ElemType e)
{ // 在不带头结点的单链线性表L中第i个位置之前插入元素e
int j=1;
LinkList p=L,s;
if(i<1) // i值不合法
return 0;
s=(LinkList)malloc(sizeof(struct LNode)); // 生成新结点
s->data=e; // 给s的data域赋值
if(i==1) // 插在表头
{
s->next=L;
L=s; // 改变L
}
else
{ // 插在表的其余处
while(p&&j<i-1) // 寻找第i-1个结点
{
p=p->next;
j++;
}
if(!p) // i大于表长+1
return 0;
s->next=p->next;
p->next=s;
}
return 1;
}
void CreateGraphF(ALGraph &G)
{ // 采用邻接表 存储结构,由文件构造没有相关信息图或网G(用一个函数构造4种图)
/********** Begin **********/
int i,j,k,w;
VertexType va,vb;
ElemType e;
char filename[13];
FILE *graphlist;
scanf("%d",&G.kind);
scanf("%s",filename);
graphlist=fopen(filename,"r");
fscanf(graphlist,"%d",&G.vexnum);
fscanf(graphlist,"%d",&G.arcnum);
for(i=0;i<G.vexnum;++i)
{
fscanf(graphlist,"%s",G.vertices[i].data);
G.vertices[i].firstarc=NULL;
}
for(k=0;k<G.arcnum;++k)
{
if(G.kind%2)
fscanf(graphlist,"%s%s%d",va,vb,&w);
else
fscanf(graphlist,"%s%s",va,vb);
i=LocateVex(G,va);
j=LocateVex(G,vb);
e.info=0;
e.adjvex=j;
if(G.kind%2)
{
e.info = w;
}
ListInsert(G.vertices[i].firstarc,1,e);
if(G.kind>=2)
{
e.adjvex=i;
ListInsert(G.vertices[j].firstarc,1,e);
}
}
fclose(graphlist);
/********** End **********/
}
void Display(ALGraph G)
{ // 输出图的邻接表G
int i;
LinkList p;
switch(G.kind)
{
case DG: printf("有向图\n"); break;
case DN: printf("有向网\n"); break;
case UDG:printf("无向图\n"); break;
case UDN:printf("无向网\n");
}
printf("%d个顶点:\n",G.vexnum);
for(i=0;i<G.vexnum;++i)
printf("%s ",G.vertices[i].data);
printf("\n%d条弧(边):\n",G.arcnum);
for(i=0;i<G.vexnum;i++)
{
p=G.vertices[i].firstarc;
while(p)
{
printf("%s→%s ",G.vertices[i].data,G.vertices[p->data.adjvex].data);
if(G.kind%2) // 网
printf(":%d\t",p->data.info );
p=p->nextarc;
}
printf("\n");
}
}
int LocateVex(ALGraph G,VertexType u)
{ // 初始条件:图G存在,u和G中顶点有相同特征
// 操作结果:若G中存在顶点u,则返回该顶点在图中位置;否则返回-1
int i;
for(i=0;i<G.vexnum;++i)
if(strcmp(u,G.vertices[i].data)==0)
return i;
return -1;
}
int FirstAdjVex(ALGraph G,VertexType v)
{ // 初始条件:图G存在,v是G中某个顶点
// 操作结果:返回v的第一个邻接顶点的序号。若顶点在G中没有邻接顶点,则返回-1
/********** Begin **********/
LinkList p;
int v1;
v1=LocateVex(G,v);
p=G.vertices[v1].firstarc;
if(p)
return p->data.adjvex;
else
return -1;
/********** End **********/
}
int NextAdjVex(ALGraph G,VertexType v,VertexType w)
{ // 初始条件:图G存在,v是G中某个顶点,w是v的邻接顶点
// 操作结果:返回v的(相对于w的)下一个邻接顶点的序号。若w是v的最后一个邻接点,则返回-1
/********** Begin **********/
LinkList p,p1;
ElemType e;
int v1;
v1=LocateVex(G,v);
e.adjvex=LocateVex(G,w);
p=Point(G.vertices[v1].firstarc,e,equal,p1);
if(!p||!p->next)
return -1;
else
return p->next->data.adjvex;
/********** End **********/
}