数据结构(C语言实现)-图(1)(图的存储结构、图的创建)

图的数组表示法(邻接矩阵)

图的邻接矩阵存储方式:用两个数组来表示图,一个一维数组存储图中顶点的信息,一个二维数组存储图中边的信息。对于网(边上带权的图),二维数组中存储权值,无连接的顶点之间权值为infinity(无穷大)。
在这里插入图片描述
代码实现如下:

#include "head.h"

#define INFINITY 65535
#define MAX_VERTEX_NUM 20    //最大顶点个数
typedef enum GraphKind{DG,DN,UDG,UDN}; //有向图,有向网,无向图,无向网
typedef char Elemtype;

typedef struct ArcCell{
	int adj;               //对图,1/0表示是否邻接;对网,用数字表示权值
}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];//以结构体为元素的**弧数组**

typedef struct{
	Elemtype vexs[MAX_VERTEX_NUM];//**顶点数组**
	AdjMatrix arcs;               //邻接矩阵(弧数组)
	int vexnum,arcnum;            //顶点数,弧数
	GraphKind kind;               //图的类型
}MGraph;   //邻接矩阵

void CreateGraph(MGraph *G)
{
	int kind;
	printf("输入图的类型对应的序号(0.DG/1.DN/2.UDG/3.UDN):");
	scanf_s("%d",&kind);
	switch (kind)
	{
	case 0:CreateDG(G); break;
	case 1:CreateDN(G); break;
	case 2:CreateUDG(G); break;
	case 3:CreateUDN(G); break;
	default :return ERROR;
	}
}

int LocateVex(MGraph *G,Elemtype point)//确定顶点point在图G(顶点数组)中的序号
{
	for(int i = 0;i<G->vexnum;i++)
		if(G->vexs[i] == point)
			return i;
}

void CreateUDN(MGraph *G)      //无向网
{
	int weight;                //边的权值
	Elemtype origin,terminus;  //边的起点、终点
	printf("请输入顶点数与弧数:\n");
	scanf_s("%d %d",&(G->vexnum),&(G->arcnum));
	for(int i = 0;i<G->vexnum;i++)
	{
		printf("输入顶点值:\n");
		scanf_s("%c",&(G->vexs[i]));
	}
	
	for(int i = 0;i<G->vexnum;i++)          //邻接矩阵初始化
		for(int = 0;j<G->vexnum;j++)
		{
			G->arcs[i][j].adj = INFINITY;
		}
	
	for(int k = 0;k<G->arcnum;k++)         //邻接矩阵赋值
	{
		printf("请输入一条边的两端及权值:\n");
		scanf_s("%c %c %d",&origin,&terminus,&weight);
		int i = LocateVex(G,origin);
		int j = LocateVex(G,terminus);
		G->arcs[i][j].adj = weight;
		G->arcs[j][i].adj = weight;
	}
	printf("创建成功\n");
}

void CreateUDG(MGraph *G)	//无向图
{
	int origin, terminus; 	//边的起点,终点
	printf("输入图的顶点数、弧数:");
	scanf_s("%d %d", &(G->vexnum), &(G->arcnum));
	for (int i = 0; i < G->vexnum; i++)	//将顶点值存储进去
	{
		printf("输入顶点值:");
		scanf_s("%c", &(G->vexs[i]));
	}
	
	for (int i = 0; i < G->vexnum; i++)	//初始化邻接矩阵
		for (int j = 0; j < G->vexnum; j++)
		{
			G->arcs[i][j].adj = 0;
		}
	for (int k = 0; k < G->arcnum; k++)
	{
		printf("输入一条边的两端");
		scanf_s("%c %c", &origin, &terminus);
		int i = LocateVex(G, origin);
		int j = LocateVex(G, terminus);
		G->arcs[i][j].adj = 1;
		G->arcs[j][i].adj = 1;
	}
	printf("创建成功\n");
}

void CreateDG(MGraph *G)//有向图
{
	int origin, terminus;
	printf("输入图的顶点数,弧数:\n");
	scanf_s("%d %d",&(G->vexnum),&(G->arcnum));
	for (int i = 0; i < G->vexnum; i++)    //顶点赋值
	{
		printf("输入顶点值:");
		scanf_s("%c",&(G->vexs[i]));
	}

	for (int i = 0; i < G->vexnum; i++)    //初始化邻接矩阵
	{
		for (int j = 0; j < G->vexnum; j++)
		{
			G->arcs[i][j].adj = 0;
		}
	}

	for (int k = 0; k < G->arcnum; k++)
	{
		printf("输入一条边的起点终点");
		scanf_s("%c %c", &origin, &terminus);
		int i = LocateVex(G, origin);
		int j = LocateVex(G, terminus);
		G->arcs[i][j].adj = 1;
	}
	printf("创建成功\n");
}


void CreateDN(MGraph *G)		//有向网
{
	int origin, terminus, weight; 	//边的起点,终点,权值
	printf("输入图的顶点数 弧数");
	scanf_s("%d %d", &(G->vexnum), &(G->arcnum));
	for (int i = 0; i < G->vexnum; i++)	//将顶点值存储进去
	{
		printf("输入顶点值:");
		scanf_s("%c", &(G->vexs[i]));
	}
	
	for (int i = 0; i < G->vexnum; i++)	//初始化邻接矩阵
		for (int j = 0; j < G->vexnum; j++)
		{
			G->arcs[i][j].adj = INFINITY;
		}
	for (int int k = 0; k < G->arcnum; k++)
	{
		printf("输入一条边的起点、终点以及权值");
		scanf_s("%c %c %d", &origin, &terminus, &weight);
		i = LocateVex(G, origin);
		j = LocateVex(G, terminus);
		G->arcs[i][j].adj = weight;
	}
	printf("创建成功\n");
}

图的邻接表

邻接表是图的的一种链式存储结构。邻接表由结点表(数组)和边表(链表)组成。有向图及无向图的邻接表示意图如图所示:
在这里插入图片描述
在这里插入图片描述
有时为了确定顶点的入度/指向顶点的弧,会建立有向图逆邻接表,如下所示:
在这里插入图片描述
代码实现如下:

#include "head.h"
#define MAX_VERTEX_NUM 20
typedef char Elemtype;
typedef enum Graphtype{DG,DN,UDG,UDN};//

typedef struct ArcNode{
	int adjvex;         //该弧指向的顶点 在结点表中的位置
	ArcNode *nextarc;   //指向下一条弧的指针
	int info;           //权值
}ArcNode;//边表结点

typedef struct VerNode{
	Elemtype data;      //顶点存储的数据
	ArcNode *firstarc;  //指向第一个边结点的指针
}VerNode,AdjList[MAX_VERTEX_NUM];//结点表

typedef struct{
	AdjList vertices;    //结点表
	int vexnum,arcnum;   //顶点个数、弧个数
	Graphtype kind;      //图的类型
}ALGraph,*Graph;

void CreateALGraph(ALGraph *G)
{
	ArcNode *arc;
	printf("输入顶点和边数:");
	scanf_s("%d %d",&G->vexnum,&G->arcnum);
	
	for(int i = 0;i < G->vexnum; i++)  //建立结点表
	{
		scanf_s("%c",&G->vertices[i].data);
		G->vertices[i].firstarc = NULL;
	}
	for(int j = 0;j<G->arcnum;j++)    //建立边表
	{
		int weight = 0;               //弧的权重
		int start,end;                //弧的起点和终点
		arc = (ArcNode*)malloc(sizeof(ArcNode)); //建立边结点
		scanf_s("%d %d %d"&start,&end,&weight);
		arc->info = weight;           //给边赋权值
		arc->adjvex = end;            //弧指向的顶点(所在结点表位置序号)
		arc->nextarc = G->vertices[start].firstarc; //该弧结点指向与结点表相连的弧
		G->vertices[start].firstarc = arc;          //结点表指针域指向该弧结点
	}
}

图的十字链表

十字链表是有向图的另一种链式存储结构,可以看成邻接表逆邻接表结合起来的一种链表。
存储结构如图所示:
在这里插入图片描述

#include "head.h"
#define MAX_VERTEX_NUM 20
typedef char Elemtype;

typedef struct ArcNode{
	int tailvex,headvex;  //弧的头尾结点在顶点表中的序号
	ArcNode *hlink,*tlink;//弧的头/尾相同的下一条弧
	int info;             //弧的权值
}ArcNode;

typedef struct VexNode{
	Elemtype data;             //顶点的数据域
	ArcNode *firstin,*firstout;//顶点的链域
}VexNode;

typedef struct{
	VexNode Vexlist[MAX_VERTEX_NUM];//顶点结点表
	int vexnum,arcnum;              //顶点、弧的个数
}OLGraph;

int LocateVex(OLGraph *G,Elemtype data)//定位某元素在顶点表中的序号
{
	for(int i = 0; i < G->vexnum; i++)
		if(G->Vexlist[i] == data)
			return i;
}

void CreateOLGraph(OLGraph *G)
{
	printf("请输入顶点和弧的数量:\n");
	scanf_s("%d %d",&G->vexnum,&G->arcnum);
	for(int i=0;i<G->vexnum;i++)
	{
		printf("请依次输入顶点数据:");
		scanf_s("%c",&G->Vexlist[i].data); //输入数据
		G->Vexlist[i].firstin = NULL;      //初始化指针域
		G->Vexlist[i].firstout = NULL;
	}
	
	ArcNode *p;
	Elemtype vstart,vend,weight;
	for(int k = 0;k < G->arcnum;k++)
	{
		printf("请依次输入弧的起点和终点对应的数据以及权值:");
		scanf_s("%c %c %d",&vstart,&vend,&weight);
		int i = LocateVex(G,vstart);
		int j = LocateVex(G,vend);
		p = (ArcNode*)malloc(sizeof(ArcNode));//构造弧结点
		p->info = weight;
		p->headvex = i;
		p->tailvex = j;
		p->hlink = G->Vexlist[i].firstin;    //让此弧结点指向此时与顶点相连的弧
		p->tlink = G->Vexlist[j].firstout;
		G->Vexlist[i].firstin = p;           //使顶点链域改为指向该弧结点
		G->Vexlist[j].firstout = p;
	} 
}

邻接多重表

邻接多重表是无向图的一种链式存储结构,它与十字链表有些类似,弧结点多了一个标志域,用来记录该边是否被搜索过,每个顶点结点则只有一个指向弧的指针域(因为是无向图,不需要考虑出度和入度)。

  • 15
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值