一、简介
图是一种复杂的数据结构,任意两个顶点之间都可能存在边,所以无法通过顶点的存储位置反应顶点之间的邻接关系,因此,图没有顺序存储结构。
从图的定义知,一个图包含两部分:顶点信息以及顶点之间边的信息。无论采用什么方法存储图,都要完整、准确地表示这两方面的信息。
下面介绍两种常用的存储结构——邻接矩阵和邻接表。
一般情况下,图越稠密,邻接矩阵的空间效率越高;而对稀疏图使用邻接表存储,则能获得较高的空间效率。
邻接矩阵比邻接表的时间代价高。
二、邻接矩阵
图的邻接矩阵存储也称数组表示法,用一个一维数组存储顶点,用一个二维数组存储边。存储边的二维数组称为邻接矩阵。 用C++中的类来定义一个使用邻接矩阵存储的无向图,代码如下:
const int size = 1000; //图中最多顶点个数
template <typename T> //使用模板,兼容各种数据类型
class MGraph
{
public:
MGraph(int n,int e) //构造函数,输入顶点数和边数
{
vertex_num = n;
edge_num = e;
for (int i = 0; i < n; i++) //输入顶点
{
T v;
cin >> v;
vertex[i] = v;
}
for (int i = 0; i < n; i++) //初始化存储边的二维矩阵,即邻接矩阵,0表示无边
{
for (int j = 0; j < n; j++)
{
edge[i][j] = 0;
}
}
for (int k = 0; k < e; k++) //输入边
{
int i, j;
cin >> i >> j;
edge[i][j] = 1; //1表示i到j有边,也可以是其他值,表示权重(边长)
edge[j][i] = 1; //无向图,两边都通;有向图则不需要这一行代码
}
}
~MGraph() = default; //析构函数,静态存储分配,无需销毁,为空
void DFS(int v){} //深度优先遍历,暂不介绍
void BFS(int v){} //广度优先遍历,暂不介绍
private:
T vertex[size]; //存储顶点的一维数组
T edge[size][size]; //存储边的二维数组
int vertex_num; //顶点数
int edge_num; //边数
};
三、邻接表
- 邻接表是一种顺序存储结构与链接存储结构相结合的存储方法,类似于树的孩子表示法。
- 对于图的每个顶点v,将v的所有邻接点链成一个单链表,称为v的边表(有向图则称为出边表)。
- 存储边表的头指针的数组和存储顶点的数组构成了邻接表的表头数组,称为顶点表。
- 所以,邻接表中存在两种结点结构,边表结点和顶点表结点。
用C++中的类实现基于邻接表存储结构下的有向或无向图,其定义如下:
struct EdgeNode //边表结点
{
int adjvex; //邻接点域
EdgeNode* next;
};
template <typename T>
struct VertexNode //顶点表结点
{
T vertex;
EdgeNode* firstEdge;
};
const int size = 1000; //图中最多顶点个数
template <typename T> //使用模板,兼容各种数据类型
class ALGraph
{
public:
ALGraph(int n,int e) //构造函数,输入顶点数和边数
{
EdgeNode* s = nullptr;
vertex_num = n;
edge_num = e;
for (int i = 0; i < n; i++) //输入顶点,初始化顶点表
{
T x;
cin >> x;
adjlist[i].vertex = x;
adjlist[i].firstEdge = nullptr;
}
for (int k = 0; k < e; k++) //输入边
{
int i, j;
cin >> i >> j; //输入边所依附的两个顶点的编号
s = new EdgeNode; //生成一个边表结点s
s->adjvex = j;
s->next = adjlist[i].firstEdge;
adjlist[i].firstEdge = s; //将边表结点s插入表头
}
}
~ALGraph() //析构函数
{
EdgeNode* p = nullptr, * q = nullptr;
for (int i = 0; i < vertex_num; i++)
{
p = q = adjlist[i].firstEdge;
while (p != nullptr)
{
p = p->next;
delete q;
q = p;
}
}
}
void DFS(int v){} //深度优先遍历,暂不介绍
void BFS(int v){} //广度优先遍历,暂不介绍
private:
VertexNode<T> adjlist[size]; //存放顶点表的数组
int vertex_num; //顶点数
int edge_num; //边数
};