【C语言】实现图的操作

图(graph)是由非空顶点集合以及描述顶点(vertex)之间关系的(edge)构成的一种数据结构。可以定义为G={v,e}的二元组 

今天介绍图的两种实现方式,分别是邻接矩阵邻接表

1.邻接矩阵实现图

(1)邻接矩阵简介

邻接矩阵是由顶点之间的相邻关系建立的矩阵

后文实现的图例

在弧的弧头弧尾的对应数组中插入对应弧的权值元素,后面实现的表为有向表,无向表的实现时将矩阵设计为对称矩阵。 

 后文实现的图(本文用-1代表两点之间不存在关系)

(2)构建邻接矩阵的结构体

typedef struct Graph{
	int ver; //定义顶点
	int** edge; //定义边之间关系
}Graph;

矩阵就是一个二维数组来实现顶点关系的存储。 

(3)创建矩阵

void Graph_creat(Graph* g,int ver)//创建矩阵 
{
	g->ver=ver;
	g->edge=(int**)malloc(sizeof(int*)*ver);//初始化矩阵
	int i,j;
	for(i=0;i<ver;++i)
	{
		g->edge[i]=(int*)malloc(sizeof(int)*ver);
		for(j=0;j<ver;++j)
		{
			g->edge[i][j]=inf;//将矩阵填入inf,代表现在顶点间不存在关系
		}
	}
} 

初始化元素包括,将顶点数填入以及将矩阵上的元素填入为-1 两步将矩阵的基本架构建立

(4)矩阵的销毁 

void Graph_distory(Graph* g)//销毁
{
	int i,j;
	for(i=0;i<g->ver;++i)
	{
		free(g->edge[i]);//遍历矩阵销毁节点
	}
	free(g->edge);
	g->edge=NULL;//最后将表置空
}

遍历完之后还要对矩阵这个结进行销毁,并将矩阵置空。 

(5)矩阵元素的插入

void Graph_insert(Graph* g,int i,int j,int weight)
{
	g->edge[i][j]=weight;
}

元素的插入就是将弧的权值插入矩阵中 

(6)矩阵的输出 

void Graph_print(Graph* g)
{
	int i,j;
	for(i=0;i<g->ver;++i)
	{
		for(j=0;j<g->ver;++j)
		{
			printf("%d\t",g->edge[i][j]);//遍历输出元素
		}
		printf("\n");
	}
}

简单遍历全矩阵来输出元素,并用tab缩进来保持输出元素的整齐。 

(7)完整矩阵代码实现

#include<stdio.h>
#include<stdlib.h>

#define inf -1

typedef struct Graph{
	int ver; 
	int** edge; 
}Graph;

void Graph_creat(Graph* g,int ver)
{
	g->ver=ver;
	g->edge=(int**)malloc(sizeof(int*)*ver);
	int i,j;
	for(i=0;i<ver;++i)
	{
		g->edge[i]=(int*)malloc(sizeof(int)*ver);
		for(j=0;j<ver;++j)
		{
			g->edge[i][j]=inf;
		}
	}
} 

void Graph_distory(Graph* g)
{
	int i,j;
	for(i=0;i<g->ver;++i)
	{
		free(g->edge[i]);
	}
	free(g->edge);
	g->edge=NULL;
}

void Graph_insert(Graph* g,int i,int j,int weight)
{
	g->edge[i][j]=weight;
}

void Graph_print(Graph* g)
{
	int i,j;
	for(i=0;i<g->ver;++i)
	{
		for(j=0;j<g->ver;++j)
		{
			printf("%d\t",g->edge[i][j]);
		}
		printf("\n");
	}
}

int main()
{
	Graph g;
	Graph_creat(&g,3);//定义节点数为3
	Graph_insert(&g,0,1,7);//插入元素0-》1权值为7
	Graph_insert(&g,1,2,3);//插入元素1-》2权值为3
	Graph_insert(&g,2,0,2);//插入元素2-》0权值为2
	Graph_print(&g);//输出表
	Graph_distory(&g);//销毁表
	return 0;
}

 

2.邻接表实现图

(1)邻接表的简介 

邻接表(adjacency list)是用顺序结构和链表结构结合的结构实现对元素弧之间关系的存储,相较于邻接矩阵而言在存储稀疏图是更有利于节约存储空间,不会造成大量空间的浪费。 

 

上图为后面要实现的图结构 

 (2)邻接表的结构

邻接表的三个结构体(1)节点结构由顶点元素域(vertex)指向第一个元素节点的指针(first)构成(2)边表结构由顶点下标值(vertex)权值(weight)指向下一个弧节点的指针(next)(3)链表结构由节点数(verties)指向顶点的指针(node)

typedef struct edgenode{
	int vertex;
	int weight; 
	struct edgenode* next;
}edgenode;//顶点 

typedef struct vernode{
	char vertex;
	edgenode* first;  
}vernode;

typedef struct{
	int verties;
	vernode* node;
}graph;

(3)邻接表的初始化

 将元素的值输入对应的结构中,再将元素指向的第一个顶点的指针置空

void graphcreate(graph* g,int verties)//初始化 
{
	g->verties=verties;//将顶点数赋予表结构的顶点值 
	g->node=(vernode*)malloc(sizeof(vernode)*verties);//初始化表结构
	int i;
	for(i=0;i<g->verties;++i)
	{
		printf("请输入第%d个元素\n",i+1);
		g->node[i].vertex=getchar();//遍历输入元素的内容值
		getchar();
		g->node[i].first=NULL; //将每一个顶点指向的第一个顶点的指针置为空
	}
} 

(4)邻接表的删除 

删除操作域链表删除操作一致,构建一个新节点来遍历全表和一个节点进行删除操作 

void graphdistory(graph* g)//删除
{
	int i;
	for(i=0;i<g->verties;++i)
	{
		edgenode* cur=g->node[i].first;//增加一个节点来容纳邻接表第一个节点
		while(cur)
		{
			edgenode* temp;//存放cur节点来进行删除操作
			temp=cur;
			cur=cur->next;
            free(temp);
		}
    }
    free(g->node);//将邻接表删除
    g->node=NULL;//将表置空
} 

(5)邻接表的插入 (头插法)

插入需要的元素有顶点对应的下标(u),弧尾元素下标值(v),以及弧上的权值(w) 

void graphinsert(graph* g ,int u,int v,int w)
{
	edgenode* newnode =(edgenode*)malloc(sizeof(edgenode));
	newnode->vertex=v;
	newnode->weight=w;
	newnode->next=g->node[u].first;//将下一个节点赋值给u节点的首节点
	g->node[u].first=newnode;//头插法插入newnode节点	 
}

(6)领接表的输出

就是将邻接表遍历输出,仅需注意输出的格式

void graphdisplay(graph* g)
{
	int i;
	for(i=0;i<g->verties;++i)//遍历输出元素
	{
		edgenode* cur=g->node[i].first;
		printf("%c->",g->node[i].vertex);//先输出元素的内容
		while(cur)
		{
			printf("%d(%d)->",cur->vertex,cur->weight);
			cur=cur->next;
		}
		printf("NULL\n");//用NULL代表最后一个指针为空
	}
}

(7)完整实现代码 

#include<stdio.h>
#include<stdlib.h>

typedef struct edgenode{
	int vertex;
	int weight;
	struct edgenode* next;
}edgenode;//顶点 

typedef struct vernode{
	char vertex;
	edgenode* first; 
}vernode;

typedef struct{
	int verties;
	vernode* node;
}graph;

void graphcreate(graph* g,int verties) 
{
	g->verties=verties;//将顶点赋予权值数量 
	g->node=(vernode*)malloc(sizeof(vernode)*verties); 
	int i;
	for(i=0;i<g->verties;++i)
	{
		printf("请输入第%d个元素\n",i+1);
		g->node[i].vertex=getchar();
		getchar();
		g->node[i].first=NULL; 
	}
} 

void graphdistory(graph* g)
{
	int i;
	for(i=0;i<g->verties;++i)
	{
		edgenode* cur=g->node[i].first;
		while(cur)
		{
			edgenode* temp;
			temp=cur;
			cur=cur->next;
            free(temp);
		}
    }
    free(g->node);
    g->node=NULL;
} 
 
void graphinsert(graph* g ,int u,int v,int w)
{
	edgenode* newnode =(edgenode*)malloc(sizeof(edgenode));
	newnode->vertex=v;
	newnode->weight=w;
	newnode->next=g->node[u].first;
	g->node[u].first=newnode;	 
}

void graphdisplay(graph* g)
{
	int i;
	for(i=0;i<g->verties;++i)
	{
		edgenode* cur=g->node[i].first;
		printf("%c->",g->node[i].vertex);
		while(cur)
		{
			printf("%d(%d)->",cur->vertex,cur->weight);
			cur=cur->next;
		}
		printf("NULL\n");
	}
}


int main()
{
	graph g;
	graphcreate(&g,5);//初始化节点为5个,元素内容分别为A,B,C,D,E
	graphinsert(&g,0,1,4);//下标为0的元素指向下标为1的元素,权值为4
	graphinsert(&g,0,2,2);//下标为0的元素指向下标为2的元素,权值为3
	graphinsert(&g,1,2,3);//下标为1的元素指向下标为2的元素,权值为3
	graphinsert(&g,2,3,4);//下标为2的元素指向下标为3的元素,权值为4
	graphinsert(&g,3,4,2);//下标为3的元素指向下标为4的元素,权值为2
	
	graphdisplay(&g);//输出表
	graphdistory(&g);//将表销毁
	return 0;
}

实现后的结果如图

如有错漏敬请指正 

 

 

 

 

 

 

 

 

 

 

 

  • 15
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值