图论_(1)_图的基本概念

这篇具有很好参考价值的文章主要介绍了图论_(1)_图的基本概念。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

基本概念

图(graph) 是由顶点集合和顶点间的二元关系集合(即边的集合或弧的集合)组成的数据结构,通常可以用 G ( V , E ) G(V,E) G(V,E)表示
顶点集合(vertext set) V ( G ) V(G) V(G) 表示,其中元素称为顶点(vertex),用 u 、 v u、v uv 等符号表示。
边的集合(edge set) E ( G ) E(G) E(G) 表示,其中元素称为边(edge),用 e e e 等符号表示
图的阶(order):顶点的个数,通常用 n n n 表示
边数(size): 边的个数,通常用 m m m 表示

无向图

图中所有的边都没有方向性,这种图称为无向图(undirected graph).
每个元素 ( u , v ) (u,v) (u,v)为一对顶点构成的无序对(用圆括号括起来),便是与顶点 u u u v v v 相关联的一条无向边(undirected edge),这条边没有特定的方向。

E ( G 1 ) = { ( 1 , 2 ) , ( 1 , 3 ) , ( 2 , 3 ) , ( 2 , 4 ) , ( 2 , 5 ) , ( 2 , 6 ) , ( 3 , 4 ) , ( 3 , 5 ) , ( 4 , 5 ) } E(G_1)=\{ (1,2),(1,3),(2,3),(2,4),(2,5),(2,6),(3,4),(3,5),(4,5) \} E(G1)={(1,2),(1,3),(2,3),(2,4),(2,5),(2,6),(3,4),(3,5),(4,5)}
图论_(1)_图的基本概念

有向图

图中所有边都是有方向性的,这种图称为有向图,有向图的边也可以称为弧(arc)

度数

顶点的度数(degree):一个顶点 u u u的度数是与它相关联的边的数目,记作 d e g ( u ) deg(u) deg(u)
顶点的出度(outdegree):是以 u u u 为起始的顶点的有向边(即从顶点 u u u 出发的有向边)的数目,记作 o d ( u ) od(u) od(u)
顶点的入度(indegree):是以 u u u 为终点的顶点的有向边(即从顶点 u u u 进入的有向边)的数目,记作 i d ( u ) id(u) id(u)
d e g ( u ) = o d ( u ) + i d ( u ) deg(u)=od(u)+id(u) deg(u)=od(u)+id(u)
定理:在无向图和有向图中,所有顶点度数总和,等于边数的两倍
m = 1 2 { ∑ i = 1 n d e g ( u i ) } m=\frac{1}{2}\{ \sum_{i=1}^ndeg(u_i)\} m=21{i=1ndeg(ui)}
偶点(even vertex):度数为偶数的顶点称为偶点
奇点(odd vertex):度数为奇数的顶点称为奇点

推论:每个图都有偶数个奇点

孤立顶点(isolated vertex):度数为0的顶点,称为孤立顶点。孤立顶点不与其他任何顶点邻接。
叶(leaf):度数为1的顶点,称为叶顶点,也称端点(end vertex), 其他顶点称为非叶顶点
图的最小度(minimum degree):图所有顶点最小的度数,记为 δ ( G ) \delta(G) δ(G)
图的最大度(maximum degree):图所有顶点的最大的度数,记为 Δ ( G ) \Delta(G) Δ(G)

Havel-Hakimi 定理(判断是否可图)

由非负整数组成的非增序列 s : d 1 , d 2 , … , d n ( n ≥ 2 , d 1 ≥ 1 ) s:d_1,d_2,\ldots,d_n(n\geq2,d_1\geq1) s:d1,d2,,dn(n2,d11)是可图的,当且仅当序列
s 1 : d 2 − 1 , d 3 − 1 , … , d d 1 + 1 − 1 , d d 1 + 2 , … , d n s_1:d_2-1,d_3-1,\ldots,d_{d1+1}-1,d_{d1+2},\ldots,d_n s1:d21,d31,,dd1+11,dd1+2,,dn
是可图的。序列 s 1 s_1 s1 中有 n − 1 n-1 n1 个非负整数, s s s 序列中 d 1 d_1 d1后的前 d 1 d_1 d1 个度数(即 d 2 d_2 d2 ~ d d 1 + 1 d_{d1+1} dd1+1 减1 后构成 s 1 s1 s1 中前 d 1 d_1 d1 个数

eg:判断 s : 5 , 4 , 3 , 3 , 2 , 2 , 2 , 1 , 1 , 1 s:5,4,3,3,2,2,2,1,1,1 s:5,4,3,3,2,2,2,1,1,1 是否可图?

  1. 删除序列 s 的首项5, 对其后的5项每项减1,得到 3,2,2,1,1,2,1,1,1, 重新排序 3,2,2,2,1,1,1,1,1
  2. 继续删除序列的首项3,对其后的3项每项减1,得到:1,1,1,1,1,1,1,1
  3. 如下图推导,可判断序列可图

图论_(1)_图的基本概念
eg 判断序列 s : 7 , 7 , 4 , 3 , 3 , 3 , 2 , 1 s: 7,7,4,3,3,3,2,1 s:7,7,4,3,3,3,2,1 是否可图的。

  1. 删除序列 s 的首项7,对其后面的7项每项减1,得到 6,3,2,2,2,1,0
  2. 删除首项6,对其后面6项每项减1,得到 2,1,1,1,0,-1

出现负数,序列是不可图的
图论_(1)_图的基本概念

邻接矩阵

邻接矩阵(adjacency matrix):一个表示各顶点之间关系的二维矩阵
E d g e [ i ] [ j ] = { 1 , < i , j > ∈ E , 或 ( i , j ) ∈ E 0 Edge[i][j] = \begin{cases} 1 ,<i,j>\in E, 或(i,j) \in E\\ 0\\ \end{cases} Edge[i][j]={1,<i,j>E,(i,j)E0
无向图 的邻接矩阵是沿主对角线 对称
有向图 的邻接矩阵 不一定 沿主对角线对称
无法用邻接矩阵存储: 图中存在自身环(self loop, 连接某个顶点自身的边) 和 重边 (multiple edge, 多条边的起点一样,终点也一样,亦称平行边,parallel edge)

通过邻接矩阵求无向图的度数
d e g ( i ) = ∑ j = 0 n − 1 E d g e [ i ] [ j ] = ∑ j = 0 n − 1 E d g e [ j ] [ i ] deg(i)=\sum_{j=0}^{n-1}Edge[i][j]=\sum_{j=0}^{n-1}Edge[j][i] deg(i)=j=0n1Edge[i][j]=j=0n1Edge[j][i]
邻接矩阵第 i i i 行所有元素之和,表示顶点 i i i 的度数,或者 第 i i i 列所有元素之和,表示顶点 i i i 的度数
通过邻接矩阵求有向图的出度与入度
出度:第 i i i 所有元素之和
o d ( i ) = ∑ j = 0 n − 1 E d g e [ i ] [ j ] od(i)=\sum_{j=0}^{n-1}Edge[i][j] od(i)=j=0n1Edge[i][j]
入度:第 i i i 所有元素之和
i d ( i ) = ∑ j = 0 n − 1 E d g e [ j ] [ i ] id(i)=\sum_{j=0}^{n-1}Edge[j][i] id(i)=j=0n1Edge[j][i]

邻接表

邻接表(adjacency list): 把从同一个顶点发出的边链接在同一个称为 边链表 的单链表中
边结点: 边链表中的每个结点代表一条边,有两个域

  1. 该边终点的序号
  2. 指向下一个边结点的指针

顶点数组:用于存储顶点信息,每个元素有两个成员
3. 一个成员用于存储顶点信息
4. 一个成员为该顶点的边链表的表头指针,指向该顶点的边链表

图论_(1)_图的基本概念

出边表:在邻接表每个顶点的边链表中,各边结点所表示的边都是从该顶点发出的边。

出边表的出度 : 统计出边表每个顶点的边链表中边结点的个数
逆邻接表(入边表):把进入同一个顶点的边链接在同一个边链表中。
入边表的入度 : 统计入边表每个顶点的边链表中边结点的个数
图论_(1)_图的基本概念
使用 出边表 表示有向图的邻接表
图论_(1)_图的基本概念

使用 入边表 表示有向图的邻接表
图论_(1)_图的基本概念
无向图 如下,使用 邻接表 表示
图论_(1)_图的基本概念
图论_(1)_图的基本概念

eg1 用邻接矩阵存储有向图,并输出各顶点的出入度

图论_(1)_图的基本概念
输入 第一行为顶点个数及边数,第二行开始为边的关系

7 9
1 2
2 3
2 5
2 6
3 5
4 3
5 2
5 4
6 7
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#define MAXN 100
int Edge[MAXN][MAXN];

int main(){
    int a,b;
    int i,j,count;
    int n,m;    // 顶点个数、边数
    int u,v;    // 边的起点和终点
    int od,id;  // 顶点的出度、入度


    FILE *file = fopen("1_1.txt","r");
    if(!file){
        printf("Fail to open file....\n");
        return;
    }

    memset(Edge,0,sizeof(Edge));
    count = 0;
    while(1){
        if(EOF == fscanf(file,"%d %d",&a,&b))
            break;

        count = count + 1;
        if(count==1){
            n=a;
            m=b;
        }

        if (count != 1){
            u=a;
            v=b;
            Edge[u-1][v-1]=1;
        }
    }
    fclose(file);

    printf("%d %d\n",n,m);

    // 打印邻接矩阵
    for(i=0;i<n;i++){
        for(j=0;j<n;j++){
            printf("%d,",Edge[i][j]);
        }
        printf("\n");
    }

    // 求各顶点的出度
    printf("\n各顶点的出度为:\n");
    for(i=0; i<n; i++){
        od = 0;
        for(j=0;j<n;j++){
            od = od + Edge[i][j];  // 累加第i行

        }
        printf("%d ",od);
    }
    printf("\n");

    printf("各顶点的入度为:\n");
    // 求各顶点的入度
    for(i=0;i<n;i++){
        id = 0;
        for(j=0;j<n;j++)
            id =id + Edge[j][i];   //累计第i列
        printf("%d ",id);
    }
    printf("\n");
    return 0;
}

图论_(1)_图的基本概念
图论_(1)_图的基本概念

eg2 判断是否可图

图论_(1)_图的基本概念
输入: 测试组数,每组输入顶点个数,及顶点的度数
输出: 邻接矩阵

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define N 15

struct vertex{
    int degree;  //顶点的度
    int index;   //顶点的序号
}v[N];


int cmp(const void *a,const void *b)
{
	return (((struct vertex*)b)->degree) -( ((struct vertex*)a)->degree);
}


int main(){
    int r,k,p,q;        // 循环遍历
    int i,j;            // 顶点序号
    int d1;             // 对剩下序列排列后的第1个顶点(度数最大的顶点)的度数
    int T,n;            // 测试数据的个数,顶点的个数
    int Edge[N][N],flag;  // 邻接矩阵,是否存在合理相邻关系的标记

    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(i=0;i<n;i++){
            scanf("%d",&v[i].degree);
            v[i].index=i;           // 按输入顺序给每个湖泊(顶点)编号
        }

        memset(Edge,0,sizeof(Edge));
        flag=1;
        for(k=0;k<n&&flag;k++){
            qsort(v+k,n-k,sizeof(struct vertex),cmp);  // 对数组进行快速排序,从大到小
            i=v[k].index;
            d1=v[k].degree;
            if(d1>n-k-1)
                flag = 0;
            for(r=1;r<=d1&&flag;r++){
                j=v[k+r].index;
                if(v[k+r].degree<=0) flag=0;
                v[k+r].degree--;
                Edge[i][j]=Edge[j][i]=1;
            }
        }
        if(flag){
            puts("Yes");
            for(p=0;p<n;p++){
                for(q=0;q<n;q++){
                    if(q) printf(" ");
                    printf("%d ",Edge[p][q]);
                }
                puts(" ");
            }
        }
        else
            puts("No");
        if(T) puts("");
    }
    return 0;
}

在这里插入图片描述

eg3 用邻接表存储有向图,求各顶点出度与入读

输入:第一行为顶点个数及边数,第二行开始为边的关系
输出:第一行为顶点的出度,第二行为顶点的入度
测试数据1

7 9
1 2
2 3
2 5
2 6
3 5
4 3
5 2
5 4
6 7

图论_(1)_图的基本概念
测试数据2:

4 7
1 4
2 1
2 2
2 3
2 3
4 2
4 3

图论_(1)_图的基本概念

#include<stdio.h>
#include<stdlib.h>

#define MAXN 100

struct ArcNode{ //边节点
    int adjvex;     // 有向边的另一个邻接点的序号
    struct ArcNode *nextarc;   // 指向下一个边结点的指针
};

struct VNode{   //顶点
    struct ArcNode *head1;     // 出边表的表头指针
    struct ArcNode *head2;     // 入边表的表头指针
};

struct LGraph{  // 图的邻接表存储结构
    struct VNode vertexs[MAXN];    //顶点数组,每个顶点为一个结构体
    int vexnum,arcnum;      //顶点数和边数
};  //图(邻接表存储)
struct LGraph lg;

void CreateLG(){        // 采用邻接表存储表示,构造有向图 G
    int i=0,a,b;
    int v1,v2;
    struct ArcNode *pi;


    for(i=0;i<lg.vexnum;i++){
        lg.vertexs[i].head1=lg.vertexs[i].head2=NULL;
    }

    FILE *file = fopen("1_3_demo.txt","r");
    if(!file){
        printf("创建图期间 Fail to open file....\n");
        return 0;
    }
    int count = 0;
    while(1){
        if(EOF == fscanf(file,"%d %d",&a,&b))
            break;

        count = count+1;

        if(count!=1){
            v1=a;
            v2=b;
            v1--;
            v2--;
            pi = (struct ArcNode*)calloc(2,sizeof(struct ArcNode));
            pi->adjvex = v2;
            pi->nextarc = lg.vertexs[v1].head1;
            lg.vertexs[v1].head1 = pi;
      
            pi = (struct ArcNode*)calloc(2,sizeof(struct ArcNode));
            pi->nextarc = v1;
            pi->nextarc = lg.vertexs[v2].head2;
            lg.vertexs[v2].head2 = pi;
        }
    }
    fclose(file);

}

// 释放图G邻接表各顶点的边链表中的所有节点所占用的存储空间
void DeleteLG(){
    int i;
    struct ArcNode *pi;
    for(i=0;i<lg.vexnum;i++){
        pi = lg.vertexs[i].head1;
        while(pi!=NULL){
            lg.vertexs[i].head1 = pi->nextarc;
            free(pi);
            pi = lg.vertexs[i].head1;
        }
        pi = lg.vertexs[i].head2;
        while(pi!=NULL){
            lg.vertexs[i].head2 = pi->nextarc;
            free(pi);
            pi = lg.vertexs[i].head2;
        }
    }
}

int main(){
    int i,a,b;
    int id,od;
    struct ArcNode *pi;

    FILE *file = fopen("1_3_demo.txt","r");
    if(!file){
        printf("创建图期间 Fail to open file....\n");
        return 0;
    }
    int count = 0;
    while(1){
        if(EOF == fscanf(file,"%d %d",&a,&b))
            break;

        count = count + 1;
        if(count==1){
            lg.vexnum=a;
            lg.arcnum=b;
        }
    }
    fclose(file);
    printf("文件中图的顶点个数及边数读取完成...\n");
    CreateLG();

    for(i=0;i<lg.vexnum;i++){
        od=0;
        pi=lg.vertexs[i].head1;
        while(pi!=NULL){
            od++;
            pi=pi->nextarc;
        }
        if(i==0) printf("%d ",od);
        else
            printf("%d ",od);
    }
    printf("\n");
    for(i=0;i<lg.vexnum;i++){
        id=0;
        pi=lg.vertexs[i].head2;
        while(pi!=NULL){
            id++;
            pi = pi->nextarc;
        }
        if(i==0)
            printf("%d ",id);
        else
            printf("%d ",id);
    }
    printf("\n");
    DeleteLG();
    return 0;
}

核心代码计算机详细过程

pi = (struct ArcNode*)calloc(2,sizeof(struct ArcNode));
pi->adjvex = v2;
pi->nextarc = lg.vertexs[v1].head1;
lg.vertexs[v1].head1 = pi;

图论_(1)_图的基本概念文章来源地址https://www.toymoban.com/news/detail-450009.html

到了这里,关于图论_(1)_图的基本概念的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 图论与算法(2)图的基本表示

    (1) 有向图和无向图: 有向图(Directed Graph):图中的边具有方向,表示节点之间的单向关系。 无向图(Undirected Graph):图中的边没有方向,表示节点之间的双向关系。 (2)加权图和无权图: 加权图(Weighted Graph):图中的边具有权重或距离,表示节点之间的关系有一定

    2024年02月04日
    浏览(47)
  • 图论01-【无权无向】-图的基本表示-邻接矩阵/邻接表

    https://github.com/Chufeng-Jiang/Graph-Theory/tree/main/src/Chapt01_Adjacency 代码有删减 代码有删减 只需要改动一行 adj = new TreeSet[V]; //构造邻接表, V行,V个LinkedList 代码有删减

    2024年02月07日
    浏览(44)
  • 离散数学:图的基本概念

    本帖子讨论图的基本概念,这一章,我们将利用有序对和二元关系的概念定义图。图分为了无向图和有向图,他们有共性也有区别,请大家注意体会,用联系和辩证的观点去认识。 注意无向图和有向图的表示,最大区别在于边的集合的表示,无向图中边集为无序集VV的子集,

    2024年02月09日
    浏览(53)
  • 图的基本概念

    一个图 G 它可以由顶点集(图 G 中顶点的有限非空集) V 和边集(图 G 中顶点之间的关系集合) E 所组成。图中顶点个数也可以称为图的阶;任何一条边的两头必须连接某一个顶点。图不可以是空,即顶点集 V 一定是非空集,但边集 E 可以是空集。 有向图 无向图 无向图里的

    2024年02月14日
    浏览(51)
  • 数据结构:图的基本概念

    图是一种非线性的数据结构,表示多对多的关系。 图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V, E),其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合。 在图中需要注意的是: 线性表和树可以看做特殊的图。 线性表中我们把数据

    2023年04月12日
    浏览(45)
  • 离散数学 第十章 图的基本概念

    目录 10.1 图的基本概念 10.2 道路与回路 10.3 图的连通性 10.4 图的矩阵表示 ①什么是图:一个序偶(V,E),记作G=(V,E)                          V(G)={v1,v2,...,vn} 结点集,n为G的阶                         E(G)={e1,e2,...,em} 边集,m为G的边数 ②图的分类: 1.无向图

    2024年02月07日
    浏览(47)
  • 图论相关基本概念

    从逻辑结构上讲,图是一种典型的 非线性结构 。 图(Graph) 是由 顶点的有穷非空集合和顶点之间边的集合 组成的,通常表示为 G(V , E) ,其中, G表示—个图,V是图G中顶点的集合,E是图G中边的集合。其中: 顶点集合V={x|x属于某个数据对象集}是有穷非空集合 E={(x,y)|

    2024年02月01日
    浏览(39)
  • 图论 | 网络流的基本概念

    流网络: G = ( V , E ) G = (V, E) G = ( V , E ) 有向图,不考虑反向边 s:源点 t:汇点 c ( u , v ) c(u, v) c ( u , v ) :边的最大容量 可行流 f f f 容量限制: 0 ≤ f ( u , v ) ≤ c ( u , v ) 0 leq f(u, v) leq c(u, v) 0 ≤ f ( u , v ) ≤ c ( u , v ) 流量守恒:除了源点和汇点,所有点满足 流入 = 流出 流入

    2024年02月04日
    浏览(39)
  • [入门必看]数据结构6.1:图的基本概念

    小题考频:33 大题考频:11 难度:☆☆☆☆ 6.1.1 图的基本概念 图的定义 A、B、C……这些元素的集合就是顶点集V,图G中顶点个数也成为图G的阶; 连接各个顶点的边的集合就是边集E 注意。图里面的一条边,连接的u,v两个顶点必须是刚才给出的顶点集中的顶点,边的两头必须

    2024年02月06日
    浏览(44)
  • 图论:十字链表的基本概念理解

    写博客是为了学习理解更深刻         在学习甲鱼课的十字链表时稍稍有点懵,进C站查找一番后发现也没有比较亲近小白的描述和解释。抱着让自己理解更深刻以及与大家分享的态度写下了这篇博客。如有错误请指出。         邻接表的使用简单方便,但在对有向图的处

    2023年04月08日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包