图的相关术语
- 无向图
- 有向图
- 顶点、边、弧、弧头、弧尾
- 无向完全图
- 有向完全图
- 稠密图、稀疏图
- 度、入度、出度
- 边的权、网图
- 路径、路径长度
- 回路、简单路径、简单回路
- 子图
- 连通图、连通分量
- 强连通、强连通分量
- 生成树、生成森林
图的存储结构
邻接矩阵
用一维数组存储顶点信息,用二维数组表示邻接关系
一个无向图:
一个有向图:
一个带权图:
邻接矩阵存储特点:
1)无向图的邻接矩阵是对称阵。
对于无向图,i行(i列)非零元素个数=第i个顶点的度TD
对于有向图,i行(i列)非零元素(非∞)个数=第i个顶点的出度OD(入度ID)
2)容易确定任意两顶点间是否有边相连。但确定边数,则必须挨个检测
3)若顶点很多边很少,会表示成一个稀疏矩阵,浪费空间。
建立一个图的邻接矩阵存储形式:
private:
VertexType vertex[M] //顶点表
Edgetype arcs[M][M] //边表
int vertexNum,edgeNum; //顶点数和边数
void MGraph ::CreatGraph( ) //建立有向图G的邻接矩阵存储
{ int i, j, k;
cin>>vertexNum>> edgeNum; //输入顶点数和边数
for(i=0; i<vertexNum; i++)
cin>> vertexs [i]; //输入顶点信息,建立顶点表
for(i=0; i< vertexNum; i++)
for(j=0; j< vertexNum; j++
arcs[i][j]=0; //初始化邻接矩阵
for(k=0; k<edgeNum; k++)
{
cin>>i>>j; //输入e条边,建立邻接矩阵
arcs[i][j]=1; //若加入arcs[j][i]=1,则为无向图的邻接矩阵存储建立(无向图的邻接矩阵是对称矩阵)
}
}
邻接表
1)G中所有邻接于顶点i的顶点j链成单链表,即称为顶点i的邻接表;再把所有点的邻接表表头放到数组中,就构成了图的邻接表。
2)此单链表的结点称为表结点。其中头结点称为顶点结点。
表结点:邻接点域(adjvertex)、指针域(next)(指向下一条邻接边的指针域)
顶点结点:顶点域(vertex)、边表头指针(firstedge)(指向第一条邻接边的指针域)
3)带权图再增加域info
建立有向图的邻接表存储,不带边上权值信息的图
typedef struct node { //表结点
int adjvertex; //邻接点域,一般是存放顶点对应的序号或在表头向量中的下标
InfoType info; //与边(或弧)相关的信息
struct node * next; //指向下一个邻接点的指针域
}EdgeNode;
typedef struct vnode { //顶点结点
VertexType vertex; //顶点域
EdgeNode * firstedge; //边表头指针
}VertexNode;
void ALGraph ::CreateALGraph( )
{
int i, j, k;
EdgeNode * p;
cout<<"请输入顶点数和边数"<<endl;
cin>> vertexNum>> edgeNum; //读入顶点数和边数
for(i=0; i<vertexNum; i++) //建立有n个顶点的顶点表
{ cout<<"请输入第 "<<i<<" 个顶点信息:"<<endl;
cin>>adjlist[i].vertex; //读入顶点信息
adjlist[i].firstedge=NULL; //顶点的边表头指针设为空
}
cout<<"下面输入边表信息:"<<endl;
for(k=0; k<edgeNum; k++) //建立边表
{ cout<<"输入边<i, j>对应的顶点编号i, j"<<endl;
cin>>i>>j; //读入边<vi, vj>的顶点对应序号
p=new EdgeNode; //生成新边表结点p
p->adjvertex=j; //邻接点序号为j
p->next=adjlist[i].firstedge; //将新边表结点p插入顶点vi的链表头部
adjlist[i].firstedge=p;
}
} //CreateALGraph
邻接表存储特点:
1)在无向图中n个顶点、e条边,其邻接表需要n个头结点和2e个表结点。在边稀疏【e<<n(n-1)/2】情况下更节省空间
2)无向图中:顶点i的度是第i个链表中的结点数
有向图中:第i个链表中的结点数只是顶点i的出度,要求入度必须遍历。(所有链表中邻接点域为i的结点的个数)
3)为了便于确定顶点i的入度(以顶点i为头的弧),建立逆邻接表。
十字链表(Orthogonal List)
有向图的一种存储方法
顶点表、边表:
firstin、firstout:以该顶点为弧头和弧尾的第一个结点
tailvertex:、headvertex弧头和弧尾的的位置
hlink:弧头相同的下一条弧
tlink:弧尾相同的下一条弧
邻接表的顶点结点存储的是弧头的顶点结点和下一个和当前弧尾顶点依附的弧的指针。
而十字链表就是把邻接表以及逆邻接表的弧节点结合起来。通过一个弧结点既能访问依附于弧尾的弧也可以访问依附于弧头的弧。
邻接多重表
主要用于无向图的存储
vertex:存储和该顶点相关的信息
firstedge:指向第一条依附于该顶点的边。
mark为标记域,可用以标记该条边是否被搜索过;
ivertex和jvertex为该边依附的两个顶点在图中的位置;
ilink指向下一条依附于顶点ivertex的边;
jlink指向下一条依附于顶点jvertex的边,info是边相关信息域。