图的邻接表基本操作
代码如下:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<malloc.h>
#define MAX_VERTEX_NUM 20
#define MAX_NAME 3
#define Status int
#define ERROR 1
#define OK 0
typedef char VertexType[MAX_NAME];
typedef int InfoType;
typedef enum{DG,DN,AG,AN}GraphKind; //{有向图,有向网,无向图,无向网}
typedef struct ArcNode
{
int adjvex; //该弧所指向的顶点的位置
InfoType *info; //网的权值指针
struct ArcNode *nextarc; //指向下一条弧的指针
} ArcNode; //表结点
typedef struct
{
VertexType data; //顶点信息 (三个域)
ArcNode *firstarc; //第一个表结点的地址,指向第一条依附于该顶点的弧
} VNode; //头结点
typedef struct
{
VNode vertices[MAX_VERTEX_NUM]; //定义一个这个类型的数组
int vexnum,arcnum; //图的当前顶点数和弧数
int kind; //图的种类标志
} ALGraph; //邻接表
//求顶点位置的算法
int LocateVex(ALGraph G,VertexType u)
{
int i;
for(i=0;i<G.vexnum;++i)
{
if(strcmp(u,G.vertices[i].data)==0)
return i;
}
return -1;
}
//求顶点信息的算法
VertexType* GetVex(ALGraph G,int v)
{
if(v>=G.vexnum || v<0)
exit(1); //出现错误退出
printf("此顶点的信息为%s\n",G.vertices[v].data);
return &G.vertices[v].data;
}
//对顶点赋新值的算法
Status PutVex(ALGraph *G,VertexType v,VertexType value)
{
int i;
i=LocateVex(*G,v);
if(i<-1)
{
strcpy((*G).vertices[i].data,value);
return OK;
}
return ERROR;
}
//求顶点的第一个邻接顶点序号的算法
int FirstAdjVex(ALGraph G,VertexType v)
{
ArcNode *p;
int i;
i=LocateVex(G,v); //i为顶点v在图G中的序号
p=G.vertices[i].firstarc;//指针指向
if(p)
return p->adjvex;//返回位置
else //p==NULL
return -1;
}
//求顶点v相对于某顶点w的下一个邻接顶点序号的算法
int NextAdjVex(ALGraph G,VertexType v,VertexType w)
{
ArcNode *p;
int v1,w1;
v1=LocateVex(G,v);
w1=LocateVex(G,w);
p=G.vertices[v1].firstarc;
while(p&&p->adjvex!=w1)
p=p->nextarc;
if(!p||!p->nextarc)
return -1;
else
return p->nextarc->adjvex;
}
//插入新顶点的算法
void InsertVex(ALGraph *G,VertexType v)
{
strcpy((*G).vertices[(*G).vexnum].data,v);
(*G).vertices[(*G).vexnum].firstarc=NULL;
(*G).vexnum++;
}
//删除顶点的算法
Status DeleteVex(ALGraph *G,VertexType v)
{
int i,j;
ArcNode *p,*q;
j=LocateVex(*G,v);
if(j<0)
return ERROR;
p=(*G).vertices[j].firstarc;
while(p)
{
q=p;
p=p->nextarc;
if((*G).kind%2)
free(q->info);
free(q);
(*G).arcnum--;
}
(*G).vexnum--;
for(i=j;i<(*G).vexnum;i++)
{
(*G).vertices[i]=(*G).vertices[i+1];
}
for(i=0;i<(*G).vexnum;i++)
{
p=(*G).vertices[i].firstarc;
while(p)
{
if(p->adjvex==j)
{
if(p==(*G).vertices[i].firstarc)
{
(*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--;
}
else
{
q->nextarc=p->nextarc;
if((*G).kind%2)
free(p->info);
free(p);
p=q->nextarc;
if((*G).kind<2)
(*G).arcnum--;
}
}
else
{
if(p->adjvex>j)
p->adjvex--;
q=p;
p=p->nextarc;
}
}
}
return OK;
}
//插入新弧的算法
Status InsertArc(ALGraph *G,VertexType v,VertexType w)
{
ArcNode *p;
int w1,i,j;
i=LocateVex(*G,v);
j=LocateVex(*G,w);
if(j<0||i<0)
return ERROR;
(*G).arcnum++;
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;
}
return OK;
}
//删除弧的算法
Status DeleteArc(ALGraph *G,VertexType v,VertexType w)
{
ArcNode *p,*q;
int i,j;
i=LocateVex(*G,v);
j=LocateVex(*G,w);
if(j<0||i<0)
return ERROR;
p=(*G).vertices[i].firstarc;
while(p&&p->adjvex!=j)
{
q=p;
p=p->nextarc;
}
if(p&&p->adjvex==j)
{
if(p==(*G).vertices[i].firstarc)
(*G).vertices[i].firstarc=p->nextarc;
else
q->nextarc=p->nextarc;
if((*G).kind%2)
free(p->info);
free(p);
(*G).arcnum--;
}
if((*G).kind>=2)
{
p=(*G).vertices[j].firstarc;
while(p&&p->adjvex!=i)
{
q=p;
p=p->nextarc;
}
if(p&&p->adjvex==i)
{
if(p==(*G).vertices[j].firstarc)
(*G).vertices[j].firstarc=p->nextarc;
else
q->nextarc=p->nextarc;
if((*G).kind==3)
free(p->info);
free(p);
}
}
return OK;
}
//图的销毁算法
void DestroyGraph(ALGraph *G)
{
int i;
ArcNode *p,*q;
(*G).vexnum=0;
(*G).arcnum=0;
for(i=0;i<(*G).vexnum;i++)
{
p=(*G).vertices[i].firstarc;
(*G).vertices[i].firstarc=NULL;
while(p)
{
q=p->nextarc;
if((*G).kind%2)
free(p->info);
free(p);
p=q;
}
}
}
//图的创建算法
Status CreateGraph(ALGraph *G)
{
FILE *fp;
int i,j,k;
int w;
VertexType va,vb;
ArcNode *p;
if((fp=fopen("有向图.txt","r"))==NULL)
{
printf("打开失败!\n");
exit(0);
}
else
printf("打开文件成功\n");
printf("请输入图的类型(有向图:0,有向网:1,无向图:2,无向网:3):");
//scanf("%d",&(*G).kind);
fscanf(fp,"%d",&G->kind);
printf("%d\n",G->kind);
printf("请输入图的顶点数,边数:");
//scanf("%d,%d",&(*G).vexnum,&(*G).arcnum);
fscanf(fp,"%d,%d",&G->vexnum,&G->arcnum);
printf("%d,%d\n",(*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);
fscanf(fp,"%s",&G->vertices[i].data);
printf("%s ",G->vertices[i].data);
(*G).vertices[i].firstarc=NULL;
}
printf("\n");
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);
fscanf(fp,"%d%s%s",&w,va,vb);
printf("%d%s%s",w,va,vb);
}
else
{
//scanf("%s%s",va,vb);
fscanf(fp,"%s%s",va,vb);
printf("%s %s",va,vb);
}
printf("\n");
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;
}
}
fclose(fp);
printf("图已创建完毕!\n");
return OK;
}
//图的打印输出
void Display(ALGraph G)
{
int i;
ArcNode *p;
switch(G.kind)
{
case DG:printf("有向图\n");break;
case DN:printf("有向网\n");break;
case AG:printf("无向图\n");break;
case AN: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)
{
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)
{
printf("%s->%s ",G.vertices[i].data,G.vertices[p->adjvex].data);
if(G.kind==AN)
printf(":%d ",*(p->info));
}
}
p=p->nextarc;
}
printf("\n");
}
}
void menu()
{
printf("\t\t\t\t\t||-----------------------------------------------------||\n");
printf("\t\t\t\t\t|| 图的邻接表存储结构 ||\n");
printf("\t\t\t\t\t||-----------------------------------------------------||\n");
printf("\t\t\t\t\t|| 1.求顶点位置 ||\n");
printf("\t\t\t\t\t||-----------------------------------------------------||\n");
printf("\t\t\t\t\t|| 2.求顶点信息 ||\n");
printf("\t\t\t\t\t||-----------------------------------------------------||\n");
printf("\t\t\t\t\t|| 3.对顶点赋新值 ||\n");
printf("\t\t\t\t\t||-----------------------------------------------------||\n");
printf("\t\t\t\t\t|| 4.求顶点的第一个邻接顶点序号 ||\n");
printf("\t\t\t\t\t||-----------------------------------------------------||\n");
printf("\t\t\t\t\t|| 5.求顶点v相对于某顶点w的下一个邻接顶点序号 ||\n");
printf("\t\t\t\t\t||-----------------------------------------------------||\n");
printf("\t\t\t\t\t|| 6.插入新顶点 ||\n");
printf("\t\t\t\t\t||-----------------------------------------------------||\n");
printf("\t\t\t\t\t|| 7.删除顶点 ||\n");
printf("\t\t\t\t\t||-----------------------------------------------------||\n");
printf("\t\t\t\t\t|| 8.插入新弧 ||\n");
printf("\t\t\t\t\t||-----------------------------------------------------||\n");
printf("\t\t\t\t\t|| 9.删除弧 ||\n");
printf("\t\t\t\t\t||-----------------------------------------------------||\n");
printf("\t\t\t\t\t|| 10.销毁图 ||\n");
printf("\t\t\t\t\t||-----------------------------------------------------||\n");
printf("\t\t\t\t\t|| 0.退出 ||\n");
printf("\t\t\t\t\t||-----------------------------------------------------||\n");
}
int main(void)
{
int i,k;
ALGraph g;
VertexType a,b;
CreateGraph(&g);
Display(g);
while(1)
{
menu();
printf("请选择图的相关操作:");
scanf("%d",&i);
switch(i)
{
case 1:
printf("请输入待求的顶点:\n");
scanf("%s",a);
k=LocateVex(g,a);
printf("顶点%s的位置是%d\n",a,k);
break;
case 2:
printf("请输入待求的顶点序号:\n");
scanf("%d",&k);
GetVex(g,k);
break;
case 3:
printf("请输入待赋值顶点和所赋新值:\n");
scanf("%s %s",a,b);
PutVex(&g,a,b);
printf("赋值成功!\n");
break;
case 4:
printf("请输入待求顶点:\n");
scanf("%s",a);
k=FirstAdjVex(g,a);
printf("顶点%s的第一个邻接顶点的序号为:%d\n",a,k);
break;
case 5:
printf("请输入顶点1与顶点2:\n");
scanf("%s %s",a,b);
k=NextAdjVex(g,a,b);
printf("顶点%s相对于顶点%s的下一个邻接顶点的序号是:%d\n",a,b,k);
break;
case 6:
printf("请输入待插入的顶点:\n");
scanf("%s",a);
InsertVex(&g,a);
printf("插入成功,如下图所示!\n");
Display(g);
break;
case 7:
printf("请输入待删除的顶点:\n");
scanf("%s",a);
DeleteVex(&g,a);
printf("删除成功,如下图所示!\n");
Display(g);
break;
case 8:
printf("请输入待插入弧的顶点:\n");
scanf("%s %s",a,b);
InsertArc(&g,a,b);
printf("插入成功!");
Display(g);
break;
case 9:
printf("请输入待删除弧的顶点:\n");
scanf("%s %s",a,b);
DeleteArc(&g,a,b);
printf("删除成功!");
Display(g);
break;
case 10:
DestroyGraph(&g);
break;
case 0:
exit(0);
default:printf("输入错误!\n");
break;
}
}
}
相关文件: