图的存储
邻接矩阵
考虑到图是由顶点和边(弧)两部分组成,那就分成两部分存储。
图的邻接矩阵存储方式是用两个数组表示图,一个一维数组存储图中的顶点信息,一个二维数组(称为邻接矩阵)存储图中的边或者弧的信息。
设图G中有n个顶点,则邻接矩阵是一个n×n 的方阵,定义为
arc[i][j]={1,0,若(vi,vj)∈E或<vi,vj>∈E反之
实际举例:
无向图:
顶点数组:
A | B | C | D |
---|
边数组:
顶点ABCDA0101B1011C0101D1110
特点:
- 无向图的邻接矩阵是一个对称矩阵。主对角线(左上角–>右下角)上线的元素是相等的。
- 某个顶点的度等于第i行的元素之和.B的度是1+0+1+1=3 度为3
- 顶点i的所有邻接点就是第i行的元素中为1的点.
有向图:
顶点数组:
A | B | C | D |
---|
边数组:
顶点ABCDA0000B1000C1000D0110
有向图的邻接矩阵一般不是对称的。
网图
每条边上带权的图叫做网
如何存储
arc[i][j]=???Wij,0,∞,若(vi,vj)∈E或<vi,vj>∈E若i==j反之
这里的wij表示权值,∞表示一个计算机允许的、大于所有边上权值的值,也就是一个不可能的值。一般表示不可达。
顶点数组:
A | B | C | D |
---|
边数组:
顶点ABCDA0∞∞∞B60∞∞C9∞0∞D∞780
代码实现:
#include <stdio.h>
typedef char VertexType; /*顶点的数据类型*/
typedef int EdgeType; /*权值类型*/
#define MAXVEX 100 /*最大定点数*/
#define INFINITY 65535 /*不可达*/
typedef struct Graph
{
VertexType vesx[MAXVEX]; // 定点表
EdgeType arc[MAXVEX][MAXVEX]; //邻接矩阵
int numVertexs; //当前的定点数
int numEdges; //当前的边数
}Graph;
/**
* @author 韦轩
* @time 2015/08/30
* @brief 邻接矩阵创建无向图
* @param G
* @return
*/
void createUdGraph(Graph* G)
{
printf("Input the vertexts and the edges :\n");
scanf_s("%d,%d", &G->numVertexs, &G->numEdges);
int i, j, w;
for (i = 0; i < G->numVertexs;i++)
{
scanf_s(&G->vesx[i]);
}
for (i = 0; i < G->numEdges; i++)
{
for (j = 0; j < G->numVertexs;j++)
{
G->arc[i][j] = INFINITY;//初始化
}
}
for (int k = 0; k < G->numEdges;k++)
{
printf("Input the (Vi,Vj) and the weight :\n");
scanf_s("%d,%d,%d", &i, &j, &w);
G->arc[i][j] = w;
G->arc[j][i] = G->arc[i][j];
}
}
可以看出,N个顶点和E条边的无向图的创建,时间复杂度是
O(N+N2+E),其中邻接矩阵的初始化,需要O(N2)
邻接表
当边数比较少的时候,邻接矩阵对空间的浪费比较严重.
为了避免空间浪费的问题,引入了邻接表的方式:数组与链表相结合的存储方法称为邻接表(Adjacency List)
处理办法:
顶点表:图中的顶点使用一个一维数组存储,为每一个还需要存储一个指向第一个邻接点的指针。
图中的每个顶点Vi的所有邻接点构成一个线性表,使用单链表存储。
无向图:
邻接表
顶点表的的各个结点由data域和firstedge两个域组成,data是数据域,存储节点信息,firstedge是指针域,指向边表的第一个结点,即此节点的第一个邻接点。
边表结点有adjvex和next指针域组成,adjvex是邻接点域,存储某顶点的邻接点在定点表中的下标。next则指向边表中下一个结点的指针。
有向图:
带权:
在边表结点增加weight数据域
代码实现
#include <stdio.h>
#include <malloc.h>
typedef char VertexType;
typedef int EdgeType; //权值类型
#define MAXVEX 100
/**
* @author 韦轩
* @time 2015/08/30
* @brief 边表结点
*
*/
typedef struct EdgeNode
{
int adhvex; //邻接点域,存储该顶点对应的下标
EdgeType weight;//权值
struct EdgeNode* next;//指针域,指向下一个邻接点
}EdgeNode;
/**
* @author 韦轩
* @time 2015/08/30
* @brief 顶点表结点
*/
typedef struct VertexNode
{
VertexType data; //顶点域,存储顶点信息
EdgeNode* firstedge; //边表头指针
}VertexNode, AdjList[MAXVEX];
/**
* @author 韦轩
* @time 2015/08/30
* @brief 图
*/
typedef struct GraphAdjList
{
AdjList adjList;
int numVertexs; //当前的顶点数
int numEdges; //当前的边数
}GraphAdjList;
void creatGraph(GraphAdjList* G)
{
int i, j, k;
EdgeNode* edgeNode;
printf("Input the vertexs and edges:\n");
scanf_s("%d,%d", &G->numVertexs, &G->numEdges);
/*
读入顶点信息,建立顶点表
*/
for (i = 0; i < G->numVertexs;i++)
{
scanf_s(&G->adjList[i].data);
G->adjList[i].firstedge = NULL;//边表置为空表
}
for (k = 0; k < G->numEdges;k++)
{
printf("Input the vi vj:\n");
scanf_s("%d,%d", &i, &j);
edgeNode = (EdgeNode*)malloc(sizeof(EdgeNode));//分配内存
/*
生成边表结点
*/
edgeNode->adhvex = j;//邻接序号为j
/*
将edgeNode指针指向当前顶点指向的结点
*/
edgeNode->next = G->adjList[i].firstedge;
/*
将当前顶点的指针指向edgeNode
*/
G->adjList[i].firstedge = edgeNode;
edgeNode = (EdgeNode*)malloc(sizeof(EdgeNode));//分配内存
edgeNode->adhvex = i;
edgeNode->next = G->adjList[j].firstedge;
/*
将当前顶点的指针指向edgeNode
*/
G->adjList[j].firstedge = edgeNode;
}
}
可以看出,N个顶点和E条边的无向图的创建,时间复杂度是
O(N+E)
十字链表
邻接多重表
边集数组
版权声明:欢迎交流