数据结构——图

目录

一、图的基本概念

↓ 图的定义

↓ 图的基本术语

→  邻接与依附

→  完全图

→  顶点的度

→  路径长度

→  回路

→  连通图、连通分量

→  生成树与森林

二、图的存储结构

↓ 邻接矩阵存储结构:

→ 邻接矩阵的优缺点:

→ 邻接矩阵创建无向网:

↓ 邻接表存储结构:

 → 邻接表的数据类型描述:

→ 邻接表求顶点的度:

→ 邻接表创建无向网:

↓ 邻接矩阵与邻接表的联系:

↓ 十字链表存储结构:

→ 十字链表的结构:

→ 十字链表存储结构图:

→ 十字链表的数据类型描述:

↓ 多重链表的存储结构:

→ 多重链表的结构:

→ 多重链表的结构图:

→ 多重链表的数据类型描述:


一、图的基本概念

图的定义

 在图形结构中,结点之间是多对多的任意关系,图中每个数据元素可以有多个直接前驱和多个直接后继,任意两个元素之间都可能相关。

图的基本术语

邻接与依附

完全图

 

n个顶点

无向完全图的边数为 n*(n-1)/ 2条边。

有向完全图的弧数为 n *(n-1)条弧。

顶点的度

无向图中:总度数为边数和的两倍

有向图中:总度数为各顶点的入度数 与 出度数之和。

其中有向图中:总入度、总出度和总弧数相等。

路径长度

回路

连通图、连通分量

 

 

生成树与森林

注意:生成树不唯一

二、图的存储结构

图的存储结构有:邻接矩阵、邻接表、十字链表、多重链表

邻接矩阵存储结构:

表示顶点之间的邻接关系,是顺序存储结构,也称为“数组表示法”.

用一维数组存储顶点的信息,用二维数组存储顶点的边(或弧)的信息。

邻接矩阵的优缺点:

优点:便于查看邻接点之间的关系,方便知道结点的度和边数,适用于稠密图。

缺点:删除或增加结点在二维数组中不方便;在稀疏图中,边数很少,结点数很多时,则存在大量的无效元素,遍历时耗费时间,也浪费空间

#define MAXVEX 20    //最大顶点个数
#define INFINITY 32767  //权值的极大值
typedef struct
{
   int arcs[MAXVEX][MAXVEX];  //用于存储边或弧的信息
   Vextype vex[MAXVEX];       //顶点的信息
   int vexnum;                //顶点的数目
   int arcnum;                //边或弧的数目
}AdiMatrix;                   //邻接矩阵
无向图的邻接矩阵为对称矩阵                                                                                                   求无向图第i个顶点 的度 等于矩阵中第i行非零元素的个数。                   

有向图的邻接矩阵不一定为对称矩阵。

第i个顶点的出度为:矩阵中第i行的非零元素的个数。

第i个顶点的入度为:矩阵中第i列的非零元素的个数。

 

邻接矩阵创建无向网:

算法思想:

1、输入网中的结点数、总边数

2、输入结点,存入一维数组中

3、初始化邻接矩阵,二维数组初始化值为权值的极大值

4、建立邻接矩阵。

void Create( AdjMatrix*G)
{
   int i,j,k,weight;
   char vex1,vex2;           //定义顶点的类型为字符型
   printf("请输入无向网中的顶点数与边数:\n");
   scanf("%d,%d",&G->vexnum,&G->arcnum);
   printf("请输入无向图%d个顶点\n",G->vexnum);
   for(i=1;i<=G->vexnum;i++)
      {
          printf("请输入第%d个顶点:\n",i);
          scanf("%c",&G->vex[i]);
      }
   for(i=1;i<=G->vexnum;i++)       //初始化矩阵,也就是二维数组
      {
         for(j=1;j<=G->vexnum;j++)
            {
               G->arcs[i][j]=INFINITF;   //初始化矩阵的值为权的极大值
            }
      }
   printf("请输入无向图中%d条边:\n",G->arcnum);
   for(k=1;k<=G->arcnum;k++)
      {
         printf("第%d条边:\n  顶点V",k);
         scanf("%c",&vex1);        //一条边的一端的顶点
         printf("<-->顶点V");      //这条边的另一端的顶点
         scanf("%c",&vex2);
         printf("输入此边的权值:");
         scanf("%d",&weight);
         i=LocateVex(G,vex1);  //找到顶点在矩阵中行的位置
         j=LocateVex(G,vex2);  //另一个顶点在矩阵中列的位置
         G->arcs[i][j]=weight; //如果不是网,赋值1
         G->arcs[j][i]=weight;  //如果是有向图,因有方向,删除此代码
      }
}
int LocateVex(AdjMatrix*G,char v)    //定义此函数用于查找顶点在矩阵中的行列位置。
{
   int i;
   for(i=1;i<=G->vexnum;i++)
      {
        if(G->vex[i]==v)
           return i;
       }
    return 0;
}

邻接表存储结构:

对于稀疏图,邻接矩阵存储时浪费空间的问题,邻接表存储可以解决。

邻接表是图的链式存储结构,由边表和顶点表组成。

 其中,边表是对每个顶点建立一个单链表,存放与该顶点邻接的所有顶点,相当于矩阵中的非零元素。

 顶点表存放用于存储每个顶点的信息,以及指向该顶点边表的头指针。顶点表采用顺序存储结构。

 邻接表的数据类型描述:

#define MAXVEX 20
typedef struct ArcNode        //边表结构,
{
   int adjvex;
   int weight;                //网的边结构,存放权值
   struct ArcNode*next;       //指向下一个顶点的邻接点
}ArcNode;
typedef struct VertexNode     //顶点表结构
{
    char vexdata;             //存放顶点的信息
    ArcNode*head;             //ArcNode类型的头指针指向边表。
}VertexNode;
typedef struct
{
    VertexNode vertex[MAXVEX];  //用VertexNode类型的数组存放邻接表
    int vexnum; //顶点数
    int arcnum; //弧或边数
}AdjList;       //邻接表

邻接表求顶点的度:

对于无向图:第i个顶点的度为第i个单链表上的结点的个数。

而对于有向图:

第i个顶点的出度为第i个单链表上结点的个数,其入度需要遍历整个邻接表,统计该结点出现的次数。耗费时间。

为方便统计顶点的入度,可以采用逆邻接表变的是边表中存放的是顶点通过入度弧所邻接的其他结点。所以根据需要采用不同的方法。

邻接表创建无向网:

算法思想:

1、统计顶点数与边数

2、输入顶点信息,建立顶点表,顶点表中head指针域置空

3、建立邻接表:

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

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

      将此边结点分别插入到 Vi 和Vj对应的两个边链表的头部,采用头插法。

#define MAXVEX 20
typedef struct ArcNode        //边表结构,
{
   int adjvex;
   struct ArcNode*next;       //指向下一个顶点的邻接点
}ArcNode;
typedef struct VertexNode     //顶点表结构
{
    char vexdata;             //存放顶点的信息
    ArcNode*head;             //ArcNode类型的头指针指向边表。
}VertexNode;
typedef struct
{
    VertexNode vertex[MAXVEX];  //用VertexNode类型的数组存放邻接表
    int vexnum; //顶点数
    int arcnum; //弧或边数
}AdjList;       
void CreateUDG(AdjList &G)
{
    int i,j,k;
    char vex1,vex2;
    printf("请输入顶点数与边数\n");
    scanf("%d,%d",&G.vexnum,&G.arcnum);
    printf("请输入图中%d个顶点:\n",G.vexnum);
    for(i=1;i<=G.vexnum;i++)
       {
           printf("请输入第%d个顶点:\n",i);
           scanf("%c",&G.vertex[i].vexdata);
           G.vertex[i].head=NULL;
       }
    printf("请输入图中%d条边\n",G.arcnum);
    for(k=1;k<=G.arcnum;k++)
       {
           printf("第%d条边:\n 顶点V",k);
           scanf("%d",&vex1);
           printf("<-->顶点V\n");
           scanf("%d",&vex2);
           i=LocateVex(G,vex1);
           j=LocateVex(G,vex2);
           p1=new ArcNode;             //生成一个新的边结点*p
           p1->adjvex=j;               //存放邻接点的序号
           p1->next=G.vertex[i].head;  //用头插法将边结点插在顶点的后面
           G.vertex[i].head=p1;
           p2=new ArcNode;              //无向网是两条边,A-》B,B-》A
           p2->adjvex=i;
           p2->next=G.vertex[j].head;
           G.vertex[j].head=p2;
       }
int LocateVex(AdjMatrix*G,char v)    //定义此函数用于查找顶点在矩阵中的行列位置。
{
   int i;
   for(i=1;i<=G->vexnum;i++)
      {
        if(G->vex[i]==v)
           return i;
       }
    return 0;
}
      

 如果是有向网:

 上述代码变化的是:

出度边与入度边二选一,如果选择入度边建立邻接表,需要采用逆邻接表。

    A-》B A结点的出度:
    p1=new ArcNode;             //生成一个新的边结点*p
    p1->adjvex=j;               //存放邻接点的序号
    p1->next=G.vertex[i].head;  //用头插法将边结点插在顶点的后面
    G.vertex[i].head=p1;
    B-》A A结点的入度:
    p2=new ArcNode;
    p2->adjvex=i;
    p2->next=G.vertex[j].head;
    G.vertex[j].head=p2;

邻接矩阵与邻接表的联系:

 

十字链表存储结构:

    十字链表存储是有序图的另一种链式存储结构。是邻接表与逆邻接表的结合,可以同时求出顶点的入度与出度,可以解决邻接表只能求出度的问题。

十字链表的结构:

顶点表结点结构:

 vexdata:顶点的信息

 head:以该顶点为弧头的边表头指针   (相当于逆邻接表,顺着边表可以找顶点的入度)

 tail:    以该顶点为弧尾的边表头指针   (相当于邻接表,  顺着边表可以找顶点的出度 )

边表结点结构:

tailvex    :弧尾顶点的序号

headvex:弧头顶点的序号

hnextarc:指向同一弧头顶点的下一条弧

tnextarc: 指向同一弧尾顶点的下一条弧

十字链表存储结构图:

                                  十字链表

 

   

十字链表的数据类型描述:

#define MAXVEX 20
typedef struct ArcNode      //边表结点结构
{
    int tailvex,headvex;
    struct ArcNode*hnextarc,*tnextarc;
}ArcNode;
typedef struct VertexNode    //顶点表结点结构
{
    char vexdata;
    ArcNode*head,*tail;      //指向边表的头指针
}VertexNode;
typedef sturct
{
    VertexNode vertex[MAXVEX]; //存放顶点表  
    int vexnum;               //顶点数
    int arcnum;               //弧数
}OrthList;

多重链表的存储结构:

多重链表是无向图中的链式存储结构。多重链表可以更方便对无向图的操作。

 多重链表中边的两个顶点都存在边表的一个结点中,每个边结点同时链接两个链表。

多重链表的结构:

顶点表结点结构:

 vexdat:存放顶点的信息

 head:该顶点的边表的头指针

 mark:标志域,标记该边访问过,(如果此边标记过,直接指向这条边)

 ivex 和 jvex:分别存放边的两个顶点的序号

 inext :指向依附于 同一 ivex 顶点的下一条边

 jnext:指向依附于同一 jvex 顶点的下一条边

多重链表的结构图:

                                   邻接表

                                   多重链表

多重链表的数据类型描述:

#define MAXVEX 20
typedef struct ArcNode      //边表结点结构
{
    int mark,ivex,jvex;
    struct ArcNode*inext,*jnext;
}ArcNode;
typedef struct VertexNode    //顶点表结点结构
{
    char vexdata;
    ArcNode*head;      //指向边表的头指针
}VertexNode;
typedef sturct
{
    VertexNode vertex[MAXVEX]; //存放顶点表  
    int vexnum;               //顶点数
    int arcnum;               //弧数
}AdijMultipleList;

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值