数据结构之用邻接表实现图(详解)

用邻接表表示图G=(V,E)时,对每个顶点i属于V,将它的所有邻接顶点存放在一个表中,这个表称为顶点i的邻接表。对每个顶点的邻接表存储在图G的邻接表数组中。

数据结构之用邻接表实现图(详解)_第1张图片

#include
#include
#include
//*********************************
//打印错误信息
void Error(char *s)
{
	printf("%s",s);
	exit(0);
}
//*********************************
//邻接表结点结构定义
typedef struct Inode *glink;
struct Inode{
	int v; //边的另一个顶点
	glink next; //邻接表指针
};
//创建一个新的邻接表结点
glink NewLNode(int v,glink next)
{
	glink x=(glink)malloc(sizeof(Inode));
		x->v=v;x->next=next;  //next为邻接表表首,即将新增的结点放在表首
	return x;
}
//用邻接表实现有向图的结构定义
typedef struct graph *Graph;
struct graph
{
	int n;//顶点数
	int e; //边数
	glink *adj;   //邻接表数组   adj存储有向图的邻接表
}Lgraph;

//***************************************
//创建一个用邻接表表示的有n个孤立顶点的有向图
Graph GraphInit(int n)
{
	int i;
	Graph G=(Graph)malloc(sizeof(graph));
	G->n=n;
	G->e=0;
	G->adj=(glink *)malloc((n+1)*sizeof(glink));
	for(i=0;i<=n;i++)
		G->adj[i]=0;
	return G;
}
//***************************************
//分别返回有向图G的顶点数和边数
	int GraphEdges(Graph G)  //返回边数
	{
		return G->e;
	}

	int GraphVertices(Graph G)  //返回顶点数
	{
		return G->n;
	}
//***************************************
//判断当前有向图G中的(i,j)边是否存在
	int GraphExist(int i,int j,Graph G)
	{
		glink p;
		if(i<1||j<1||i>G->n||j>G->n)  //如果i或j不在图的范围之内,则边不存在
			return 0;
		p=G->adj[i];  //G->adj[i]->v表示出发点为i,到达点为v,
		while(p&&p->v!=j)  //如果起点为i,顶点j则有边,返回1
			p=p->next;
		if(p) return 1;  //循环结束,(i,j)有边,返回1
		else return 0;
	}
//***************************************
//通过i的邻接表表首插入顶点j来实现向有向图中加入一条有向边(i,j)的操作
void GraphAdd(int i,int j,Graph G)
{
	if(i<1||j<1||i>G->n||j>G->n||i==j||GraphExist(i,j,G)) //首先判断是否(i,j)是否越界且是否已经存在边 ,如是,则打印错误信息,并退出
	Error("Bad input");
	G->adj[i]=NewLNode(j,G->adj[i]);//添加一条新的边, 在顶点位置插入j
	G->e++;
}
//***************************************
//删除有向图G中的边(i,j)
void GraphDelete(int i,int j,Graph G)
{
	glink p,q;
	if(i<1||j<1||i>G->n ||j>G->n || !GraphExist(i,j,G))//首先判断i和j是否越界以及是否已经存在边
		Error("Bad input");
	p=G->adj[i]; //将表首赋值给临时变量p,方便在删除边后释放p
	if(p->v==j)  //如果刚好是要删除的边对应的顶点,则将表首指向下一结点
	{	
		G->adj[i]=p->next;
		free(p);   //释放内存
	}
	else 
	{
	while(p&&p->v!=j) p=p->next;   //依次往后找,如果找到则结束循环
	if(p)			//找到的话就用临时变量,同理指向删除顶点的下一结点
	{
		q=p->next;
		p=q->next;
		free(q);
	}  
	}
}
//***************************************
//通过计算顶点i的邻接表长,返回有向图G中顶点i的出度
int OutDegree(int i,Graph G)
{
	glink p;
	int j=0;
	if(i<1||i>G->n) Error("Bad input");
	p=G->adj[i];  
	while(p){j++;p=p->next ;}   //从邻接表的表首开始依次往后找,求出表长
	return j;
}
//***************************************
//返回有向图G中顶点i的入度
int InDegree(int i,Graph G)
{
	int sum=0;
	int j;
	if(i<1||i>G->n ) 
		Error("Bad input");
	for(j=1;j<=G->n;j++)  //对每个顶点进行查询,如果(j,i)有边,则sum++
		if(GraphExist(j,i,G))
			sum++;
	return sum;
}

//***************************************
//输出有向图G的邻接表
void GraphOut(Graph G)
{
	glink p;
	int i;
	for(i=1;i<=G->n;i++)  //n个顶点,n次循环
	{
		p=G->adj[i];	//对每个顶点的邻接表进行打印
		while(p)
		{
			printf("i=%d,j=%d\t",i,p->v);  //i为起点,a[i]->v为以i为起点的抵达点   即(i,j)的j顶点
			p=p->next ;
		}
		printf("\n");
	}
}
//***************************************
int main()
{
	Graph G;
	G=GraphInit(10);
	GraphAdd(1,3,G);
	GraphAdd(2,4,G);
	GraphAdd(1,5,G);
	GraphAdd(3,7,G)	;
	GraphAdd(6,3,G);
	GraphAdd(8,2,G);
	GraphAdd(5,9,G);
	GraphOut(G);
	int i=1;
	printf("i=%d的出度:%d\n",i,OutDegree(i,G));
	printf("i=%d的入度:%d\n",i,InDegree(i,G));
	return 0;
}


你可能感兴趣的:(数据结构)