图的创建 有向图 插入 删除 邻接矩阵 邻接表

有向图的创建,插入删除顶点,插入删除弧,打印邻接矩阵和邻接表,查看顶点下标。

注:先分结构介绍,最后是完整代码和运行结果。

弧结点↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

typedef struct ArcNode
{
	int AdjVertex;//邻接点下标
	struct ArcNode *Next;
}ArcNode;

顶点域↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

typedef struct VertexNode
{
	char Vertex;//顶点信息
	ArcNode *FirstArc;
}VertexNode[MAXIMUM];

图结构↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

typedef struct Graph//有向图
{
	VertexNode AdjList;//邻接表
	int AdjMatrix[MAXIMUM][MAXIMUM];//邻接矩阵
	int AmountofVertex;//顶点数
	int AmountofArc;//边数
}Graph;

图的创建↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

int CreateGraph(Graph *G)//创建有向图
{
	int i,j;
	if(G==NULL)
	{
		printf("创建有向图失败!\n");//图创建失败
		return ERROR;
	}
	else
		printf("成功创建有向图\n");//图创建成功
	G->AmountofArc=0;//0条边
	G->AmountofVertex=0;//0个顶点

	for(i=0;i<MAXIMUM;i++)
	{
		G->AdjList[i].FirstArc=NULL;//所有顶点集指向NULL
		G->AdjList[i].Vertex='0';//所有顶点赋值为字符0
	}

	printf("\n");
	return CORRECT;
}

单个顶点插入↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

int InsertVertex(Graph *G)//插入顶点
{
	int k;
	char vertex;
	ArcNode *p;

	
	printf("请输入要插入顶点的信息(一个字母)\n");//插入顶点
	scanf("%c",&vertex);
	getchar();
	for(k=0;k<MAXIMUM;k++)
		if(G->AdjList[k].Vertex=='0')
		{	
			G->AdjList[k].Vertex=vertex;
			G->AmountofVertex++;//顶点数加一
			printf("\n");
			return CORRECT;
		}
	printf("顶点数组集已满!插入失败!\n");//数组元素满
	printf("\n");
	return ERROR;
}

删除单个顶点及其相关弧↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

int DeleteVertex(Graph *G)//删除顶点(同时删除所有该顶点相关的弧)
{
	int i,j,k;
	ArcNode *p,*pre,*del;//del为被删除结点,pre为del前驱

	printf("删除顶点vi,以及与v相关的所有弧,请依次输入顶点vi下标\n");
	scanf("%d",&i);
	getchar();
	
	G->AdjList[i].Vertex='0';//删除顶点信息
	G->AmountofVertex--;//顶点数减一
	p=G->AdjList[i].FirstArc;
	G->AdjList[i].FirstArc=NULL;
	while(p)						//删除出度的弧
	{
		del=p;
		p=p->Next;
		free(del);

		G->AmountofArc--;//弧数量减一
	}

	for(k=0;k<=G->AmountofVertex;k++)//删除入度的弧
	{
		p=G->AdjList[k].FirstArc;
		while(p)
		{
			if(p->AdjVertex==i)
			{
				if(p==G->AdjList[k].FirstArc)//被删除弧结点为第一个结点
				{
					del=p;
					p=p->Next;
					G->AdjList[k].FirstArc=p;
					pre=NULL;
					free(del);

					G->AmountofArc--;//弧数量减一
					break;
				}
				else
				{
					del=p;
					p=p->Next;
					pre->Next=p;
					free(del);

					G->AmountofArc--;//弧数量减一
					break;
				}
			}
			pre=p;
			p=p->Next;
		}
	}
	printf("\n\n");
	return CORRECT;
}

插入弧↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

int InsertArc(Graph *G)
{
	int i,j;
	ArcNode *p,*Insert;

	printf("插入弧<vi,vj>,请依次输入弧尾vi和弧头vj的下标i和j(以空格隔开)\n");
	scanf("%d %d",&i,&j);
	getchar();

	if(G->AdjList[i].Vertex=='0'||G->AdjList[j].Vertex=='0')//不存在顶点vi或vj,插入失败
	{
		printf("顶点v%d或顶点v%d不存在,创建弧失败!!\n",i,j);
		return ERROR;
	}

	p=G->AdjList[i].FirstArc;
	while(p)
	{
		if(p->AdjVertex==j)
		{
			printf("已存在弧<v%d,v%d>,插入弧失败!\n",i,j);//插入弧重复,插入失败
			return ERROR;
		}
		p=p->Next;
	}

	Insert=(ArcNode *)malloc(sizeof (ArcNode));
	Insert->AdjVertex=j;

	Insert->Next=G->AdjList[i].FirstArc;		//头插法插入
	G->AdjList[i].FirstArc=Insert;		//头插法插入

	G->AmountofArc++;//弧数量加一

	printf("\n\n");
	return CORRECT;
}

删除弧↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

int DeleteArc(Graph *G)
{
	int i,j,k;
	ArcNode *p,*pre,*del;//del为被删除结点,pre为del前驱

	printf("删除弧<vi,vj>,请依次输入弧尾vi和弧头vj的下标i和j(以空格隔开)\n");
	scanf("%d %d",&i,&j);
	getchar();

	for(p=G->AdjList[i].FirstArc;;p=p->Next)
	{
		pre=p;
		if(p==NULL)//没有弧
		{
			printf("不存在弧<v%d,v%d>,删除弧失败!\n",i,j);
			return ERROR;
		}
		if(p->AdjVertex==j)
		{
			if(p==G->AdjList[i].FirstArc)	//被删除弧结点为第一个结点
			{
				del=p;
				p=p->Next;
				G->AdjList[i].FirstArc=p;
				free(del);	//删除弧结点
				pre=NULL;
	
				G->AmountofArc--;	//弧数量减一
				return CORRECT;
			}
			else		//被删除弧结点不是第一个结点
			{
				del=p;
				p=p->Next;
				pre->Next=p;
				free(del);	//删除弧结点
	
				G->AmountofArc--;	//弧数量减一
				return CORRECT;
			}
		}
	}
	printf("\n\n");
	return CORRECT;
}

打印邻接矩阵↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

void PrintAdjMatrix(Graph *G)//邻接矩阵
{
	int i,j,k,k_;
	ArcNode *p;
	
	for(i=0;i<G->AmountofVertex;i++)
		for(j=0;j<G->AmountofVertex;j++)
		{
			if(G->AdjMatrix[i][j]!=0)
				G->AdjMatrix[i][j]=0;//邻接矩阵初始化为0
		}

	for(i=0,k=0;k<G->AmountofVertex;i++)
	{
		if(G->AdjList[i].Vertex=='0') continue ;
		for(p=G->AdjList[i].FirstArc;p;p=p->Next)
			G->AdjMatrix[i][p->AdjVertex]=1;//相邻顶点赋值为1
		k++;
	}

	printf("邻接矩阵:\n");

	for(i=0,k=0;k<G->AmountofVertex;i++)
	{
		if(G->AdjList[i].Vertex=='0') continue;
		for(j=0,k_=0;k_<G->AmountofVertex;j++)
		{
			if(G->AdjList[j].Vertex=='0') continue;
			printf("%3d",G->AdjMatrix[i][j]);//输出矩阵
			k_++;
		}
		k++;
		printf("\n");
	}
	printf("\n\n");
}

打印邻接表↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

void PrintAdjGraph(Graph *G)//邻接表
{
	int i=0,k=0;
	ArcNode *p;

	printf("邻接表:\n");
	while(k<G->AmountofVertex)
	{
		if(G->AdjList[i].Vertex=='0')
			k--;
		else
		{
			for(p=G->AdjList[i].FirstArc;p;p=p->Next)
				printf("<%c,%c>",G->AdjList[i].Vertex,G->AdjList[p->AdjVertex].Vertex);
			printf("\n");
		}
		k++;
		i++;
	}
	printf("\n\n");
}

查看顶点对应下标序号↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

int PrintVertexNum(Graph *G)//顶点下标序号表
{
	int i,j,k;
	ArcNode *p;

	for(i=0,k=0;i<MAXIMUM;i++)
	{
		for(j=0;j<20;j++)
		{
			if(G->AdjList[j].Vertex=='0') continue;
			printf("%c(%d)\t",G->AdjList[j].Vertex,j);//打印所有顶点和下标
			k++;
			if(k>=G->AmountofVertex) 
			{
				printf("\n\n");
				return CORRECT;
			}
		}
		printf("\n");
	}
	printf("\n\n");
	return CORRECT;
}

完整程序代码↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

#include <stdio.h>
#include <stdlib.h>
#define MAXIMUM 100
#define ERROR 1
#define CORRECT 0

typedef struct ArcNode
{
	int AdjVertex;//邻接点下标
	struct ArcNode *Next;
}ArcNode;

typedef struct VertexNode
{
	char Vertex;//顶点信息
	ArcNode *FirstArc;
}VertexNode[MAXIMUM];

typedef struct Graph//有向图
{
	VertexNode AdjList;//邻接表
	int AdjMatrix[MAXIMUM][MAXIMUM];//邻接矩阵
	int AmountofVertex;//顶点数
	int AmountofArc;//边数
}Graph;

int CreateGraph(Graph *G)//创建有向图
{
	int i,j;
	if(G==NULL)
	{
		printf("创建有向图失败!\n");//图创建失败
		return ERROR;
	}
	else
		printf("成功创建有向图\n");//图创建成功
	G->AmountofArc=0;//0条边
	G->AmountofVertex=0;//0个顶点

	for(i=0;i<MAXIMUM;i++)
	{
		G->AdjList[i].FirstArc=NULL;//所有顶点集指向NULL
		G->AdjList[i].Vertex='0';//所有顶点赋值为字符0
	}

	printf("\n");
	return CORRECT;
}

int InsertVertex(Graph *G)//插入顶点
{
	int k;
	char vertex;
	ArcNode *p;

	
	printf("请输入要插入顶点的信息(一个字母)\n");//插入顶点
	scanf("%c",&vertex);
	getchar();
	for(k=0;k<MAXIMUM;k++)
		if(G->AdjList[k].Vertex=='0')
		{	
			G->AdjList[k].Vertex=vertex;
			G->AmountofVertex++;//顶点数加一
			printf("\n");
			return CORRECT;
		}
	printf("顶点数组集已满!插入失败!\n");//数组元素满
	printf("\n");
	return ERROR;
}

int DeleteVertex(Graph *G)//删除顶点(同时删除所有该顶点相关的弧)
{
	int i,j,k;
	ArcNode *p,*pre,*del;//del为被删除结点,pre为del前驱

	printf("删除顶点vi,以及与v相关的所有弧,请依次输入顶点vi下标\n");
	scanf("%d",&i);
	getchar();
	
	G->AdjList[i].Vertex='0';//删除顶点信息
	G->AmountofVertex--;//顶点数减一
	p=G->AdjList[i].FirstArc;
	G->AdjList[i].FirstArc=NULL;
	while(p)						//删除出度的弧
	{
		del=p;
		p=p->Next;
		free(del);

		G->AmountofArc--;//弧数量减一
	}

	for(k=0;k<=G->AmountofVertex;k++)//删除入度的弧
	{
		p=G->AdjList[k].FirstArc;
		while(p)
		{
			if(p->AdjVertex==i)
			{
				if(p==G->AdjList[k].FirstArc)//被删除弧结点为第一个结点
				{
					del=p;
					p=p->Next;
					G->AdjList[k].FirstArc=p;
					pre=NULL;
					free(del);

					G->AmountofArc--;//弧数量减一
					break;
				}
				else
				{
					del=p;
					p=p->Next;
					pre->Next=p;
					free(del);

					G->AmountofArc--;//弧数量减一
					break;
				}
			}
			pre=p;
			p=p->Next;
		}
	}
	printf("\n\n");
	return CORRECT;
}

int InsertArc(Graph *G)
{
	int i,j;
	ArcNode *p,*Insert;

	printf("插入弧<vi,vj>,请依次输入弧尾vi和弧头vj的下标i和j(以空格隔开)\n");
	scanf("%d %d",&i,&j);
	getchar();

	if(G->AdjList[i].Vertex=='0'||G->AdjList[j].Vertex=='0')//不存在顶点vi或vj,插入失败
	{
		printf("顶点v%d或顶点v%d不存在,创建弧失败!!\n",i,j);
		return ERROR;
	}

	p=G->AdjList[i].FirstArc;
	while(p)
	{
		if(p->AdjVertex==j)
		{
			printf("已存在弧<v%d,v%d>,插入弧失败!\n",i,j);//插入弧重复,插入失败
			return ERROR;
		}
		p=p->Next;
	}

	Insert=(ArcNode *)malloc(sizeof (ArcNode));
	Insert->AdjVertex=j;

	Insert->Next=G->AdjList[i].FirstArc;		//头插法插入
	G->AdjList[i].FirstArc=Insert;		//头插法插入

	G->AmountofArc++;//弧数量加一

	printf("\n\n");
	return CORRECT;
}

int DeleteArc(Graph *G)
{
	int i,j,k;
	ArcNode *p,*pre,*del;//del为被删除结点,pre为del前驱

	printf("删除弧<vi,vj>,请依次输入弧尾vi和弧头vj的下标i和j(以空格隔开)\n");
	scanf("%d %d",&i,&j);
	getchar();

	for(p=G->AdjList[i].FirstArc;;p=p->Next)
	{
		pre=p;
		if(p==NULL)//没有弧
		{
			printf("不存在弧<v%d,v%d>,删除弧失败!\n",i,j);
			return ERROR;
		}
		if(p->AdjVertex==j)
		{
			if(p==G->AdjList[i].FirstArc)	//被删除弧结点为第一个结点
			{
				del=p;
				p=p->Next;
				G->AdjList[i].FirstArc=p;
				free(del);	//删除弧结点
				pre=NULL;
	
				G->AmountofArc--;	//弧数量减一
				return CORRECT;
			}
			else		//被删除弧结点不是第一个结点
			{
				del=p;
				p=p->Next;
				pre->Next=p;
				free(del);	//删除弧结点
	
				G->AmountofArc--;	//弧数量减一
				return CORRECT;
			}
		}
	}
	printf("\n\n");
	return CORRECT;
}

void PrintAdjMatrix(Graph *G)//邻接矩阵
{
	int i,j,k,k_;
	ArcNode *p;
	
	for(i=0;i<G->AmountofVertex;i++)
		for(j=0;j<G->AmountofVertex;j++)
		{
			if(G->AdjMatrix[i][j]!=0)
				G->AdjMatrix[i][j]=0;//邻接矩阵初始化为0
		}

	for(i=0,k=0;k<G->AmountofVertex;i++)
	{
		if(G->AdjList[i].Vertex=='0') continue ;
		for(p=G->AdjList[i].FirstArc;p;p=p->Next)
			G->AdjMatrix[i][p->AdjVertex]=1;//相邻顶点赋值为1
		k++;
	}

	printf("邻接矩阵:\n");

	for(i=0,k=0;k<G->AmountofVertex;i++)
	{
		if(G->AdjList[i].Vertex=='0') continue;
		for(j=0,k_=0;k_<G->AmountofVertex;j++)
		{
			if(G->AdjList[j].Vertex=='0') continue;
			printf("%3d",G->AdjMatrix[i][j]);//输出矩阵
			k_++;
		}
		k++;
		printf("\n");
	}
	printf("\n\n");
}

void PrintAdjGraph(Graph *G)//邻接表
{
	int i=0,k=0;
	ArcNode *p;

	printf("邻接表:\n");
	while(k<G->AmountofVertex)
	{
		if(G->AdjList[i].Vertex=='0')
			k--;
		else
		{
			for(p=G->AdjList[i].FirstArc;p;p=p->Next)
				printf("<%c,%c>",G->AdjList[i].Vertex,G->AdjList[p->AdjVertex].Vertex);
			printf("\n");
		}
		k++;
		i++;
	}
	printf("\n\n");
}

int PrintVertexNum(Graph *G)//顶点下标序号表
{
	int i,j,k;
	ArcNode *p;

	for(i=0,k=0;i<MAXIMUM;i++)
	{
		for(j=0;j<20;j++)
		{
			if(G->AdjList[j].Vertex=='0') continue;
			printf("%c(%d)\t",G->AdjList[j].Vertex,j);//打印所有顶点和下标
			k++;
			if(k>=G->AmountofVertex) 
			{
				printf("\n\n");
				return CORRECT;
			}
		}
		printf("\n");
	}
	printf("\n\n");
	return CORRECT;
}


int main(void)
{
	int a;
	Graph *G;
	G=(Graph *)malloc(sizeof (Graph));
	CreateGraph(G);

	while(1)
	{
		printf("当前总弧数为:%d\n",G->AmountofArc);
		printf("当前顶点数为:%d\n",G->AmountofVertex);
		printf("输入9查看操作序号\n\n");
		scanf("%d",&a);
		getchar();
		switch(a)
		{
		case 1:InsertVertex(G); break;
		case 2:DeleteVertex(G); break;
		case 3:InsertArc(G); break;
		case 4:DeleteArc(G); break;
		case 5:PrintAdjGraph(G); break;
		case 6:PrintAdjMatrix(G); break;
		case 7:PrintVertexNum(G); break;
		case 9:
		printf("****************************序号菜单*************************\n");
		printf("请输入操作序号:\n");
		printf("(1)插入顶点\t\t(2)删除顶点及所有相关弧\t\t(3)插入弧\n\n");
		printf("(4)删除弧\t\t(5)打印邻接表\t\t(6)打印邻接矩阵\n\n");
		printf("(7)当前已插入顶点的下标:\t\t(0)结束程序\n\n");
		printf("***************************************************************\n\n");break;
		case 0:return CORRECT;
		}
		
	}
	return CORRECT;
}

示例↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
在这里插入图片描述

运行结果↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 12
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值