首页 > 其他分享 >35. 图的建立

35. 图的建立

时间:2023-06-23 21:23:47浏览次数:29  
标签:struct 建立 int graph vertexNum 35 edge 顶点

一、邻接矩阵表示图

1.1、图的表示

  节点数为 n 的图 \(G = (V,E)\) 的邻接矩阵 A 是 n*n 的。将 G 的顶点编号为 \(v_{1},v_{2},...,v_{n}\),则

\[A[i][j] = \begin{cases} 1 &,若(v_{i},v_{j}) 或 <v_{i},v_{j}> 是 E(G) 中的边\\ 0 & ,若 (v_{i},v_{j}) 或 <v_{i},v_{j}> 不是 E(G) 中的边 \end{cases} \]

#define WeightType      int                             // 带权图中边上权值的数据类型
#define VertexType      char                            // 顶点的数据类型
#define MaxVertexNum    10                              // 顶点数目的最大值

typedef struct GNode *PtrToGNode;
typedef PtrToGNode MGraph;                              // 以邻接矩阵存储的图类型
typedef struct ENode *PtrToENode;
typedef PtrToENode Edge;                                // 边

// 用邻接矩阵存储图
struct GNode
{
    VertexType vertex[MaxVertexNum];                    // 顶点表
    WeightType edge[MaxVertexNum][MaxVertexNum];        // 邻接矩阵,边表
    int vertexNum;                                      // 顶点数
    int edgeNum;                                        // 边数
};

// 边
struct ENode
{
    int v1,v2;                                          // 有向边<v1,v2>
    WeightType weight;                                  // 权重
};

1.2、初始化只有顶点的图

/**
 * @brief 初始化一个有vertexNum个顶点但没有边的图
 * 
 * @param vertexNum 顶点数
 * @return MGraph 返回指向图的指针
 */
MGraph CreateGraph(int vertexNum)
{
    MGraph graph;
    int V,E;

    graph = (MGraph)malloc(sizeof(struct GNode));
    graph->vertexNum = vertexNum;
    graph->edgeNum = 0;

    for(V = 0; V < graph->vertexNum; V++)
    {
        for(E = 0; E < graph->vertexNum; E++)
        {
            graph->edge[V][E] = 0;
        }
    }

    return graph;
}

1.3、向图中插入边

/**
 * @brief 向图中插入边
 * 
 * @param graph 待操作的图
 * @param edge 待插入的边
 */
void InsertEdge(MGraph graph, Edge edge)
{
    graph->edge[edge->v1][edge->v2] = edge->weight;         // 插入边<V1,V2>
    // 若是无向图,还要插入边<V2,V1>
    graph->edge[edge->v2][edge->v1] = edge->weight;
    graph->edgeNum++;
}

1.4、创建图

/**
 * @brief 创建图
 * 
 * @return MGraph 返回指向图的指针
 */
MGraph BuildGraph()
{
    MGraph graph;
    Edge edge;
    VertexType vertex;
    int vertexNum,edgeNum,i;

    printf("请输入顶点数:\n");
    scanf("%d", &vertexNum);
    getchar();

    graph = CreateGraph(vertexNum);

    // 如果顶点有数据的话,读入数据
    printf("请输入顶点的数据:\n");
    for(i = 0; i < graph->vertexNum; i++)
    {
        scanf("%c", &(graph->vertex[i]));
        getchar();
    }

    printf("请输入边数:\n");
    scanf("%d", &edgeNum);
    getchar();

    printf("请输入对应的边:\n");
    printf("(格式为:第一个顶点下标 第二个顶点下标 权值)\n");
    if(edgeNum != 0)
    {
        edge = (Edge)malloc(sizeof(struct ENode));
        for(i = 0; i < edgeNum; i++)
        {
            scanf("%d %d %d", &edge->v1, &edge->v2, &edge->weight);
            getchar();
            InsertEdge(graph, edge);
        }
    }

    return graph;
}

二、邻接表表示法

2.1、图的表示

  邻接表:G[N] 为指针数组,对应矩阵每行一个链表,只存非 0 元素。

#define WeightType      int                     // 带权图中边上权值的数据类型
#define VertexType      char                    // 顶点类型
#define MaxVertexNum    10                      // 顶点数目的最大值

typedef struct GNode *PtrToGNode;
typedef PtrToGNode LGraph;                      // 以邻接表存储的图类型
typedef struct AdjVNode *PtrToAdjVNode;
typedef struct ENode *PtrToENode;
typedef PtrToENode Edge;                        // 边

// 顶点信息
typedef struct VNode
{
    VertexType data;                            // 存顶点数据
    PtrToAdjVNode firstEdge;                    // 第一条边
}AdjList[MaxVertexNum];

// 边信息
struct AdjVNode
{
    int adjVex;                                 // 边指向哪个节点(邻接点下标)
    WeightType weight;                          // 边权重
    PtrToAdjVNode next;                         // 指向下一条边的指针
};

// 边
struct ENode
{
    VertexType v1,v2;                           // 有向边<V1,V2>
    WeightType weight;                          // 权重
};

// 用邻接表存储图
struct GNode
{
    AdjList vertices;                           // 邻接表
    int vertexNum;                              // 顶点数
    int edgeNum;                                // 边数
};

2.2、初始化只有顶点的图

/**
 * @brief 初始化一个有VertexNum个顶点但没有边的图
 * 
 * @param vertexNum 顶点数
 * @return MGraph 返回指向图的指针
 */
LGraph CreateGraph(int vertexNum)
{
    LGraph graph;
    int V,E;

    graph = (LGraph)malloc(sizeof(struct GNode));
    graph->vertexNum = vertexNum;
    graph->edgeNum = 0;

    for(V = 0; V < graph->vertexNum; V++)
    {
        graph->vertices[V].firstEdge = NULL;
    }

    return graph;
}

2.3、向图中插入边

/**
 * @brief 向图中插入边
 * 
 * @param graph 待操作的图
 * @param edge 待插入的边
 */
void InsertEdge(LGraph graph, Edge edge)
{
    PtrToAdjVNode newNode;

    // 为v2建立新的邻接点
    newNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
    newNode->adjVex = edge->v2;
    newNode->weight = edge->weight;

    // 将v2插入v1的表头
    newNode->next = graph->vertices[edge->v1].firstEdge;
    graph->vertices[edge->v1].firstEdge = newNode;

    // 若是无向图,还需要插入边<v2,v1>
    // 为v1建立新的邻接点
    newNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
    newNode->adjVex = edge->v1;
    newNode->weight = edge->weight;

    // 将v1插入v2的表头
    newNode->next = graph->vertices[edge->v2].firstEdge;
    graph->vertices[edge->v2].firstEdge = newNode;
}

2.4、创建图

/**
 * @brief 创建图
 * 
 * @return LGraph 返回指向图的指针
 */
LGraph BuildGraph(void)
{
    LGraph graph;
    Edge edge;
    int V;
    int vertexNum,i;

    printf("请输入顶点数:\n");
    scanf("%d", &vertexNum);
    getchar();

    // 如果顶点有数据的话,读入数据
    printf("请输入顶点的数据:\n");
    for(i = 0; i < graph->vertexNum; i++)
    {
        scanf("%c", &(graph->vertices[i].data));
        getchar();
    }

    graph = CreateGraph(vertexNum);

    printf("请输入边数:\n");
    scanf("%d", &(graph->edgeNum));
    getchar();

    if(graph->edgeNum != 0)
    {
        printf("请输入对应的边:\n");
        printf("(格式为:第一个顶点下标 第二个顶点下标 权值)\n");

        edge = (Edge)malloc(sizeof(struct ENode));
        for(i = 0; i < graph->edgeNum; i++)
        {
            scanf("%d %d %d", &edge->v1, &edge->v2, &edge->weight);
            getchar();
            InsertEdge(graph, edge);
        }
    }

    return graph;
}

标签:struct,建立,int,graph,vertexNum,35,edge,顶点
From: https://www.cnblogs.com/kurome/p/17500200.html

相关文章

  • CF1835D&E&F
    感觉这三题分开写很浪费,所以合并成了半场CF的总结(CF1835DDoctor'sBrownHypothesis首先你看到这个\(k\geqn^3\)就在疯狂暗示,也就是说你可以经过每个环,并且对于每个环都绕\(n-1\)圈,因此只需要满足增量被所有环长的\(\gcd\)整除并且在一个SCC里面,那么就是可以调整到......
  • [转]火狐浏览器访问github提示:未连接:有潜在的安全问题...github.com 启用了被称为 HTT
    火狐浏览器访问github,提示:       未连接:有潜在的安全问题;       Firefox检测到潜在的安全威胁,并因github.com要求安全连接而没有继续。如果这种情况是因为使用DevSidecar而引起的,可以使用以下方式解决:在地址栏输入:about:config在搜索框输入:security.en......
  • 一天被艾特@48次!35岁Android程序员处境堪比生产队的驴!
    缘起随着互联网和移动互联网的快速发展,各类应用软件(app)如雨后春笋般涌现,许多应用程序甚至成为超级app,一些活跃用户过亿的应用程序成为国民app,这些app的兴起与程序员这个群体密不可分。快速发展的行业、互联网巨头的光环、国民级的应用程序带来的成就感、远超出普通行业的薪水,每年......
  • 最新Android音视频开发学习指南,建立自己的技术护城河
    我们常说音视频是程序员小众领域,但其实音视频技术在日常生活中随处可见:直播中要保证在各种网络状况下实现超低价延时、降低卡顿率,就需要用到音视频中的RTC和直播技术;上百人的视频会议若要保证流畅度和清晰的画质就要用到RTC和转码合流服务等技术…Android音视频开发进阶指南目......
  • 我35岁了,我担心我失业就再也找不到程序员的工作了
    写在前面人到中年发现自己竟没有任何核心优势!最尴尬的事情,莫过于一个程序员在10多年,甚至20年的从业经历中,一直没好好考虑过如何构建自己的核心竞争力。如果长年如此,会导致他就跟着公司慢吞吞的走着,就像温水煮青蛙,直到30多、40岁的时候,突然发现自己几乎一无所长。举个例子,比如从技术......
  • Polardb 如何替换MYSQL 之 IMCI 列式(1)建立一个列式引擎
    开头还是介绍一下群,如果感兴趣polardb,mongodb,mysql,postgresql,redis等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,可以解决你的问题。讲了那么多期,都是在力量上进行论述,本期开始进入到正式的POALRDB的内部操作中,POLARDB与MYSQL在登录中最大的不同是,你可以通过代......
  • POSTGRESQL SQL 优化,不建立索引,不调整参数,不修改SQL的另类方式
    开头还是介绍一下群,如果感兴趣polardb,mongodb,mysql,postgresql,redis等有问题,有需求都可以加群群内有各大数据库行业大咖,CTO,软件架构师,软件开发大佬,可以解决你的问题。在MYSQL中很少听说过自建统计信息,实际上在其他数据库中,创建统计信息的方式和需求都是有的,尤其处理复杂SQ......
  • 一个40岁中年程序员的感言:一定要学好这些东西,35 岁以后也依然被公司抢着要!
    时光给我留下了什么?不知不觉间虚度了40年光阴,看着父母逐渐的苍老和孩子逐渐长大,看着自己发福的身材,已知道自己在这个陌生的城市里已经扎根,估计是很难再去哪里了。回首故里似乎和童年一样渐渐变得模糊,每次回家总感觉自己已经很难融入其中,看着别人聊天聊地,自己也很难插上嘴,曾经自己所......
  • Codeforces 1835F - Good Graph
    goodproblem,badround。判断YES还是NO很trivial,就直接跑最大匹配看看是不是\(n\)即可。如果是NO,那么考虑Hall定理的证明过程构造即可。具体方法就是找到左部任意一非匹配点,在残量网络上BFS可以到达的点,那所有可以到达的左部点形成的集合就是符合要求的反例。因为你......
  • Codeforces 1835E - Old Mobile
    首先先观察到一个非常浅显的性质:就是一个位置在序列中不是第一次出现,那么到这个位置的时候打出这个字符需要恰好一次按键,这是因为我们肯定在打出第一次出现这个字符的位置的时候已经知道哪个键对应这个字符了,到那个位置的时候直接敲一下就ok了。也就是我们只用关心这个序列中出......