图的逻辑结构:多对多
图没有顺序存储结构,但可以借助二维数组来表示元素间的关系
数组表示法(邻接矩阵)
链式存储结构:多重链表->邻接表/邻接多重表/十字链表
重点介绍:
邻接矩阵(数组)表示法
邻接表(链式)表示法
1.邻接矩阵
1.数组(邻接矩阵)表示法

无向图的邻接矩阵表示法


有向图的邻接矩阵表示法



网(即有权图)的邻接矩阵表示法

邻接矩阵的存储表示:用两个数组分别存储顶点表和邻接矩阵
#define MaxInt 32767//表示极大值,即无穷大
#define MVNum 100//最大顶点数
typedef char VerTexType;//设顶点的数据类型为字符型
typedef char ArcType;//假设边的权值类型为整形
typedef struct
{
VerTexType vexs[MVNum];//顶点表
ArcType arcs[MVNum][MVNum];//邻接矩阵
int vexnum,arcnum;//图的当前点数和边数
}AMGraph;
采用邻接矩阵表示法创建无向网
【算法思想】
(1)输入总顶点数和总边数
(2)依次输入点的信息存入顶点表中
(3)初始化邻接矩阵,使每个权值初始化为极大值
(4)构造邻接矩阵
Status CreateUDN(AMGraph &G)
{
//采用邻接矩阵表示法,创建无向网G
cin>>G.vexnum>>G.arcnum;//输入总顶点数,总边数
for(i=0;i<G.vexnum;i++)
{
cin>>G.vexs[i];//依次输入点的信息
}
for(i=0;i<G.vexnum;i++)//初始化邻接矩阵
for(j=0;j<G.vexnum;j++)
G.arcs[i][j]=MaxInt;//边的权值均置为极大值
for(k=0;k<G.arcnum;k++)
{
//构造邻接矩阵
cin>>v1>>v2>>w;//输入一条边所依附的顶点及边的权值
i=LocateVex(G,v1);
j=LocateVex(G,v2);//确定v1和v2在G中的位置
G.arcs[i][j]=w;//边<v1,v2>的权值为w
G.arcs[j][i]=G.arcs[i][j];//置<v1,v2>的对称边<v2,v1>的权值为w
}
return OK;
}
//补充算法:在图中查找顶点
int LocateVex(AMGraph G,VertexType u)
{
//图G中查找顶点u,存在则返回顶点表中的下标;否则返回-1
int i;
for(i=0;i<G.vexnum;i++)
if(u==G.vexs[i])
return i;
return -1;
}

2.邻接表
1.邻接表表示法(链式)

顶点:按编号顺序将顶点数据存储在一维数组中
关联同一顶点的边(以顶点为尾的弧):用线性链表存储
无向图

特点:
邻接表不唯一
若无向图中有n个顶点,e条边,则其邻接表需n个头结点和2e个表结点。适合存储稀疏图
无向图中顶点vi的度为第i个单链表中的结点数

//图的邻接表存储表示
typedef struct VNode
{
VerTexType data;//顶点信息
ArcNode* firstarc;//指向第一条依附该顶点的边的指针
}VNode,AdjList[MVNum];//AdjList表示邻接表类型
说明:例如,AdjList v; 相当于:VNode v[MVNum];
//弧(边)的结点结构
#define MVNum 100//最大顶点数
typedef struct ArcNode//边结点
{
int adjvex;//该边所指向的顶点的位置
struct ArcNode* nextarc;//指向下一条边的指针
OtherInfo info;//和边相关的信息
}ArcNode;
//图的结构定义
typedef struct
{
AdjList vertices;//vertices--vertex的复数
int vexnum, arcnum;//图的当前顶点数和弧数
}ALGraph;


//采用邻接表表示法创建无向网
Status CreateUDG(ALGraph& G)
{
//采用邻接表表示法,创建无向图G
cin >> G.vexnum >> G.arcnum;//输入总顶点数,总边数
for (i = 0; i < G.vexnum; i++)//循环遍历顶点
{
vertices//输入各点,构造表头结点表
cin >> G.vertices[i].data;//输入顶点值
G.[i].firstarc = NULL;//初始化表头结点的指针域
}
for (k = 0; k < G.arcnum; k++)//循环遍历边
{
//输入各边,构造邻接表
cin >> v1 >> v2;//输入一条边依附的两个顶点
j = LocateVex(G, v1);
j = LocateVex(G, v2);
p1 = new ArcNode;//生成一个新的边结点*p1
p1->adjvex = j;//邻接点序号为j
p1->nextarc = G.vertices[i].firstarc;
G.vertices[i].firstarc = p1;//将新结点*p1插入顶点vi的边表头部
p2 = new ArcNode;//生成另一个对称的新的边结点*p2
p2->adjvex = i;//邻接点序号为i
p2->nextarc = G.vertices[j].firstarc;
G.vertices[j].firstarc = p2;//将新结点*p2插入顶点vj的边表头部
}
return OK;
}
邻接表特点:
1.方便找任一顶点的所有“邻接点”
2.节约稀疏图的空间
需要n个头指针+2e个结点(每个结点至少2个域)
3.方便计算任一顶点的“度”?
对无向图方便,对有向图不方便,只能计算出度,需要构造逆邻接表(存指向自己的边)来方便计算入度
4.不方便检查任意一对顶点间是否存在边
邻接矩阵与邻接表表示法的关系

1.联系:邻接表中每个链表对应于邻接矩阵中的一行,链表中结点个数等于一行中非零元素的个数
2.区别:
2.1.对于任意确定的无向图,邻接矩阵是唯一的(行列号与顶点编号一致),但邻接表不唯一(链接次序与顶点编号无关)
2.2邻接矩阵的空间复杂度为O(n2),而邻接表的空间复杂度为O(n+e)
3.用途:邻接矩阵多用于稠密图,而邻接表多用于稀疏图
十字链表是有向图的另一种链式存储结构。我们也可以把它看成是将有向图的邻接表和逆邻接表结合起来形成的一种链表。
在有向图中每一条弧对应十字链表中的一个弧结点,同时有向图中的每个顶点在十字链表中对应有一个结点,叫做顶点结点

邻接多重表

博客介绍了图的逻辑结构及存储方式,重点讲解邻接矩阵和邻接表表示法。邻接矩阵借助二维数组,适用于稠密图;邻接表是链式存储,适合稀疏图。还对比了二者关系,提及十字链表和邻接多重表等链式存储结构。

1954

被折叠的 条评论
为什么被折叠?



