数据结构——图的存储

192 阅读4分钟

图的存储结构:

1.邻接矩阵表示法:

  • 包括一个用于存储邻接矩阵的二维数组和一个存储顶点信息的一维数组:
#define MaxInt 32767 //表示极大值
#define MVNum 100 //表示最大顶点数

typedef char VerTexType; //假设顶点的数据类型为字符型
typedef int ArcType; //假设边的权值类型为整型
typedef struct
{
    VerTexType Vexs[MVNum];//顶点表
    ArcType Arcs[MVNum][MVNum];//邻接矩阵
    
    int Vexnum;//图的当前顶点数
    int Arcnum;//边数
}AMGraph;

采用邻接矩阵法创建无向网(创建图)
  • 输入总顶点数和边数
  • 依次输入点的信息存入到顶点表中
  • 初始化邻接矩阵,使得每个权值初始化为最大值
  • 构造邻接矩阵,依次输入每条边依附的顶点和权值,确定两个顶点在图中的位置后,使相应边赋予相应的权值,同时使其对称边赋予相同的权值。
邻接矩阵法存储的优缺点:
优点
  • 便于计算各个顶点的度,对于无向图,顶点i的度就是邻接矩阵第i行元素之和;对于有向图,第i行元素和是顶点i的出度,第i列元素和是i的入度。
  • 便于判断两个顶点间是否有边。
缺点
  • 不便于删除或增加顶点
  • 不便于统计边的数目,需要扫描邻接矩阵所有元素才能统计完毕。
  • 空间复杂度高,适合存储稠密图,如果存储稀疏图,比较浪费空间。
算法分析:
  • 时间复杂度O(n²)
  • 如果要构造无向图(即没有权值)需要将边的权值初始化为0,将权值赋值为1即可。
status CreateUDN(AMGraph &G)
{
    int i,j,k;
    VerTexType v1,v2;//定义两个顶点类型的变量
    ArcType w;//定义一个权值类型的变量
    
    cin>>G.Vexnum>>G.Arcnum; //输入顶点数和边数
    
    //初始化顶点表
    for(i=0;i<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;
        
        //这两句用于确定输入顶点在G中的位置,即顶点数组的下标
        i = LocateVex(G,v1);
        j = LocateVex(G,v2);
        
        G.Arcs[i][j] = w; //边<v1,v2>的权值为w
        G.Arcs[j][i] = G.arcs[i][j]; //因为是无向图,所以邻接矩阵是对称的
        
    }
    
    return OK;
}

//确定顶点位置的函数
LocateVex(AMGraph G,VerTexType v)
{
    int i;
    for(i=0;i<G.Vexnum;i++)
    {
        if(v==G.Vexs[i])
        {
            return i;
        }
    }
    return -1;
}

2.邻接表表示法:

  • 图的一种链式存储结构。在邻接表中,对图中每个的顶点vi都建立一个单链表,把与vi相邻接的顶点存在这个链表中。
  • 邻接表中每个单链表的第一个结点存放有关顶点的信息,把这个结点看成链表的表头,其余结点存放有关边的信息,邻接表由两部分组成:表头结点表边表
表头结点表:由所有表头结点以顺序结构的形式存储,以便可以随机访问任一顶点的边链表。
  • 表头结点包括 数据域(data)链域(firstarc) 两部分。
  • 数据域(data): 用于存储顶点vi的名称或其他有关信息;
  • 链域(firstarc): 用于指向链表的第一个结点(即与顶点vi邻接的第一个邻接点)。
边表:由表示图中顶点间关系的2n个边链表组成。
  • 边链表中边表结点包括三部分:
  • 邻接点域(adjvex) :存储顶点vi的邻接点在顶点表中的下标;
  • 数据域(info): 存储和边相关的信息,如权值等;
  • 链域(firstarc) :指示与顶点vi邻接的下一条边的结点;
#define MVNum 100

typedef char VerTexType;

//边结点
typedef struct ArcNode
{
    int adjvex;
    int info;
    struct ArcNode *nextarc; //指向下一条边的指针
}ArcNode;

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

typedef struct
{
    AdjList vertices;
    int vexnum,arcnum;
}ALGraph;
采用邻接表表示法创建无向图
  • 输入总顶点数和总边数
  • 依次输入点的信息存入顶点表中,每个表头结点的指针域初始化为NULL
  • 创建邻接表。依次输入每条边依附的两个顶点,确定这两个顶点的序号i和j后,将此边结点分别插入vi和vj对应的两个边链表的头部。

未完.......