数据结构-图

1、图的定义

图:是一种灵活的数据结构,一般作为一种模型用来定义对象之间的关系或者联系。对象由顶点表示,而对象之间的关系或关联则通过顶点之间的边来表示。

2、图的应用

图算法、统计网络跳数、拓扑排序、图着色、哈密顿圈问题、分团问题、可序列化冲突

3、图的代码实现

/*graph.h*/
#ifndef	GRAPH_H
#define GRAPH_H
#include <stdlib.h>
#include "list.h"
#include "set.h"

/*define a structure for adjacency lists*/
typedef struct AdjList_
{
	void *vertex;
	Set adjacent;
}AdjList;

/*define structure for graphs*/
typedef struct Graph_
{
	int		vcount;
	int		ecount;
	int		(*match)(const void *key1,const void *key2);
	void	(*destroy)(void *data);
	List	adjlists;
}Graph;

/*define colors for vertices in graphs*/
typedef	enum VertexColor_ {white,gray,black}  VertexColor;

/*public interface*/
void graph_init(Graph *graph,int (*match)(const void *key1,const void *key2),void (*destroy)(void *data));
void graph_destroy(Graph *graph);
int graph_ins_vertex(Graph *graph,const void *data);
int graph_ins_edge(Graph *graph,const void *data1,const void *data2);
int graph_rem_vertex(Graph *graph,void **data);
int graph_rem_edge(Graph *graph,void *data1,void **data2);
int graph_adjlist(const Graph *graph,const void *data,AdjList **adjlist);
int graph_is_adjacent(const Graph *graph,const void *data1,const void *data2);
#define	graph_adjlists(graph) ((graph)->dajlists)
#define	graph_vcount(graph) ((graph)->vcount)
#define	graph_ecount(graph) ((graph)->ecount)

#endif
/*graph.c*/
#include<stdlib.h>
#include<string.h>
#include"graph.h"
#include"list.h"
#include"set.h"

void graph_init(Graph *graph,int (*match)(const void *key1,const void *key2),void (*destroy)(void *data))
{
	/*initialize the graph*/
	graph->vcount=0;
	graph->ecount=0;
	graph->match=match;
	graph->destroy=destroy;

	/*initialize the list of adjacentcy-list structure*/
	list_init(&graph->adjlists,NULL);
	return ;
}

void graph_destroy(Graph *graph)
{
	AdjList	*adjlist;

	/*remove each adjacency-list structure and destroy its adjacency list*/
	while(list_size(&graph->adjlists)>0)
	{
		if(list_rem_next(&graph->adjlists,NULL,(void **)&adjlist)==0)
		{
			set_destroy(&adjlist->adjacent);
			if(graph->destroy!=NULL)
				graph->destroy(adjlist->vertex);
			free(adjlist);
		}
	}

	/*destroy the list of adjacency-list structures,which is now empty*/
	list_destroy(&graph->adjlists);

	/*clear the structure*/
	memset(graph,0,sizeof(Graph));
	return ;
}

int graph_ins_vertex(Graph *graph,const void *data)
{
	ListElmt *element;
	AdjList	 *adjlist;
	int retval;

	/*do not allow the insertion of duplicate vertices*/
	for(element=list_head(&graph->adjlists);element !=NULL;element=list_next(element))
	{
		if(graph->match(data,((AdjList *)list_data(element))->vertex))
			return 1;
	}

	/*insert the vertex*/
	if((adjlist=(AdjList *)malloc(sizeof(AdjList)))==NULL)
		return -1;
	adjlist->vertex=(void *)data;
	set_init(&adjlist->adjacent,graph->match,NULL);
	if((retval=list_ins_next(&graph->adjlists,list_tail(&graph->adjlists),adjlist))!=0)
	{
		return retval;
	}

	/*adjust the vertex count to account for the inserted vetex*/
	graph->vcount++;
	return 0;
}

int graph_ins_edge(Graph *graph,const void *data1,const void *data2)
{
	ListElmt *element;
	int retval;

	/*do not allow insertion of an edge without both its vertices in the graph*/
	for(element=list_head(&graph->adjlists);element !=NULL;element=list_next(element))
	{
		if(graph->match(data2,((AdjList *)list_data(element))->vertex))
			break;
	}
	if(element==NULL)
		return -1;
	for(element=list_head(&graph->adjlists);element !=NULL;element=list_next(element))
	{
		if(graph->match(data1,((AdjList *)list_data(element))->vertex))
			break;
	}
	if(element==NULL)
		return -1;

	/*insert the second vertex into the adjacency list of the first vertex*/
	if((retval=set_insert(&((AdjList *)list_data(element))->adjacent,data2))!=0)
	{
		return retval;
	}

	/*Adjust the edge count to account for the inserted edge*/
	graph->ecount++;
	return 0;
}

int graph_rem_vertex(Graph *graph,void **data)
{
	ListElmt *element,*temp,*prev;
	AdjList *adjlist;
	int found;

	/*traverse each adjacency list and the vertice it contains*/
	prev=NULL;
	found=0;
	for(element=list_head(&graph->adjlists);element !=NULL;element=list_next(element))
	{
		/*do not allow removal of the vertex if it is in an adjacency list*/
		if(set_is_member(&((AdjList *)list_data(element))->adjacent,*data))
			return -1;

		/*keep a pointer to the vertex to be removed*/
		if(graph->match(*data,((AdjList *)list_data(element))->vertex))
		{
			temp=element;
			found=1;
		}

		/*keep a pointer to the vertex before the vertex to be removed*/
		if(!found)
			prev=element;
	}

	/*return if the vertex was not found*/
	if(!found)
		return -1;

	/*do not allow removal of the tex if its adjacency list is not empty*/
	if(set_size(&((AdjList *)list_data(temp))->adjacent)>0)
		return -1;

	/*remove the vertex*/
	if(list_rem_next(&graph->adjlists,prev,(void **)&adjlist)!=0)
		return -1;

	/*free the storage allocated by the abstract datatype*/
	*data=adjlist->vertex;
	free(adjlist);

	/*adjust the vertex count to account for the removed vertex*/
	graph->vcount--;
	return 0;

}

int graph_rem_edge(Graph *graph,void *data1,void **data2)
{
	ListElmt *element;

	/*locate the adjacency list for the first vertex*/
	for(element=list_head(&graph->adjlists);element !=NULL;element=list_next(element))
	{
		if(graph->match(data1,((AdjList *)list_data(element))->vertex))
			break;
	}
	if(element==NULL)
		return -1;

	/*remove the second vertex from the adjacency list of the first vertex*/
	if(set_remove(&((AdjList *)list_data(element))->adjacent,data2)!=0)
		return -1;

	/*adjust the edge count to account for the removed edge*/
	graph->ecount--;
	return 0;
}

int graph_adjlist(const Graph *graph,const void *data,AdjList **adjlist)
{
	ListElmt *element,*prev;

	/*locate the adjacency list for the  vertex*/
	prev=NULL;
	for(element=list_head(&graph->adjlists);element !=NULL;element=list_next(element))
	{
		if(graph->match(data,((AdjList *)list_data(element))->vertex))
			break;
	}

	/*return if the vertex was not found*/
	if(element==NULL)
		return -1;

	/*pass back the adjacency list for the vertex*/
	*adjlist=list_data(element);
	return 0;
}

int graph_is_adjacent(const Graph *graph,const void *data1,const void *data2)
{
		ListElmt *element,*prev;

	/*locate the adjacency list for the first vertex*/
	prev=NULL;
	for(element=list_head(&graph->adjlists);element !=NULL;element=list_next(element))
	{
		if(graph->match(data1,((AdjList *)list_data(element))->vertex))
			break;
		prev=element;
	}

	/*return if the vertex was not found*/
	if(element==NULL)
		return 0;

	/*return whether the second vertex is in the adjacency list of the first*/
	return set_is_member(&((AdjList *)list_data(element))->adjacent,data2);
}

应用实例:

后续补上

数据结构-图

时间: 2024-10-25 11:57:38

数据结构-图的相关文章

?数据结构-图之强连通

数据结构-图之强连通 在一个无向图G中,若从顶点v_i到顶点v_j有路径相连(当然从v_j到v_i也一定有路径),则称v_i和v_j是连通的.如果G是有向图,那么连接v_i和v_j的路径中所有的边都必须同向.如果图中任意两点都是连通的,那么图被称作连通图.图的连通性是图的基本性质. 连通分量:无向图G的一个极大连通子图称为G的一个连通分量(或连通分支).连通图只有一个连通分量,即其自身:非连通的无向图有多个连通分量. 初级通路:通路中所有的顶点互不相同.初级通路必为简单通路,但反之不真. 强连通

C#与数据结构--图的遍历

C#与数据结构--图的遍历 8.2 图的存储结构 图 的存储结构除了要存储图中各个顶点的本身的信息外,同时还要存储顶点与顶点之间的所有关系(边的信息),因此,图的结构比较复杂,很难以数据元素在存储区 中的物理位置来表示元素之间的关系,但也正是由于其任意的特性,故物理表示方法很多.常用的图的存储结构有邻接矩阵.邻接表.十字链表和邻接多重表. 8.2.1  邻接矩阵表示法 对于一个具有n个顶点的图,可以使用n*n的矩阵(二维数组)来表示它们间的邻接关系.图8.10和图8.11中,矩阵A(i,j)=1

数据结构--图 的JAVA实现(上)

1,摘要: 本系列文章主要学习如何使用JAVA语言以邻接表的方式实现了数据结构---图(Graph),这是第一篇文章,学习如何用JAVA来表示图的顶点.从数据的表示方法来说,有二种表示图的方式:一种是邻接矩阵,其实是一个二维数组:一种是邻接表,其实是一个顶点表,每个顶点又拥有一个边列表.下图是图的邻接表表示. 从图中可以看出,图的实现需要能够表示顶点表,能够表示边表.邻接表指是的哪部分呢?每个顶点都有一个邻接表,一个指定顶点的邻接表中,起始顶点表示边的起点,其他顶点表示边的终点.这样,就可以用邻

数据结构--图 的JAVA实现(下)

在上一篇文章中记录了如何实现图的邻接表.本文借助上一篇文章实现的邻接表来表示一个有向无环图. 1,概述 图的实现与邻接表的实现最大的不同就是,图的实现需要定义一个数据结构来存储所有的顶点以及能够对图进行什么操作,而邻接表的实现重点关注的图中顶点的实现,即怎么定义JAVA类来表示顶点,以及能够对顶点进行什么操作. 为了存储图中所有的顶点,定义了一个Map<key, value>,实际实现为LinkedHashMap<T, VertexInterface<T>>,key 为

数据结构--图--图的数组存储表示,深度优先搜索遍历和广度优先搜索遍历

图有四种存储结构:数组,邻接表,十字链表,邻接多重表.下面以数组为存储结构来实现图的深度优先搜索遍历和广度优先搜索遍历.其中广度优先搜索遍历中有用到STL中的queue,注意头文件的包含.具体代码如下: //图的数组(邻接矩阵)存储表示和深度优先遍历 const int MAX_VERTEX_NUM=20; //最大顶点数 typedef enum {DG,DN,UDG,UDN} GraphKind ;//(有向图,有向网,无向图,无向网) typedef int VRType; typedef

数据结构--图--最小生成树(Prim算法)

构造连通网的最小生成树,就是使生成树的边的权值之和最小化.常用的有Prim和Kruskal算法.先看Prim算法:假设N={V,{E}}是连通网,TE是N上最小生成树中边的集合.算法从U={u0}(uo属于V),TE={}开始,重复执行下述操作:在所有u属于U,v属于V-U的边(u,v)属于E中找到代价最小的一条边(u0,v0)并入集合TE,同时v0并入U,直至U=V为止.此时TE中必有n-1条边,T={V,{TE}}为N的最小生成树.为实现此算法,需另设一个辅助数组closedge,以记录从U

java 数据结构 图中使用的一些常用算法 图的存储结构 邻接矩阵:图的邻接矩阵存储方式是用两个数组来标示图。一个一位数组存储图顶点的信息,一个二维数组(称为邻接矩阵)存储图中边或者弧的信息。 设图G有n个顶点,则邻接矩阵是一个n*n的方阵,定义为: 实例如下,左图是一个无向图。右图是邻接矩阵表示:

以下内容主要来自大话数据结构之中,部分内容参考互联网中其他前辈的博客. 图的定义 图是由顶点的有穷非空集合和顶点之间边的集合组成,通过表示为G(V,E),其中,G标示一个图,V是图G中顶点的集合,E是图G中边的集合. 无边图:若顶点Vi到Vj之间的边没有方向,则称这条边为无项边(Edge),用序偶对(Vi,Vj)标示. 对于下图无向图G1来说,G1=(V1, {E1}),其中顶点集合V1={A,B,C,D}:边集合E1={(A,B),(B,C),(C,D),(D,A),(A,C)}: 有向图:若

数据结构-图存储表示之邻接表

邻接表 在图论中,邻接表代表一个图中的所有边或弧. 邻接表存储表示,需要保存一个顺序存储的顶点表和每个顶点上的边的链接表. 邻接表(Adjacency List),即数组与链表相结合的存储方法. 如果是无向图,那么每条边由两个结点组成,分别代表边的两个端点: 如果是有向图,那么每条边是一个结点对,分别代表边的始点和终点. 一般来说,邻接表是无向的. 在计算机科学中,邻接表描述一种紧密相关的数据结构,用于表征图.在邻接表的表示中,对于图中的每个顶点,我们将保存所有其它与之相连的顶点(即"邻接表&q

数据结构——图

图(Graph) (参考资料:<大话数据结构><算法导论>) 图是由顶点的有穷非空集合和顶点之间的边的集合组成,通常表示为:G(V,E),其中G表示一个图,V是图G中顶点(Vertex)的集合,E是图中边的集合. 图的相关术语 1.无向图与有向图 无向图:图中任意两个顶点u和v之间的边没有方向(无向边),每一条无向边用无序偶对(u,v)或(v,u)表示. 无向完全图:任意两个顶点之间都存在边,边个数:n*(n-1)/2(n个顶点). 有向图:图中任意两个顶点u和v之间的边具有方向(