C++知识点总结(51):图与图的存储

一、概念

1. 数据结构

一般情况下,我们会将数据结构分为逻辑结构和物理结构,其中逻辑结构是我们的逻辑下存储的结构,而物理结构是计算机的逻辑下存储的结构。数据结构的分类可以参见下表:

数据结构
逻辑结构
非线性结构
集合结构
同属一个集合别无其他关系
树状结构
一对多
图状结构
多对多
线性结构
一对一
物理结构
顺序结构
链式结构
单链表
双链表
循环链表
索引结构
CSP-J不涉及
散列结构

2. 图

图(graph)是一种点和点之间多对多关系所组成的数据结构。图也是由顶点的非空集合 V V V 和边的集合 E E E 组成的,表示为 G = ( V , E ) G=(V,E) G=(V,E)。一般地,我们用 V ( G ) V(G) V(G) 表示图 G G G 的顶点集,用 E ( G ) E(G) E(G) 表示图 G G G 的边集。

3. 图的术语

图中的点称为 顶点
图中的点与点所具有的练习称为

点和点的关系称为 邻接
点与边的关系称为 关联

有些图点和点之间的关系是相互的,这种图被称为 无向图,无向图的边一般用 ( x , y ) (x, y) (x,y) 来表示,也可以写作 ( y , x ) (y, x) (y,x)

有些图点和点之间的关系是单向的,这种图被称为 有向图,无向图中由顶点出发的边称为 出边,指向顶点的边称为 入边。有向图的边一般用 < x , y > <x, y> <x,y> 来表示,不可以写作 < y , x > <y, x> <y,x>,因为方向不一样。

图中的边带有某种与之相关的数值,我们称之为 权值,边带有权值的图通常称为 网(加权图)
如果图是有向的,称为 加权有向图
如果图是无向的,称为 加权无向图
没有自环和重边的图就属于 简单图
对于有很少条边的图( e < n log ⁡ 2 n e<n \log_2n e<nlog2n)称为 稀疏图,反之称为 稠密图
一个图从任意一个顶点可以到另外任意一个顶点(不一定直接联通),则称为 连通图
一个图从任意两个顶点可以互相到达(不一定直接联通),则称为 强连通图
从图中提取出的图(可以是空图、一个顶点、图本身)称作 子图

没有重复顶点的一条路径称为 简单路径
起点和终点相同的路径称为 回路(环)

4. 图的公式

如果在无向图中,任意两个顶点都有一条边直接相连,这时就称该图为 无向完全图。具有 n n n 个顶点的无向完全图具有 n ( n − 1 ) 2 \frac{n(n-1)}{2} 2n(n1) 条边。

如果在有向图中,任意两个顶点都有两条边(双向)直接相连,这时就称该图为 有向完全图。具有 n n n 个顶点的无向完全图具有 n ( n − 1 ) n(n-1) n(n1) 条边。

无向图中,顶点 v v v 指的是与该顶点相关联的边的数目。
有向图中,顶点 v v v 分别是 入度出度
一个具有 n n n 个顶点, e e e 条边的图,其所有顶点的度数之和等于边数的 2 2 2 倍。
一个简单无向图中有 x x x 条边,每个顶点的度数都是 y y y,则这个图有 2 x y \frac{2x}{y} y2x 个顶点。

二、例题

1. 绘制图

{ V ( G ) = 1 , 2 , 3 , 4 , 5 E ( G ) = ( 1 , 3 ) , ( 1 , 4 ) , ( 2 , 4 ) , ( 3 , 5 ) , ( 5 , 2 ) \begin{cases} V(G) &= {1,2,3,4,5} \\ E(G) &= {(1,3),(1,4),(2,4),(3,5),(5,2)} \end{cases} {V(G)E(G)=1,2,3,4,5=(1,3),(1,4),(2,4),(3,5),(5,2)

这种题目是没有固定画法的。我们首先根据小括号确定这是一个无向图。这个图可以画成五边形、五角星等等。

{ V ( G ) = 1 , 2 , 3 , 4 E ( G ) = < 1 , 2 > , < 2 , 3 > , < 3 , 4 > , < 4 , 1 > \begin{cases} V(G) &= {1,2,3,4} \\ E(G) &= {<1,2>,<2,3>,<3,4>,<4,1>} \end{cases} {V(G)E(G)=1,2,3,4=<1,2>,<2,3>,<3,4>,<4,1>

根据尖括号确定这是一个有向图。可以画成正方形、漏斗形等等。

2. 带权邻接矩阵

#include <iostream>
#include <cstring>
using namespace std;

int n, m;
int a, b, c;
int adj[105][105];

int main()
{
    cin >> n >> m;
    
    for (int i = 1; i <= m; i++)
    {
        cin >> a >> b >> c;
        adj[a][b] = c;
    }

    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            if (adj[i][j] == 0) cout << "* ";
            else cout << adj[i][j] << " ";
        }
        cout << endl;
    }
    return 0;
}

3. 优化带权邻接矩阵

我们可以考虑优化,用二维动态结构体数组来存储这一系列的内容。

#include <iostream>
#include <vector>
using namespace std;

struct Node
{
    int v, w; // v: 点  w: 权值
};

int n, m;
int a, b, c;
vector <Node> adj[105];

int main()
{
    cin >> n >> m;
    while (m--)
    {
        cin >> a >> b >> c;
        adj[a].push_back({b, c});
    }
    for (int i = 1; i <= n; i++)
    {
        cout << i << ":";
        for (int j = 0; j < adj[i].size(); j++)
            cout << adj[i][j].v << " ";
        cout << endl;
    }
    return 0;
}
  • 10
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值