图的类型定义和存储结构

目录

 

图的存储结构

邻接矩阵(数组)表示法

有向图

 无向图

 邻接矩阵的存储表示

采用邻接矩阵表示法创建无向图

在图中查找顶点

 邻接矩阵表示法的优缺点

邻接表(链式)表示法

无向图

 特点

有向图

 图的邻接表存储表示算法

十字链表

 邻接多重表

抽象数据类型定义

图的存储结构

  • 图的逻辑结构:多对多
  • 图没有顺序存储结构,但可以借助二维数组来表示元素间的关系

邻接矩阵(数组)表示法

有向图

  • 无权图的邻接矩阵

若有向无权图G=(V,E)有n(n≧1)个顶点,则其邻接矩阵是n阶对称方阵

第i行:以结点Vi为尾的弧(出度边)

第j列:以结点Vj为头的弧(入度边)

  •  带权图的邻接矩阵

 无向图

  • 无向无权图:对称矩阵

        ①顶点i的度 = 第i行(列)中1的个数

  •  无向有权图

 邻接矩阵的存储表示

用两个数组分别存储顶点表邻接矩阵

#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; 

采用邻接矩阵表示法创建无向图

①输入总顶点数和总边数

②依次输入点的信息存入顶点表中

③初始化邻接矩阵,使每个权值初始都是极大值

④构造邻接矩阵

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];
    }
    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;
}

 邻接矩阵表示法的优缺点

优点:①直观、方便、好理解

             ②方便检查任意一对顶点间是否存在边

             ③方便找任一顶点的所有“邻接点”(有边直接相连的顶点)

             ④方便计算任一顶点的“度”

缺点:①不便于增加和删除顶点

            ②浪费空间--存稀疏图(点很多而边很少)有大量无效元素

            ③浪费时间--统计稀疏图中一共有多少条边

邻接表(链式)表示法

无向图

  • 线性链表存储
  • 链表中的结点称为表结点,每个结点由三个域组成。其中邻接点域(adjvex)指示与顶点Vi邻

接的顶点在图中的位置(顶点编号),链域(nextarc)指向下一个与顶点Vi邻接的表结点,数据

域(info)存储和边或弧相关的信息,如权值。对于无权图,则可以省略此区域。

  • 每个链表设一个表头结点(顶点结点),由两个域组成。链域(firstarc)指向链表中的第一个结

点,数据域(data)存储顶点名或其他信息

 特点

①邻接表不唯一

②若无向图中有n个顶点,e条边,则其邻接表需n个头结点和2e个表结点。适宜存储稀疏图

 ③无向图中顶点Vi的度为第i个单链表中的结点数

有向图

①需要n+e个存储空间

②正邻接表中顶点Vi的出度为第i个单链表中的结点个数

③逆邻接表中顶点Vi的入度为整个单链表中邻接点域值是i-1的结点个数

 图的邻接表存储表示算法

表头顶点(顶点结点)

typedef struct VNode{
    VerTexType data;    //顶点信息
    ArcNode *firstarc;    //指向第一条依附该顶点的边的指针
}VNode,AdjList[MVNum];    //AdjList表示邻接表类型

 图的结构定义

typedef struct{
    AdjList vertices;
    int vexnum,arcnum;    //图的当前顶点数和弧数
}ALGraph;//邻接表表示的图

算法思想

1.输入总顶点数和总边数

2.建立顶点表

        ①依次输入点的信息存入顶点表中

        ②使每个表头结点的指针域初始化为NULL

3.创建邻接表

        ①依次输入每条边依附的两个顶点

        ②确定两个顶点的序号i和j,建立边结点

         ③将此边结点分别插入到Vi和Vj对应的边链表的头部

采用邻接表表示法创建无向图                时间复杂度为O(n+e)

Status CreateUDG(ALGraph &G){    //采用邻接表表示法,创建无向图G
    cin>>G.vexnum>>G.arcnum;    //输入总顶点数和总边数
    for(i=0;i < G.vexnum;++i){    //输入各点,构造表头结点表
        cin>>G.vertices[i].data;    //输入顶点值
        G.vertices[i].firstarc = NULL;    //初始化表头结点的指针域
    }
    for(k=0;k < G.arcnum;++k){    //输入各边,构造邻接表
        cin>>v1>>v2;            //输入一条边所依附的两个顶点
        i = LocateVex(G,v1);
        j = LocateVex(G.v2);
        p1 = new ArcNode;        //生成一个新的边结点*p1
        p1 -> adjvex = j;        //从i指向j,将p1的邻接点序号置为j
        p1 -> nextarc = G.vertices[i].firstarc;    
        G.vertices[i].firstarc = p1;    //将新结点*p1插入顶点Vi的边表的第一个
        p2 = new ArcNode;        //生成一个新的边结点*p2
        p2 -> adjvex = i;        //从j指向i,将p2的邻接点序号置为i
        p2 -> nextarc = G.vertices[j].firstarc;   
        G.vertices[j].firstarc = p2;    //将新结点*p2插入顶点Vj的边表的第一个
    }
    return OK;
}

 邻接表特点:①方便找任一顶点的所有“邻接点”

                         ②节约稀疏图的空间:无向图需要N个头指针+2e个结点(每个结点至少2个域)

                         ③邻接表的表示不唯一

邻接矩阵的空间复杂度为O(n^2);        邻接表的空间复杂度为O(n+e)

邻接矩阵多用于稠密图;邻接表多用于稀疏图

十字链表

 邻接多重表

①Data域:存储和顶点相关的信息
②指针域firstedge:指向依附于该顶点的第一条边所对应的表结点
③标志域mark:用以标示这条边是否被访问过
④ivex和jvex域:分别保存该边所依附的两个顶点在图中的位置
⑤info域:保存该边的相关信息
⑥指针域ilink:指向下一条依附于顶点ivex的边
⑦指针域jlink:指向下一条依附于顶点jvex的边

//无向图的邻接多重表存储表示
#define MAX_VERTEX_NUM 20
typedef enum{
    unvisited,visited
}VisitIf;
typedef struct EBox{
    VisitedIf mark;        //访问标记
    int ivex,jvex;         //该边依附的两个顶点的位置
    struct EBox *ilink,*jlink;    //分别指向依附这两个顶点的下一条边
    InfoType *info;        //该边信息指针
}Ebox;
typedef struct VexBox{
    VerTexType data;
    EBox *firstedge;        //指向第一条依附该顶点的边
}VexBox;
tyypedef struct{
    VexBox adjmulist[MAX_VERTEX_NUM];
    int vexnum,edgenum;    //无向图的当前顶点数和边数
}AMLGraph;
    
    

抽象数据类型定义

ADT Graph{
    数据对象V:具有相同特性的数据元素的集合,称为顶点集。
    数据关系R:R={VR}
		VR={<v,w>|<v,w>| v,wV∧p(v,w) ,<v,w>表示从v到w的弧,P(v,w)定义了弧<v,w>的信息 }
    基本操作P: 
	    Create_Graph() : 图的创建操作。
		    初始条件:无。
     	    操作结果:生成一个没有顶点的空图G。
	    GetVex(G, v) : 求图中的顶点v的值。
		    初始条件:图G存在,v是图中的一个顶点。
		    操作结果:生成一个没有顶点的空图G。 
		    … … 
	    DFStraver(G,V):从v出发对图G深度优先遍历。
            初始条件:图G存在。
            操作结果:对图G深度优先遍历,每个顶点访问且只访问一次。
	    BFStraver(G,V):从v出发对图G广度优先遍历。
           初始条件:图G存在。
           操作结果:对图G广度优先遍历,每个顶点访问且只访问一次。
} ADT Graph 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值