图 (中)

图的存储

邻接矩阵

考虑到图是由顶点和边(弧)两部分组成,那就分成两部分存储。

图的邻接矩阵存储方式是用两个数组表示图,一个一维数组存储图中的顶点信息,一个二维数组(称为邻接矩阵)存储图中的边或者弧的信息。

设图G中有n个顶点,则邻接矩阵是一个 n×n 的方阵,定义为

arc[i][j]={1,0,(vi,vj)E<vi,vj>E

实际举例:

无向图:

顶点数组:

ABCD

边数组:

ABCDA0101B1011C0101D1110

特点:

  1. 无向图的邻接矩阵是一个对称矩阵。主对角线(左上角–>右下角)上线的元素是相等的。
  2. 某个顶点的度等于第 i 行的元素之和.B的度是1+0+1+1=3 度为3
  3. 顶点 i 的所有邻接点就是第i行的元素中为1的点.

有向图:

顶点数组:

ABCD

边数组:

ABCDA0000B1000C1000D0110

有向图的邻接矩阵一般不是对称的。

网图

每条边上带权的图叫做网

如何存储

arc[i][j]=Wij,0,,(vi,vj)E<vi,vj>Ei==j

这里的 wij 表示权值, 表示一个计算机允许的、大于所有边上权值的值,也就是一个不可能的值。一般表示不可达。

顶点数组:

ABCD

边数组:

ABCDA0B60C90D780

代码实现:

#include <stdio.h>

typedef char VertexType; /*顶点的数据类型*/

typedef int EdgeType; /*权值类型*/

#define MAXVEX 100 /*最大定点数*/

#define INFINITY 65535 /*不可达*/

typedef struct Graph
{
    VertexType vesx[MAXVEX]; // 定点表
    EdgeType arc[MAXVEX][MAXVEX]; //邻接矩阵
    int numVertexs; //当前的定点数
    int numEdges; //当前的边数
}Graph;

/**
 * @author 韦轩
 * @time 2015/08/30
 * @brief 邻接矩阵创建无向图
 * @param G 
 * @return
 */
void createUdGraph(Graph* G)
{
    printf("Input the vertexts and the edges :\n");
    scanf_s("%d,%d", &G->numVertexs, &G->numEdges);

    int i, j, w;
    for (i = 0; i < G->numVertexs;i++)
    {
        scanf_s(&G->vesx[i]);
    }

    for (i = 0; i < G->numEdges; i++)
    {
        for (j = 0; j < G->numVertexs;j++)
        {
            G->arc[i][j] = INFINITY;//初始化
        }
    }

    for (int k = 0; k < G->numEdges;k++)
    {
        printf("Input the (Vi,Vj) and the weight :\n");
        scanf_s("%d,%d,%d", &i, &j, &w);
        G->arc[i][j] = w;
        G->arc[j][i] = G->arc[i][j];
    }
}

可以看出,N个顶点和E条边的无向图的创建,时间复杂度是
O(N+N2+E) ,其中邻接矩阵的初始化,需要 O(N2)

邻接表

当边数比较少的时候,邻接矩阵对空间的浪费比较严重.

为了避免空间浪费的问题,引入了邻接表的方式:数组与链表相结合的存储方法称为邻接表(Adjacency List)

处理办法:

顶点表:图中的顶点使用一个一维数组存储,为每一个还需要存储一个指向第一个邻接点的指针。

图中的每个顶点 Vi 的所有邻接点构成一个线性表,使用单链表存储。

无向图:

邻接表

顶点表的的各个结点由data域和firstedge两个域组成,data是数据域,存储节点信息,firstedge是指针域,指向边表的第一个结点,即此节点的第一个邻接点。

边表结点有adjvex和next指针域组成,adjvex是邻接点域,存储某顶点的邻接点在定点表中的下标。next则指向边表中下一个结点的指针。

有向图:

带权:

在边表结点增加weight数据域

代码实现

#include <stdio.h>
#include <malloc.h>
typedef char VertexType;

typedef int EdgeType; //权值类型

#define MAXVEX 100

/**
 * @author 韦轩
 * @time 2015/08/30
 * @brief 边表结点
 *  
 */
typedef struct EdgeNode
{
    int adhvex; //邻接点域,存储该顶点对应的下标
    EdgeType weight;//权值
    struct EdgeNode* next;//指针域,指向下一个邻接点
}EdgeNode;

/**
 * @author 韦轩
 * @time 2015/08/30
 * @brief 顶点表结点
 */
typedef struct VertexNode
{
    VertexType data; //顶点域,存储顶点信息
    EdgeNode* firstedge; //边表头指针
}VertexNode, AdjList[MAXVEX];

/**
 * @author 韦轩
 * @time 2015/08/30
 * @brief 图
 */
typedef struct GraphAdjList
{
    AdjList adjList; 
    int numVertexs; //当前的顶点数
    int numEdges; //当前的边数
}GraphAdjList;


void creatGraph(GraphAdjList* G)
{
    int i, j, k;
    EdgeNode* edgeNode;
    printf("Input the vertexs and edges:\n");
    scanf_s("%d,%d", &G->numVertexs, &G->numEdges);
    /*
        读入顶点信息,建立顶点表
    */
    for (i = 0; i < G->numVertexs;i++)
    {
        scanf_s(&G->adjList[i].data);
        G->adjList[i].firstedge = NULL;//边表置为空表
    }

    for (k = 0; k < G->numEdges;k++)
    {
        printf("Input the vi vj:\n");
        scanf_s("%d,%d", &i, &j);

        edgeNode = (EdgeNode*)malloc(sizeof(EdgeNode));//分配内存

        /*
            生成边表结点
        */
        edgeNode->adhvex = j;//邻接序号为j

        /*
            将edgeNode指针指向当前顶点指向的结点
        */
        edgeNode->next = G->adjList[i].firstedge;

        /*
            将当前顶点的指针指向edgeNode
        */
        G->adjList[i].firstedge = edgeNode;

        edgeNode = (EdgeNode*)malloc(sizeof(EdgeNode));//分配内存

        edgeNode->adhvex = i;

        edgeNode->next = G->adjList[j].firstedge;

        /*
        将当前顶点的指针指向edgeNode
        */
        G->adjList[j].firstedge = edgeNode;
    }
}

可以看出,N个顶点和E条边的无向图的创建,时间复杂度是
O(N+E)

十字链表

邻接多重表

边集数组

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值