6.1图的定义

G由两个集合V和E组成,记为G=(V,E) , 其中V是顶点的有穷非空集合, E是V中顶点偶对的有穷集合,这些顶点偶对称为边。V(G)和E(G)通常分别表示图G的顶点集合和边集合,E(G)可以为空集。若E(G)为空,则图G只有顶点而没有边。

​ 对于图G ,若边集E(G)为有向边的集合,则称该图为有向图 ; 若边集E(G)为无向边的集合, 则称该图为无向图。

​ 在有向图中,顶点对<x, y>是有序的,它称为从顶点 x到顶点 y的一条有向边。因此,<x, y>与<y, x>是不同的两条边。顶点对用一对尖括号括起来,x是有有向边的始点,y是有向边的终点。<x, y>也称作一条弧,则 x为弧尾,y为弧头。

​ 在无向图中,顶点对(x, y)是无序的,它称为与顶点x和顶点y相关联的一条边。这条边没有特定的方向,(x,y)与(y,x)是同一条边。为了有别于有向图,无向图的顶点对用一对圆括号括起来。

6.1.2图的基本术语

  • 子图:假设有两个图 G = (V, E)和 G'= (V', E'), 如果V包含V‘且 E包含E’, 则称 G'为 G的子图
  • 无向完全图和有向完全图:对于无向图,若具有 n(n-1)/2 条边,则称为无向完全图。 对于有向图,若具有nn( - l)条弧,则称为有向完全图
  • 稀疏图和稠密图:有很少条边或弧(如 e<nolg2 n) 的图称为稀疏图,反之称为稠密图
  • 权和网:在实际应用中,每条边可以标上具有某种含义的数值,该数值称为该边上的。这些权可以表示从一个顶点到另一个顶点的距离或耗费 。这种带权的图通常称为
  • 邻接点:对于无向图 G, 如果图的边 (v, v')属于E, 则称顶点 v 和 v'互为邻接点, 即v和v'相邻接。边(v,v')依附于顶点v和v', 或者说边(v,v')与顶点v和v'相关联
  • 度、入度和出度:顶点v的是指和v相关联的边的数目,记为TD(v)。对于有向图,顶点v的度分为入度出度入度是以顶点v为头的弧的数目,记为ID(v); 出度是以顶点v为尾的弧的数目,记为OD(v)。顶点v的度为TD(v)=ID(v)+OD(v)。
  • 路径和路径长度:在无向图G中,从顶点 v 到顶点 v' 的路径是一个顶点序列 (v = vi,0, Vi, 1,...,Vi,m=v'), 其中(vi,j-1,vi,j)属于E, 1<=j<=m。如果G是有向图,则路径也是有向的, 顶点序列应满足<vi,j-1,vi,1>属于E,1<=j<=m。路径长度是一条路径上经过的边或弧的数目。
  • 回路或环:第一个顶点和最后一个顶点相同的路径称为回路或环
  • 简单路径、 简单回路或简单环:序列中顶点不重复出现的路径称为简单路径。除了第一个顶点和最后一个顶点之外,其余顶点不重复出现的回路,称为简单回路简单环
  • 连通、连通图和连通分量:在无向图 G 中,如果从顶点 v 到顶点 v'有路径,则称 v 和 v' 是连通的。如果对于图中任意两个顶点 Vi 、Vj属于V, Vi 和 Vj都是连通的,则称 G 是连通图。 所谓连通分量, 指的是无向图中的极大连通子图。
  • 强连通图和强连通分量:在有向图 G 中,如果对于每一对 vi, vj属于 V,vi不等于vj, 从 vi 到 vj 和 从 vj 到 vi 都存在路径,则称G是强连通图。有向图中的极大强连通子图称作有向图的强连通分量。
  • 连通图的生成树: 一个极小连通子图,它含有图中全部顶点,但只有足以构成一 棵树的 n-1 条边,这样的连通子图称为连通图的生成树
  • 有向树和生成森林:有一个顶点的入度为 0, 其余顶点的入度均为 l 的有向图称为有向树。 一 个有向图的生成森林是由若干棵有向树组成,含有图中全部顶点,但只有足以构成若干棵不相交的有向树的弧。

6.2 案例引入

案例 6.1: 六度空间理论。

六度空间理论是一个数学领域的猜想,又称为六度分割理论(SixDegrees ofSeparation)。六 度空间理论是 20 世纪 60 年代由美国的心理学家米格兰姆 (Stanley Milgram) 提出的,理论指出: 你和任何一 个陌生人之间所间隔的人不会超过6个,也就是说,最多通过6个中间人你就能够认识任何一个陌生人。

​ 随着新技术的发展,六度空间理论的应用价值受到了人们的广泛关注,除了前面提到的微 软的人立方搜索,很多领域都运用了六度空间理论,例如 SNS 网站、 BLOG 网站、电子游戏社 区、直销网络等。

6.3 图的类型定义

图是一种数据结构,加上一组基本操作,就构成了抽象数据类型。抽象数据类型图的定义如下:

ADTGraph{
  数据对象: V是具有相同特性的数据元素的集合,称为顶点集。
  数据关系:
    R = {VR}
    VR = {<v, w>|v,wEV且P(v,w)<v,w>表示从v到w的弧,谓词P               (v, w)定义了弧<v, w>的意义或信息}
  基本操作:
    CreateGraph(&G,V,VR)
     初始条件:V是图的顶点集,VR是图中弧的集合。
     操作结果:按V和VR的定义构造图G。
    DestroyGraph(&G)
     初始条件:图G存在。 操作结果:销毁图G。
    Locat eVex(G,u)
     初始条件:图G存在,u和G中顶点有相同特征。
     操作结果:若G中存在顶点u,则返回该顶点在图中的位置;否则返回其他信息。        GetVex(G,v)
     初始条件:图G存在,v是G中某个顶点。 操作结果:返回v的值。
    PutVex(&G,v,value);
     初始条件:图G存在,v是G中某个顶点。
     操作结果:对 v赋值value。
    FirstAdjVex(G,v)
     初始条件:图G存在,v是G中某个顶点。
     操作结果:返回 v的第一 个邻接顶点。若v在G中没有邻接顶点,则返回 “空”     NextAdjVex(G,v,w)
     初始条件:图G存在,v是G中某个顶点,w是v的邻接顶点。
     操作结果:返回v的(相对千w的)下一 个邻接顶点。若w是v的最后一 个邻接        点,则返回 “空” 。
    InsertVex(&G,v)
     初始条件:图G存在,v和图中顶点有相同特征。
     操作结果:在图G中增添新顶点v。
    DeleteVex(&G,v)
     初始条件:图G存在,v是G中某个顶点。
     操作结果:删除 G中顶点v及其相关的弧。
    InsertArc(&G,v,w)
     初始条件:图G存在,v和w是G中两个顶点。
     操作结果:在G中增添弧<v, w>,若G是无向图,则还增添对称弧<w, v>。
    DeleteArc(&G,v,w)
     初始条件:图G存在,v和w是G中两个顶点。
     作结果:在G中删除弧<v, w>,若G是无向图,则还删除对称弧<w, v>。
    DFSTraverse(G)
     初始条件:图G存在。
     操作结果:对图进行深度优先遍历,在遍历过程中对每个顶点访问一次。           BFSTraverse(G)
     初始条件:图G存在。
     操作结果:对图进行广度优先遍历,在遍历过程中对每个顶点访问一次。 
}ADT Graph

6.4图的存储结构

6.4.1邻接矩阵

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;

2.采用邻接矩阵表示法创建无向网

  • 算法描述

    Status CreateUDN(AMGraph &G)
    {//采用邻接矩阵表示法,创建无向网G
        cin>>G.vexnum>>G.arcnum;            //输人总顶点数,总边数
        for(i=O;i<G.vexnum;++i)             //依次输入点的信息
            cin>>G.vexs[i);
        for(i=O;i<G.vexnum;++i)             //初始化邻接矩阵,边的权值均置为极大值MaxInt
            for(j=0;j<G.vexnum;++j)
                G.arcs[i][j]=MaxInt;
        for(k=O;k<G.arcnum;++k)             //构造邻接矩阵
        {               
             cin>>vl>>v2>>w;                //输人一条边依附的顶点及权值
             i=LocateVex(G,vl);j=LocateVex(G,v2); //确定vl和v2在G中的位置,即顶点数组的下标
             G.arcs[i) [j)=w;               //边<v1, v2>的权值置为w
             G.arcs[j][i]=G.arcs[i][j];     //置<v1,v2>的对称边<v2, v1>的权值为w
         }                                  //for
         return OK;
    }
    

6.4.2邻接表

1.邻接表表示法

邻接表(Adjacency List) 是图的一 种链式存储结构。 在邻接表中,对图中每个顶点V; 建立一 个单链表,把与 V;相邻接的顶点放在这个链表中。邻接表中每个单链表的第一个结点存放有关顶点的信息, 把这一结点看成链表的表头, 其余结点存放有关边的信息, 这样邻接表便由两部分组 成:表头结点表和边表。

//- - - - -图的邻接表存储表示- - - - -
#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;

2.采用邻接表表示法创建无向图

  • 算法描述

     Status CreateUDG(ALGraph &G)
    {//采用邻接表表示法, 创建无向图 G
         cin>>G.vexnum>>G.arcnum; 
         for(i=O;i<G.vexnum;++i
         {
             cin>>G.vertices[i].data;
             G.vertices[i].firstarc=NULL;
         }
         for(k=O;k<G.arcnum;++k)
         {
             cin>>c1>>c2;
             i=LocateVex{G,v1};j=LocateVex{G,v2};
             pl=new ArcNode; 
             pl->adjvex= j; 
             pl->nextarc=G.vertices[i].firstarc;
             G.vertices[i].firstarc=pl;
             p2=new ArcNode;
             p2->adjvex=i; 
             p2->nextarc=G.vertices[j].firstarc;
             G.vertices[j].firstarc=p2;
         }
         return OK;
    }
    

6.4.3十字链表

有向图的十字链表存储表示的形式说明如下所示:

//- - - - -有向图的十字链表存储表示- - - - -
#define MAX_VERTEX_NUM 20
typedef strut ArcBox
{
    int tailvext,headvex;
    struct ArcBox *hlink, *tlink;
    InfoType *info;
}ArcBox;
typedef struct VexNode
{
    VertexType data;
    ArcBox *firstin,*firstout; 
}VexNode;
typedef struct
{
    VexNode xlist[MAX_VERTEX_NUM];
    int vexnnm, arcnum;
}OLGraph;

6.4.4 临界多重表

在邻接多重表上,各种基本操作的实现亦和邻接表相似。邻接多重表的类型说明如下:

//- - - - -无向图的邻接多重表存储表示-----
#define MAX_VERTEX_NUM 20
typedef enum{unvisited,visited} Visitlf;
typedef struct EBox
{
    Visitlf mark;
    int ivex, jvex;
    struct EBox *ilink, *jlink; 
    InfoType *info;
}Ebox;
typedef struct VexBox
{
    VertexType data;
    EBox *firstedge;
}VexBox;
typedef struct{
    VexBox adjmulist[MAX_VERTEX_NUM];
    int vexnum, edgenum;
}AMLGraph;
posted @ 2022-02-07 17:36  在结束时开始  阅读(70)  评论(0)    收藏  举报