一、邻接表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语言版)》