图:
图是线性表和树的结合,图中任意两个数据对象之间都可能存在某种特定关系
两部分构成:结点和边,结点必不可少
存储:
邻接矩阵
书写:
1、二维数组存储边,其中的数据1表示右边,0表示无边;对于有权重的图,存储的数据也可以为权重
2、会有一个一维数组进行数据来代表各个结点,其下标被二维数组所使用
缺点:表中的数据一半都是重复的,浪费了空间和时间,更多的用于数据比较多的表
代码实现
基本思路:
- 定义图
- 定义边
- 初始化图
- 插入边中的元素
- 建立图
- 构造图
- 做好数据初始化的操作
- 给图做一个定义:包含顶点数、边、二维数组为矩阵,存放数据的位置
- 这里将邻接矩阵的图称为MGraph
#define MaxVertexNum 100 /*最大顶点数设为100*/
#define INFINITY 65535 /*用作当数据未被访问到*/
typedef int Vertex; /*用顶点的下标表示顶点*/
typedef int WeightType; /*设置边的权值*/
typedef char DataType; /*顶点存储的数据类型*/
typedef struct GNode* PtrToGNode;
struct GNode {
int Nv; /*顶点数*/
int Ne;/*边*/
WeightType G[MaxVertexNum][MaxVertexNum];/*邻接矩阵*/
DataType Data[MaxVertexNum];/*存放数据*/
};
typedef PtrToGNode MGraph;
- 构造边
- V1、V2为有向边的两端;
- weight表示权重
//构造边
typedef struct ENode* PtrToENode;
struct ENode {
Vertex V1, V2;
WeightType weight;
};
typedef PtrToENode Edge;
- 初始化图
- 传入元素为顶点的数目
- 为Graphmalloc申请一块空间
- 将Graph中的每一个元素存储为最大值(便于之后与访问过区分开来)
//初始化
MGraph CreateGraph(int VertexNum)
{
Vertex V, M;
MGraph Graph;
Graph = (MGraph)malloc(sizeof(struct GNode));
Graph->Nv = VertexNum;
Graph->Ne = 0;
for (V = 0; V < Graph->Nv; V++)
{
for (M = 0; M < Graph->Nv; M++)
{
Graph->G[V][M] = INFINITY;
}
}
return Graph;
}
- 插入元素
- 传入数据为图、边
- 对图中的数据进行更新
void InsertEdge(MGraph Graph, Edge E)
{
Graph->G[E->V1][E->V2] = E->weight;
Graph->G[E ->V2][E->V1] = E->weight;//无向图为什么也要插入边呢
}
5、建立图
- 通过输入有多少顶点的值、边的值来进行元素的插入、图的构建
MGraph BuidGraph()
{
MGraph Graph;
Edge E;
Vertex V;
int Nv, i;
scanf("%d", &Nv);
Graph = CreateGraph(Nv);
scanf("%d", &(Graph->Ne));
if (Graph->Ne != 0)
{
E = (Edge)malloc(sizeof(struct ENode));
for (i = 0; i < Graph->Ne; i++)
{
scanf("%d %d %d", &E->V1, &E->V2, &E->weight);
InsertEdge(Graph, E);
}
}
for (V = 0; V < Graph->Nv; V++)
{
scanf("%c", &(Graph->Data[V]));
}
return Graph;
}
邻接表
邻接表:头节点为一个数组,不同的数据下标代表不同链表的头部,其中每一个头节点后面跟上一串链表,链表中是从头节点到其它结点能通的路线
实现
1、定义关于邻接表的图
2、定义一个头结点的数组
3、有一个结构体存放每一个结点
4、每一条边
代码实现
1、定义图
- 顶点数
- 边数
- 邻接表
邻接表为LGraph
#define MaxVertexNum 100
typedef int Vertex;
typedef int WeightType;
typedef char DataType;
#include <stdlib.h>
//图结点的定义
typedef struct GNode* PtrToGNode;
struct GNode {
int Nv; //顶点数
int Ne;//边数
AdjList G;//邻接表
};
typedef PtrToGNode LGraph;
2、定义头节点数组
包含:一条指向结点的指针 进行数据存储
//头结点
typedef struct Vnode {
PtrToAdjVNode FirstEdge;
DataType Data; //很多时候顶点无数据,故Data可以不出现
}AdjList[MaxVertexNum];//一共有多少个顶点就有多大
3、存放每一个结点
需要存储:终点的数据、权重、指向下一个的指针
//每一个结点 -----放在每一个顶点的链表里面---只需要存储它的终点即可
typedef struct AdjVNode* PtrToAdjVNode;
struct AdjVNode {
Vertex AdjV;
WeightType Weight; //有权图需要存储权重
PtrToAdjVNode Next;
};
4、每一条边
//每一个结点 -----放在每一个顶点的链表里面---只需要存储它的终点即可
typedef struct AdjVNode* PtrToAdjVNode;
struct AdjVNode {
Vertex AdjV;
WeightType Weight; //有权图需要存储权重
PtrToAdjVNode Next;
};