数据结构--图的邻接表存储

这段代码展示了图的邻接表存储结构,包括顶点、弧的操作,如插入、删除、查找等。此外,还实现了深度优先遍历和广度优先遍历的非递归算法。用户可以选择进行各种操作,如插入顶点、弧,删除顶点、弧,或者进行图的遍历。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

图的邻接表存储

代码如下:

//图的邻接表存储结构

#include<stdio.h>
#include<string.h>
#include<malloc.h>
#define MAX_VERTEX_NUM 20     //最大顶点个数
#define MAX_NAME 3            //顶点字符串最大长度+1
#define ERROR 0
#define OK 1
typedef int ElemType;
typedef int Status;
typedef enum{DG,DN,AG,AN}GraphKind;    //图的种类:有向图、有向网、无向图、无向网
typedef int InfoType;
typedef char VertexType[MAX_NAME];

 //队列结构
typedef struct node    
{
	ElemType data;
	struct node *next;
}QueueNode;
typedef struct
{
	QueueNode *front;
	QueueNode *rear;
}LinkQueue;


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)
		return 0;
	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);
	p=G.vertices[i].firstarc;
	if(p)
	{
		return p->adjvex;
		printf("该顶点的第一个邻接顶点的序号为%d\n",p->adjvex);
	}
	else
		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;
		printf("顶点%s相对于顶点%s的下一个邻接顶点序号为:%s\n",v,w,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).vexnum--;
	for(i=j;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,v);
	if(i<0||j<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(i<0||j<0||i==j)
		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[i].firstarc)
			     (*G).vertices[i].firstarc=p->nextarc;
		    else
			     q->nextarc=p->nextarc;
	    	if((*G).kind==3)
		     	free(p->info);
		    free(p);
		}
	}
	return OK;
}
			



//图的销毁
void DestoryGraph(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)
{
	int i,j,k;
	int w;
	VertexType va,vb;
	ArcNode *p;
	printf("请输入图的类型(有向图:0,有向网:1,无向图:2,无向网:3):");
	scanf("%d",&(*G).kind);
	printf("请输入图的顶点数、边数:");
	scanf("%d %d",&(*G).vexnum,&(*G).arcnum);
	printf("请输入%d个顶点的值(<%d个字符):",(*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)
	{
		printf("请输入第%d条边",k+1);
		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;
		}
	}
	printf("图已创建完毕!");
	return OK;
}

Status wenjian(ALGraph *G)
{
	FILE *fp;
	int i,j,k;
	int w;
	VertexType va,vb;
	ArcNode *p;
	if((fp=fopen("algraph.txt","r"))==NULL)   //打开文件
	{
		printf("文件打开失败!\n");
	}
	else
		printf("文件打开成功!\n");
	fscanf(fp,"%d",&(*G).kind);
	fscanf(fp,"%d,%d",&(*G).vexnum,&(*G).arcnum);
	for(i=0;i<(*G).vexnum;++i)
	{
		fscanf(fp,"%s",(*G).vertices[i].data);
		(*G).vertices[i].firstarc=NULL;
	}
	for(k=0;k<(*G).arcnum;++k)
	{
		if((*G).kind==1||(*G).kind==3)
			fscanf(fp,"%d%s%s",&w,va,vb);
		else
			fscanf(fp,"%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;
		}
	}
	fclose(fp);       //关闭文件
	printf("图已创建完毕!");
	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.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)
				{
					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");
	}
}

int InitQueue(LinkQueue *Q)               //链队列的初始化操作
{
	Q->front=(QueueNode *)malloc(sizeof(QueueNode));
	Q->front->next=NULL;
	Q->rear=Q->front;
	return OK;
}
int EnQueue(LinkQueue *Q,ElemType e)   //链队列的入操作
{
	QueueNode *p;
	p=(QueueNode *)malloc(sizeof(QueueNode));
	p->data=e;
	p->next=NULL;
	Q->rear->next=p;
	Q->rear=p;
	return OK;
}
int DeQueue(LinkQueue *Q,ElemType *e)        //链队列的出队操作
{
	QueueNode *p;
	if(Q->front==Q->rear)
		return ERROR;
	p=Q->front->next;
	*e=p->data;
	Q->front->next=p->next;
	if(Q->rear==p)
        Q->rear=Q->front;
	free(p);
	return OK;
}
int QueueEmpty(LinkQueue Q)
{
	if(Q.front==Q.rear)
		return 0;
	else
		return 1;
}

//邻接表存储结构上的深度优先遍历非递归算法
void DFSTraverse(ALGraph G,VertexType v0)
{
	int visited[MAX_VERTEX_NUM]={0}; 
	int S[MAX_VERTEX_NUM];
	int top=-1;
	int v,w;
	VertexType  *Vt1;
	for(v=0;v<G.vexnum;v++)
		visited[v]=0; 
	v=LocateVex(G,v0);
	S[++top]=v;
	visited[v]=1;
	printf("%s ",G.vertices[v].data);
	while(top!=-1)         
	{
		v=S[top];
		Vt1=GetVex(G,v);
		w=FirstAdjVex(G,*Vt1);  //求v的第一个邻接点
		while(w!=-1)
		{
			if(!visited[w])
			{
				S[++top]=w;
				visited[w]=1;
				printf("%s ",G.vertices[w].data);
				break;
			}
			w=NextAdjVex(G,G.vertices[v].data,G.vertices[w].data); 
		}
		if(w==-1 && top>-1)
			top--;
	}
	printf("\n");
}

//邻接表存储结构上的广度优先遍历算法
void BFSTraverse(ALGraph G)
{
	int v,u,w;
	VertexType u1,w1;
	LinkQueue Q;
    int visited[MAX_VERTEX_NUM];
	for(v=0;v<G.vexnum;++v)
		visited[v]=-1;
	InitQueue(&Q);
	for(v=0;v<G.vexnum;v++)
		if(visited[v]==-1)
		{
			visited[v]=1;
			printf("%s ",G.vertices[v].data);
			EnQueue(&Q,v);
			while(!QueueEmpty(Q))
			{
				DeQueue(&Q,&u);
				strcpy(u1,*GetVex(G,u));
				w=FirstAdjVex(G,u1);
				for(;w>=0;w=NextAdjVex(G,u1,strcpy(w1,*GetVex(G,w))))
					if(visited[w]==-1)
					{
						visited[w]=1;
						printf("%s ",G.vertices[w].data);
						EnQueue(&Q,w);
					}
			}
		}
		printf("\n");
}







int menu()
{
	int i;
    printf("\n||-----------------------------图的邻接表存储--------------------------------||\n");
	printf("||                请选择操作:                                                ||\n");
    printf("||                      1.求顶点位置                                         ||\n");
	printf("||                      2.求顶点信息                                         ||\n");
	printf("||                      3.对顶点赋新值                                       ||\n");
	printf("||                      4.求顶点的第一个邻接顶点序号                         ||\n");
	printf("||                      5.求顶点相对于某顶点的下一个邻接顶点序号             ||\n");
	printf("||                      6.插入新顶点                                         ||\n");
	printf("||                      7.删除顶点                                           ||\n");
	printf("||                      8.插入新弧                                           ||\n");
	printf("||                      9.删除弧                                             ||\n");
	printf("||                      10.销毁图                                            ||\n");
	printf("||                      11.图的打印与输出                                    ||\n");
	printf("||                      12.图的广度优先遍历                                  ||\n");
	printf("||                      13.图的深度优先遍历                                  ||\n");
	printf("||---------------------------------------------------------------------------||\n");
	scanf("%d",&i);
	return i;
	}

int main()
{
	int select,i,d;
	char c[3],e[3],v[3]="v1";
	ALGraph myG;
	printf("请选择构图方式 1.手动输入;2.文件读入\n");
	scanf("%d",&select);
	if(select==1)
	{
		CreateGraph(&myG);
	}
	else
	{
	    wenjian(&myG);
	}
	
	while(i)
	{
		i=menu();
	switch(i)
	{
	case 1:
		printf("请输入所求顶点:");
		scanf("%s",c);
		d=LocateVex(myG,c);
		printf("该顶点为%d\n",d);
		break;
	case 2:
		printf("请输入所求序号:");
		scanf("%d",&d);
		GetVex(myG,d);
		break;
	case 3:
		printf("请输入顶点和所赋新值:");
		scanf("%s %s",e,c);
		PutVex(&myG,e,c);
		printf("赋值成功\n");
		break;
	case 4:
		printf("请输入顶点:");
		scanf("%s",e);
		FirstAdjVex(myG,e);
		break;
	case 5:
		printf("请输入顶点、相对顶点:");
		scanf("%s %s",e,c);
		NextAdjVex(myG,e,c);
		break;
	case 6:
		printf("请输入新顶点值:");
		scanf("%s",e);
		InsertVex(&myG,e);
        printf("插入成功!\n");
		break;
	case 7:
		printf("请输入要删除的顶点:");
		scanf("%s",e);
		DeleteVex(&myG,e);
        printf("删除成功!\n");
		break;
	case 8:
		printf("请输入要插入新弧的弧尾、弧头:");
		scanf("%s %s",e,c);
		InsertArc(&myG,e,c);
        printf("插入成功!\n");
		break;
	case 9:
		printf("请输入要删除弧的弧尾、弧头:");
		scanf("%s %s",e,c);
		DeleteArc(&myG,e,c);
        printf("删除成功!\n");
		break;
	case 10:
        printf("该图已销毁!\n");
		break;
	case 11:
		Display(myG);
        printf("打印已完成!\n");
		break;
	case 12:
	    printf("邻接表存储结构上的广度优先遍历:\n");
        BFSTraverse(myG);
		break;
	case 13:
	    printf("邻接表存储结构上的深度优先遍历非递归:\n");
        DFSTraverse(myG,v);
	}
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大菜彩

家人们鼓励鼓励!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值