数据结构——图的链式存储结构实现

一、邻接表Adiacency List(链式)表示法

  • 对每个顶点vi 建立一个单链表,把与vi有关联的边的信息(即度或出度边)链接起来,表中每个结点都设为3个域;

 

 

  • 每个单链表还应当附设一个头结点(设为2个域),存vi信息;
  • 每个单链表的头结点另外用顺序存储结构存储。
  • 对于任一确定的无向图邻接表不唯一
  • 邻接表的空间复杂度为O(n+e),多用于稀疏图的存储(e<<n^2)

c语言实现:

/*
文件名:AdjacencyList.h
描述:图的链式存储结构,邻接表
时间:2018.11.24
	2018.12.26修改
*/
#pragma once

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

/*-----------------图的邻接链表存储表示------------------*/
#define MAX_VERTEX_NUM	20		//最大定点数
#define InfoType int	//该弧相关信息类型
#define VertexType int		//顶点类型
typedef struct ArcNode {
	//邻接表结点类型定义
	int adjvex;		//该弧所指向的顶点的位置
	struct ArcNode *nextarc;		//指向下一条弧的指针
	InfoType *info;		//该弧相关信息的指针
}ArcNode;

typedef struct VNode {
	//图顶点类型定义
	VertexType data;	//顶点信息
	ArcNode	*firstarc;	//指向第一条依附该顶点的弧的指针
}VNode,AdjList[MAX_VERTEX_NUM];

typedef struct {
	//图类型定义
	AdjList vretices;	//邻接表
	int vexnum, arcnum;		//图的当前顶点数和弧数
	int kind;		//图的种类
}ALGraph;

int what(ALGraph G, int adj)
{
	int i = 0;
	for (i = 0; i < G.vexnum; i++)
	{
		if (G.vretices[i].data == adj) return i;
	}
	return -1;

}

void CreateDG(ALGraph *G)	//邻接表构建有向图G
{
	ArcNode *p = NULL;
	ArcNode **q = NULL;
	int i, j, temp_adj;
	InfoType temp_info;
	printf("输入图的顶点数,弧数");
	scanf("%d %d", &G->vexnum, &G->arcnum);
	for (i = 0; i < G->vexnum; i++)		//输入顶点值及初始化邻接表指针
	{
		printf("输入第%d个顶点:", i + 1);
		scanf("%d", &(G->vretices[i].data));
		G->vretices[i].firstarc = NULL;		//初始化指针,杜绝野指针
	}
	for (i = 0; i < G->vexnum; i++)
	{
		for (j = 0, temp_adj = 0; temp_adj != -1; j++)	//输入的弧尾为-1时表示该顶点的弧已输入完
		{
			printf("输入第顶点%d的第%d条弧的弧尾,弧信息", G->vretices[i].data, j+1);
			scanf("%d %d", &temp_adj, &temp_info);
			temp_adj = what(*G, temp_adj);
			if (temp_adj == -1)
			{
				if (j == 0)
				{
					G->vretices[i].firstarc = NULL;
				}
				else
				{	
					free(p);
					p = NULL;
					*q = NULL;
				}
			}
			else 
			{
				if (j == 0)
				{
					G->vretices[i].firstarc = (ArcNode *)malloc(sizeof(ArcNode));	//给邻接表的第i个头结点开辟第一个表结点
					
					G->vretices[i].firstarc->info = (InfoType *)malloc(sizeof(InfoType));	//给邻接表的第i个头结点的第一个表结点的info指针开辟空间
					G->vretices[i].firstarc->nextarc = (ArcNode *)malloc(sizeof(ArcNode));	//给下一个指向开辟空间
					p = G->vretices[i].firstarc;
					p->adjvex = temp_adj;
					*(p->info) = temp_info;
				}
				else
				{
					p->nextarc = (ArcNode *)malloc(sizeof(ArcNode));
					p->info = (InfoType *)malloc(sizeof(InfoType));
					p->adjvex = temp_adj;
					*(p->info) = temp_info;
				}
				q = &(p->nextarc);
				p = p->nextarc;

			}
		}//for_j

	}//for_i
	printf("创建成功\n");
}//CreateDG

运行结果:

二、十字链表(针对有向图)

  • 每条弧对应一个结点(称为弧结点5个域)
  • 每个顶点也对应一个结点(称为顶点结点3个域)

 

C语言实现:

/*
文件名:OrthogonaList.c
描述:图的链式存储结构,十字链表,针对有向图
时间:2018.11.24
*/

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

/*---------------有向图十字链表存储表示----------------*/
#define Max_VERTEX_NUM	20		//最大顶点数
#define InfoType int	//该弧相关信息类型
#define VertexType int		//顶点类型


typedef struct ArcBox {
	//十字链表结点定义
	int tailvex, headvex;		//该弧的尾和头顶点的位置
	struct ArcBox *hlink, *tlink;	//分别为弧头相同和弧尾相同的弧的链域
	InfoType *info;		//该弧相关信息的指针
}ArcBox;

typedef struct VexNode {
	//图顶点类型定义
	VertexType data;
	ArcBox *firstin, *firstout;		//分别指向该顶点第一条入弧和出弧
}VexNode;

typedef struct {
	VexNode xlist[Max_VERTEX_NUM];		//表头向量
	int vexnum, arcnum;		//有向图的当前顶点数和弧数
}OLGraph;

int LocateVex(OLGraph *G, VertexType v)		//返回顶点v在图G中的位置
{
	int i;
	for (i = 0; i < G->vexnum; i++)
	{
		if (v == G->xlist[i].data)
		{
			return i;
		}
	}
}//LocateVex

void CreateDG(OLGraph *G)		//采用十字链表存储表示,构造有向图G
{
	int *IncInfo=(InfoType*)malloc(sizeof(InfoType));
	int i, j, k;
	ArcBox *p = NULL;
	VertexType v1, v2;
	printf("输入当前图的顶点数,弧数,弧是否含有其它信息(1.是,0.否):");
	scanf("%d %d %d", &G->vexnum, &G->arcnum, IncInfo);
	for (i = 0; i < G->vexnum; i++)		//构造表头向量
	{
		printf("输入第%d个顶点:", i + 1);
		scanf("%d", &(G->xlist[i].data));		//输入定点值
		G->xlist[i].firstin = NULL;		//初始化指针,杜绝野指针
		G->xlist[i].firstout = NULL;
	}
	for (k = 0; k < G->arcnum; k++)
	{
		printf("输入弧的起始顶点和终止顶点:");
		scanf("%d %d", &v1, &v2);
		if (IncInfo!=NULL && *IncInfo != 0)
		{
			printf("输入弧信息:");
			scanf("%d", IncInfo);
		}
		else
		{
			IncInfo = NULL;
		}
		i = LocateVex(G, v1);	//确定v1,v2在G中的位置
		j = LocateVex(G, v2);
		p = (ArcBox*)malloc(sizeof(ArcBox));
	//	*p = { i,j,G->xlist[j].firstin,G->xlist[j].firstout,IncInfo };	//对弧结点赋值
				//{tailvex,headvex,hlink,tlink,info}
		p->tailvex = i;
		p->headvex = j;
		p->hlink = G->xlist[j].firstin;
		p->tlink = G->xlist[j].firstout;
		p->info = IncInfo;
		G->xlist[j].firstin = G->xlist[i].firstout = p;		//完成在入弧和出弧链头的插入
	}
	printf("构建成功\n");
}//CreateDG

int main()
{
	OLGraph G;
	CreateDG(&G);
	return 0;
}

运行结果:

三、邻接多重表(针对无向图) 

这是无向图的另一种链式存储结构,当对边操作时,无向图应采用此种结构存储。

  • 每条边只对应一个结点(称为边结点),设立6个域;
  • 每个顶点也对应一个结点(顶点结点),设立2个域;

C语言实现:

/*
文件名:AdjacencyMultilist.c
描述:图的链式存储结构,邻接多重表,针对无向图
时间:2018.11.24
*/

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

/*---------------无向图的邻接多重表表存储表示----------------*/
#define Max_VERTEX_NUM	20		//最大顶点数
#define InfoType int	//该弧相关信息类型
#define VertexType int		//顶点类型
#define VisitIf int		//访问标记类型
typedef struct EBox {
	//边结点定义
	VisitIf		mark;		//访问标记
	int ivex, jvex;		//该边依附的两个顶点的位置
	struct EBox *ilink, *jlink;		//分别指向衣服这两个顶点的下一条边
	InfoType *info;		//该边信息指针
}EBox;

typedef struct VexBox {
	//顶点定义
	VertexType data;
	EBox *firstedge;		//指向第一条依附该顶点的边
}VexBox;

typedef struct {
	VexBox adjmulist[Max_VERTEX_NUM];	//顶点数组
	int vexnum, edgenum;		//无向图的当前顶点数和边数
}AMLGraph;

int LocateVex(AMLGraph *G, VertexType v)		//返回顶点v在图G中的位置
{
	int i;
	for (i = 0; i < G->vexnum; i++)
	{
		if (v == G->adjmulist[i].data)
		{
			return i;
		}
	}
}//LocateVex

void CreateUDG(AMLGraph *G)
{
	int *IncInfo = (InfoType*)malloc(sizeof(InfoType));
	int i, j, k;
	EBox *p = NULL;
	VertexType v1, v2;
	printf("输入当前图的顶点数,边数,边是否含有其它信息(1.是,0.否):");
	scanf("%d %d %d", &G->vexnum, &G->edgenum, IncInfo);
	for (i = 0; i < G->vexnum; i++)		//构造表头向量
	{
		printf("输入第%d个顶点:", i + 1);
		scanf("%d", &(G->adjmulist[i].data));		//输入定点值
		G->adjmulist[i].firstedge = NULL;		//初始化指针,杜绝野指针
	}
	for (k = 0; k < G->edgenum; k++)
	{
		printf("输入边的两个顶点:");
		scanf("%d %d", &v1, &v2);
		if (IncInfo!=NULL && *IncInfo != 0)
		{
			printf("输入弧信息:");
			scanf("%d", IncInfo);
		}
		else
		{
			IncInfo = NULL;
		}
		i = LocateVex(G, v1);	//确定v1,v2在G中的位置
		j = LocateVex(G, v2);
		p = (EBox*)malloc(sizeof(EBox));
		//	*p = { i,j,G->xlist[j].firstin,G->xlist[j].firstout,IncInfo };	//对弧结点赋值
		//{tailvex,headvex,hlink,tlink,info}
		p->ivex = i;
		p->jvex = j;
		p->ilink = G->adjmulist[i].firstedge;
		p->jlink = G->adjmulist[i].firstedge;
		G->adjmulist[i].firstedge = G->adjmulist[j].firstedge = p;		//完成在入弧和出弧链头的插入
	}
	printf("创建成功\n");
}//createUDG

int main()
{
	AMLGraph G;
	CreateUDG(&G);
	return 0;
}



运行结果:

 

参考:《数据结构(c语言版)》

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值