6.4图的存储结构

6.4图的存储结构

**写在前面:**这些是我学习的时候的一些个人理解和笔记,如有错误,欢迎指正。

图是没有顺序存储结构的,但可以借助二维数组来表示元素之间的关系,即邻接矩阵表示法;图的链式存储有邻接表十字链表邻接多重表

6.4.1邻接矩阵

邻接矩阵是表示顶点之间的相邻关系的矩阵。
如果是图:有边相关联的值为1,没有则为0;
如果是网:有边相关联的值为权值,没有则无穷。
有向图的邻接矩阵:出度找行,入度找列;
无向图的邻接矩阵是对称的,顶点的度:看行或者列都可以。

邻接矩阵的存储表示

需要两个表(顶点表和邻接矩阵表)+点数和边数

#define MaxInt 32767    //表示极大值
#define MVNum 100   //最大的顶点数
typedef char VerTexType;    //顶点数据类型
typedef int ArcType;    //假设边的权值类型为整型
typedef struct 
{
    VerTexType vexs[MVNum]; //顶点表
    ArcType arcs[MVNum][MVNum];  //邻接矩阵表
    int vexnum,arcnum;  //图的当前点数和边数
}AMGraph;

邻接矩阵创建无向网的算法描述

时间复杂度:O(n^2)
1.输入总顶点数和边数
2.将顶点信息存到顶点表中
3.初始化邻接矩阵,权值设为最大值
4.构造邻接矩阵

Status CreateUDN(AMGraph &G)
{//采用邻接矩阵表示法创建无向网
    cin>>G.vexnum>>G.arcnum;    //输入顶点个数,边的个数
    for(int i=0;i<G.vexnum;++i)
        cin>>G.vexs[i];
    for(int i=0;i<G.vexnum;++i)
        for(int j=0;j<G.vexnum;+j)
        G.arcs[i][j]=MaxInt;                //初始化邻接矩阵,变得权值默认最大
    for(int 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;                     //网图有权值
        G.arcs[j][i]=G.arcs[i][j];      //因为是无向网图
    }
    return OK;
}

邻接矩阵的优缺点

优点:

1.便于判断两顶点间有无边,看A[i][j]等于1还是0;
2.便于计算各个顶点的度。

缺点:

1.不便于增加和删除顶点
2.不便于统计变得数目,需要扫描邻接矩阵的所有元素才能知道,时间复杂度O(n^2)
3.空间复杂度高,空间复杂度为O(n^2)

6.4.2邻接表

邻接表是图的一种链式存储结构。
邻接表由两部分组成:表头结点边表

  • 表头结点:包括数据域链域两部分,数据域存储顶点信息,链域用于指向链表中的第一个结点。
  • 边表:包括邻接点域、数据域、链域三部分组成
  • 在这里插入图片描述

图的邻接表的存储表示

需要3个结构体:边结点、顶点、邻接表

#define MVNum 100//最大顶点数
typedef struct ArcNode  //边结点
{
    int adjvex;     //边所指的顶点位置
    struct ArcNode *nextarc;//指向下一条边的指针
    OtherInfo info;//和边的相关信息(如可以放权值)
}ArcNode;
typedef struct VNode    //顶点
{
    VerTexType data;
    ArcNode * firstarc;//指向第一条依附该顶点的边的指针
}VNode,AdjList[MVNum];
typedef struct      //邻接表
{
    AdjList vertices;
    int vexnum,arcnum;  //当前的顶点数和边数
}ALGraph;

邻接表创建无向图的算法描述

时间复杂度:O(n+e)
1.输入顶点数和边数
2.输入顶点并且将其存如顶点表中,每个表头指针域初始化为NULL
3.创建邻接表。输入边依附的两个顶点,找到顶点的位置i,j,通过头插法把边结点插入

Status CreateUDG(ALGraph &G)
{
    cin>>G.vexnum>>G.arcnum;    //输入点数和边数
    for(int i=0;i<G.vexnum;++i) //存顶点信息
    {
        cin>>G.vertices[i].data;
        G.vertices[i].firstarc=NULL;
    }
    for(int i=0;i<G.arcnum;++i)
    {
        cin>>v1>>v2;    //边依附的两个顶点
        i=LocateVex(G,v1);j=LocateVex(G,v2);
        ArcNode *p1=new ArcNode;//头插法
        p1->adjvex=j;
        p1->nextarc=G.vertices[i].firstarc; G.vertices[i].firstarc=p1;
        ArcNode *p2=new ArcNode;
        p2->adjvex=i;
        p2->nextarc=G.vertices[j].firstarc; G.vertices[j].firstarc=p2;
    }
    return OK;
}

邻接表的优缺点

优点:

1.便于增加和删除结点
2.便于统计边的数目,按照顶点表扫描所有边表可以得到边的数目,时间复杂度为O(n+e)
3.空间效率高,空间复杂度为O(n+e)

缺点:

1.不便于判断顶点之间是否有边,要判断vi和vj是否有边,需要扫描第i个边表,最坏情况需要耗费O(n)时间
2.不便于计算个顶点的度数。无向图容易计算,有向图的出度也容易计算但是入度计算需要遍历整个链表

十字链表

邻接多重表

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值