图的概念、性质和存储与简单遍历

news2024/11/25 18:54:06

前置知识:树的基本概念及性质

为了保证学习效果,请保证已经掌握前置知识之后,再来学习本章节!如果在阅读中遇到困难,也可以回到前面章节查阅。

学习目标

  • 掌握图的基本概念
  • 掌握图的一些性质

图的概念

基本概念

图 (Graph) 是一个二元组 𝐺=(𝑉(𝐺),𝐸(𝐺))G=(V(G),E(G)) 。其中 𝑉(𝐺)V(G) 是非空集,称为 点集 (Vertex set) ,对于 𝑉V 中的每个元素,我们称其为 顶点 (Vertex) 或 节点 (Node) ,简称  ; 𝐸(𝐺)E(G) 为 𝑉(𝐺)V(G) 各结点之间边的集合,称为 边集 (Edge set) 。

常用 𝐺=(𝑉,𝐸)G=(V,E) 表示图。

当 𝑉,𝐸V,E 都是有限集合时,称 𝐺G 为 有限图 。

当 𝑉V 或 𝐸E 是无限集合时,称 𝐺G 为 无限图 。

图有多种,包括 无向图 (Undirected graph) , 有向图 (Directed graph) , 混合图 (Mixed graph) 等

若 𝐺G 为无向图,则 𝐸E 中的每个元素为一个无序二元组 (𝑢,𝑣)(u,v) ,称作 无向边 (Undirected edge) ,简称 边 (Edge) ,其中 𝑢,𝑣∈𝑉u,v∈V 。设 𝑒=(𝑢,𝑣)e=(u,v) ,则 𝑢u 和 𝑣v 称为 𝑒e 的 端点 (Endpoint) 。

若 𝐺G 为混合图,则 𝐸E 中既有向边,又有无向边。

若 𝐺G 的每条边 𝑒𝑘=(𝑢𝑘,𝑣𝑘)ek​=(uk​,vk​) 都被赋予一个数作为该边的  ,则称 𝐺G 为 赋权图 。如果这些权都是正实数,就称 𝐺G 为 正权图 。

形象地说,图是由若干点以及连接点与点的边构成的。

图片

图上的关系

点与点——邻接

在无向图 𝐺=(𝑉,𝐸)G=(V,E) 中,对于两顶点 𝑢u 和 𝑣v ,若存在边 (𝑢,𝑣)(u,v) ,则称 𝑢u 和 𝑣v 是 相邻(邻接)的 。

一个顶点 𝑣∈𝑉v∈V 的 邻域 (Neighborhood) 是所有与之相邻的顶点所构成的集合,记作 𝑁(𝑣)N(v) 。

PS:邻接表存储的就是邻域,并且由此得名。

点与边——关联

在无向图 𝐺=(𝑉,𝐸)G=(V,E) 中,若点 𝑣v 是边 𝑒e 的一个端点,则称 𝑣v 和 𝑒e 是 关联的

度数

与一个顶点 𝑣v 关联的边的条数称作该顶点的 度 (Degree) ,记作 𝑑(𝑣)d(v) 。特别地,对于边 (𝑣,𝑣)(v,v) ,则每条这样的边要对 𝑑(𝑣)d(v) 产生 22 的贡献。

对于无向简单图,有 𝑑(𝑣)=∣𝑁(𝑣)∣d(v)=∣N(v)∣ 。

握手定理(又称图论基本定理):对于任何无向图 𝐺=(𝑉,𝐸)G=(V,E) ,有 ∑𝑣∈𝑉𝑑(𝑣)=2∣𝐸∣∑v∈V​d(v)=2∣E∣ ,即无向图中结点度数的总和等于边数的两倍。有向图中结点的入度之和等于出度之和等于边数。

推论: 在任意图中,度数为奇数的点必然有偶数个。

证明:反证法

简单图

自环 (Loop) :对 𝐸E 中的边 𝑒=(𝑢,𝑣)e=(u,v) ,若 𝑢=𝑣u=v ,则 𝑒e 被称作一个自环。

重边/平行边 (Multiple edge) :若 𝐸E 中存在两个完全相同的元素(边) 𝑒1,𝑒2e1​,e2​ ,则它们被称作(一组)重边。

简单图 (Simple graph) :若一个图中 没有自环和重边,它被称为简单图。非空简单无向图中一定存在度相同的结点。

如果一张图中有自环或重边,则称它为 多重图 (Multigraph) 。

图片

​ 在无向图中 (𝑢,𝑣)(u,v) 和 (𝑣,𝑢)(v,u) 算一组重边,而在有向图中, 𝑢→𝑣u→v 和 𝑣→𝑢v→u 不为重边。

​ 在题目中,如果没有特殊说明,是可以存在自环和重边的,在做题时需特殊考虑。

路径

途径 (Walk) / 链 (Chain) :一个点和边的交错序列,其中首尾是点—— 𝑣0,𝑒1,𝑣1,𝑒2,𝑣2,…,𝑒𝑘,𝑣𝑘v0​,e1​,v1​,e2​,v2​,…,ek​,vk​ ,有时简写为 𝑣0→𝑣1→𝑣2→⋯→𝑣𝑘v0​→v1​→v2​→⋯→vk​ 。其中 𝑒𝑖ei​ 的两个端点分别为 𝑣𝑖−1vi−1​ 和 𝑣𝑖vi​ 。通常来说,边的数量 𝑘k 被称作这条途径的 长度 (如果边是带权的,长度通常指路径上的边权之和,题目中也可能另有定义)。(以下设 𝑤=[𝑣0,𝑒1,𝑣1,𝑒2,𝑣2,⋯,𝑒𝑘,𝑣𝑘]w=[v0​,e1​,v1​,e2​,v2​,⋯,ek​,vk​] 。)

迹 (Trail) :对于一条途径 𝑤w ,若 𝑒1,𝑒2,⋯,𝑒𝑘e1​,e2​,⋯,ek​ 两两互不相同,则称 𝑤w 是一条迹。

路径 (Path) (又称 简单路径 (Simple path) ):对于一条迹 𝑤w ,除了 𝑣0v0​ 和 𝑣𝑘vk​ 允许相同外,其余点两两互不相同,则称 𝑤w 是一条路径。

回路 (Circuit) :对于一个迹 𝑤w ,若 𝑣0=𝑣𝑘v0​=vk​ ,则称 𝑤w 是一个回路。

环/圈 (Cycle) (又称 简单回路/简单环 (Simple circuit) ):对于一条简单路径 𝑤w ,若 𝑣0=𝑣𝑘v0​=vk​ ,则称 𝑤w 是一个环。

!!! warning
关于路径的定义在不同地方可能有所不同,如,“路径”可能指本文中的“途径”,“环”可能指本文中的“回路”。如果在题目中看到类似的词汇,且没有“简单路径”/“非简单路径”(即本文中的“途径”)等特殊说明,最好询问一下具体指什么。

连通

无向图

对于一张无向图 𝐺=(𝑉,𝐸)G=(V,E) ,对于 𝑢,𝑣∈𝑉u,v∈V ,若存在一条途径使得 𝑣0=𝑢,𝑣𝑘=𝑣v0​=u,vk​=v ,则称 𝑢u 和 𝑣v 是 连通的 (Connected) 。由定义,任意一个顶点和自身连通,任意一条边的两个端点连通。

若无向图 𝐺=(𝑉,𝐸)G=(V,E) ,满足其中任意两个顶点均连通,则称 𝐺G 是 连通图 (Connected graph) , 𝐺G 的这一性质称作 连通性 (Connectivity) 。

若 𝐻H 是 𝐺G 的一个连通子图,且不存在 𝐹F 满足 𝐻⊊𝐹⊆𝐺H⊊F⊆G 且 𝐹F 为连通图,则 𝐻H 是 𝐺G 的一个 连通块/连通分量 (Connected component) (极大连通子图)。

图片

图片

有向图

对于一张有向图 𝐺=(𝑉,𝐸)G=(V,E) ,对于 𝑢,𝑣∈𝑉u,v∈V ,若存在一条途径使得 𝑣0=𝑢,𝑣𝑘=𝑣v0​=u,vk​=v ,则称 𝑢u 可达 𝑣v 。由定义,任意一个顶点可达自身,任意一条边的起点可达终点。(无向图中的连通也可以视作双向可达。)

若一张有向图的节点两两互相可达,则称这张图是 强连通的 (Strongly connected) 。

图片

若一张有向图的边替换为无向边后可以得到一张连通图,则称原来这张有向图是 弱连通的 (Weakly connected) 。

与连通分量类似,也有 弱连通分量 (Weakly connected component) (极大弱连通子图)和 强连通分量 (Strongly Connected component) (极大强连通子图)。

图片

𝑛n 个顶点的强连通图最多 𝑛(𝑛−1)n(n−1) 条边,最少 𝑛n 条边。

图片

图的连通性也是竞赛的一个常见考点,相关算法请后面将学习,现在先理解其概念即可。

稀疏图/稠密图

若一张图的边数远小于其点数的平方,那么它是一张 稀疏图 (Sparse graph) 。

若一张图的边数接近其点数的平方,那么它是一张 稠密图 (Dense graph) 。

这两个概念并没有严格的定义,一般用于讨论 时间复杂度 为 𝑂(∣𝑉∣2)O(∣V∣2) 的算法与 𝑂(∣𝐸∣)O(∣E∣) 的算法的效率差异(在稠密图上这两种算法效率相当,而在稀疏图上 𝑂(∣𝐸∣)O(∣E∣) 的算法效率明显更高)。

特殊的图

完全图

若无向简单图 𝐺G 满足任意不同两点间均有边,则称 𝐺G 为 完全图 (Complete graph) , 𝑛n 阶完全图记作 𝐾𝑛Kn​ 。若有向图 𝐺G 满足任意不同两点间都有两条方向不同的边,则称 𝐺G 为 有向完全图 (Complete digraph) 。

图片

环图/圈图

若无向简单图 𝐺=(𝑉,𝐸)G=(V,E) 的所有边恰好构成一个圈,则称 𝐺G 为 环图/圈图 (Cycle graph) , 𝑛n ( 𝑛≥3n≥3 ) 阶圈图记作 𝐶𝑛Cn​ 。易知,一张图为圈图的充分必要条件是,它是 22 - 正则连通图。

星图/菊花图

若无向简单图 𝐺=(𝑉,𝐸)G=(V,E) 满足,存在一个点 𝑣v 为支配点,其余点之间没有边相连,则称 𝐺G 为 星图/菊花图 (Star graph) , 𝑛+1n+1 ( 𝑛≥1n≥1 ) 阶星图记作 𝑆𝑛Sn​ 。

轮图

若无向简单图 𝐺=(𝑉,𝐸)G=(V,E) 满足,存在一个点 𝑣v 为支配点,其它点之间构成一个圈,则称 𝐺G 为 轮图 (Wheel Graph) , 𝑛+1n+1 ( 𝑛≥3n≥3 ) 阶轮图记作 𝑊𝑛Wn​ 。

image-20210328095407460

若无向简单图 𝐺=(𝑉,𝐸)G=(V,E) 的所有边恰好构成一条简单路径,则称 𝐺G 为 链 (Chain/Path Graph) , 𝑛n 阶的链记作 𝑃𝑛Pn​ 。易知,一条链由一个圈图删去一条边而得。

如果一张无向连通图不含环,则称它是一棵 树 (Tree) 。相关内容详见 树基础 。

补图

对于无向简单图 𝐺=(𝑉,𝐸)G=(V,E) ,它的 补图 (Complement graph) 指的是这样的一张图:记作 𝐺ˉGˉ ,满足 𝑉(𝐺ˉ)=𝑉(𝐺)V(Gˉ)=V(G) ,且对任意节点对 (𝑢,𝑣)(u,v) , (𝑢,𝑣)∈𝐸(𝐺ˉ)(u,v)∈E(Gˉ) 当且仅当 (𝑢,𝑣)∉𝐸(𝐺)(u,v)∈/E(G) 。

图片

反图

对于有向图 𝐺=(𝑉,𝐸)G=(V,E) ,它的 反图 (Transpose Graph) 指的是点集不变,每条边反向得到的图,即:若 𝐺G 的反图为 𝐺′=(𝑉,𝐸′)G′=(V,E′) ,则 𝐸′={(𝑣,𝑢)∣(𝑢,𝑣)∈𝐸}E′={(v,u)∣(u,v)∈E} 。

平面图

如果一张图可以画在一个平面上,且没有两条边在非端点处相交,那么这张图是一张 平面图 (Planar graph) 。一张图的任何子图都不是 𝐾5K5​ 或 𝐾3,3K3,3​ 是其为一张平面图的充要条件。对于简单连通平面图 𝐺=(𝑉,𝐸)G=(V,E) 且 𝑉≥3V≥3 , ∣𝐸∣≤3∣𝑉∣−6∣E∣≤3∣V∣−6 。

image-20210328095019950

 

学习目标

  • 掌握图的四种存储方法的代码实现
  • 理解图的四种存储方法各自的时间空间复杂度
  • 能够根据题目的要求和数据范围,选择合适存图方式

图的逻辑结构

一张图是由节点构成的,一个无向图如下图所示:

图片

什么叫 「逻辑结构」?就是说为了方便研究,我们把图 抽象 成这个样子。

根据这个逻辑结构,我们可以认为每个节点的实现如下:

// 图节点的逻辑结构
struct node {
    int data;                 // 存当前结点信息
    vector<int> neighbors;  // 存邻接的所有结点
}

看到这个实现,你有没有很熟悉?它和我们之前说的多叉树节点几乎完全一样:

// 树节点的逻辑结构
struct node {
    int data;                 // 存当前结点信息
    vector<int> son;        // 存所有的子结点
}

Copy

不过呢,上面的这种实现是「逻辑上的」,实际上我们很少用这个node类实现图,而是用接下来介绍的几种方法去存储。其中包含我们前面经常提到的 邻接表和邻接矩阵

图的存储方法

接下来描述图的具体四种存储方式,这四种方式是我们今后和图这种数据结构打交道的接口,请一定要掌握。

首先约定,用 𝑛n 代指图的点数,用 𝑚m 代指图的边数,用 𝑑+(𝑢)d+(u) 代指点 𝑢u 的出度,即以 𝑢u 为出发点的边数。

直接存边

方法

使用一个数组来存边,数组中的每个元素都包含一条边的起点与终点(带边权的图还包含边权)。(或者使用多个数组分别存起点,终点和边权。)

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

struct Edge {
    int u, v, w;   // 一条边的 起点、终点、权值
};

int n, m;
vector<Edge> e;
vector<bool> vis;

// 函数功能:判断 u,v 之间有没有边
bool find_edge(int u, int v) {
    for (int i = 1; i <= m; ++i) {
        if (e[i].u == u && e[i].v == v) {
            return true;
        }
    }
    return false;
}

// 遍历图
void dfs(int u) {
    if (vis[u]) return;
    vis[u] = true;
    for (int i = 1; i <= m; ++i) {
        if (e[i].u == u) {
            dfs(e[i].v);
        }
    }
}

int main() {
  cin >> n >> m;
  // 初始化 vector 数组,也可以将 vis 定义成: “bool vis[N];” 以省去初始化。下同
  vis.resize(n + 1, false);
  e.resize(m + 1);

  for (int i = 1; i <= m; ++i) cin >> e[i].u >> e[i].v >> e[i].w;

  return 0;
}

复杂度

查询是否存在某条边: 𝑂(𝑚)O(m) 。

遍历一个点的所有出边: 𝑂(𝑚)O(m) 。

遍历整张图: 𝑂(𝑛𝑚)O(nm) 。

空间复杂度: 𝑂(𝑚)O(m) 。

应用

由于直接存边的遍历效率低下,一般不用于遍历图。

在 Kruskal 算法中,由于需要将边按边权排序,需要直接存边。

在有的题目中,需要多次建图(如建一遍原图,建一遍反图),此时既可以使用多个其它数据结构来同时存储多张图,也可以将边直接存下来,需要重新建图时利用直接存下的边来建图。

邻接矩阵

方法

使用一个二维数组 g 来存边,其中 g[u][v] 为 1 表示存在 𝑢u 到 𝑣v 的边,为 0 表示不存在。

如果是带边权的图,可以在 g[u][v] 中存储 𝑢u 到 𝑣v 的边的边权,0 表示没有连接,其他值表示权重。

如果是无向图,则将一条无向边拆成两条方向相反的边即可。(所谓的「无向」,也就等同于「双向」)

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

const int N = 1e5+5;
int n, m;
bool vis[N];
bool g[N][N];

bool find_edge(int u, int v) { return g[u][v]; }

void dfs(int u) {
    if (vis[u]) return;
    vis[u] = true;
    for (int v = 1; v <= n; ++v) {
        if (g[u][v]) {
            dfs(v);
        }
    }
}

int main() {
    cin >> n >> m;

    fill_n(vis, N, false);  // 将 vis 数组清 false,类似 memset
    fill_n(g, N*N, false);
    
    for (int i = 1; i <= m; ++i) {
        int u, v;
        cin >> u >> v;
        g[u][v] = true;   // u->v 有条单向边
        // 如果是双向边
        // g[u][v] = g[v][u] = true;
    }
    return 0;
}

复杂度

查询是否存在某条边: 𝑂(1)O(1) 。

遍历一个点的所有出边: 𝑂(𝑛)O(n) 。

遍历整张图: 𝑂(𝑛2)O(n2) 。

空间复杂度: 𝑂(𝑛2)O(n2) 。

应用

邻接矩阵只适用于没有重边(或重边可以忽略)的情况。

其最显著的优点是可以 𝑂(1)O(1) 查询一条边是否存在。

由于邻接矩阵在稀疏图上效率很低(尤其是在点数较多的图上,空间无法承受),所以一般只会 在稠密图上使用邻接矩阵。并且,在稠密图上使用邻接矩阵的运行效率远高于邻接表,这是因为 CPU 中顺序访问的速度是远高于随机访问的(缓存命中)。

图片

邻接表

方法

使用一个支持动态增加元素的数据结构构成的数组,如 vector<int> g[N] 来存边,其中 g[u] 存储的是点 𝑢u 的所有出边的相关信息(终点、边权等)。

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

const int N = 1e5+5;
int n, m;
bool vis[N];
vector<int> g[N];

bool find_edge(int u, int v) {
    for (int i = 0; i < g[u].size(); ++i) {
        if (g[u][i] == v) {
            return true;
        }
    }
    return false;
}

void dfs(int u) {
    if (vis[u]) return;
    vis[u] = true;
    for (int i = 0; i < g[u].size(); ++i) dfs(g[u][i]);
}

int main() {
    cin >> n >> m;
    
    vis.resize(n + 1, false);
    g.resize(n + 1);
    
    for (int i = 1; i <= m; ++i) {
        int u, v;
        cin >> u >> v;
        g[u].push_back(v);
        // 如果是无向图,还须:
        // g[v].push_back(u);
    }
    
    return 0;
}

复杂度

查询是否存在 𝑢u 到 𝑣v 的边: 𝑂(𝑑+(𝑢))O(d+(u)) (如果事先进行了排序就可以使用 二分查找 做到 𝑂(log⁡(𝑑+(𝑢)))O(log(d+(u))) )。

遍历点 𝑢u 的所有出边: 𝑂(𝑑+(𝑢))O(d+(u)) 。

遍历整张图: 𝑂(𝑛+𝑚)O(n+m) 。

空间复杂度: 𝑂(𝑚)O(m) 。

应用

存各种图都很适合,除非有特殊需求(如需要快速查询一条边是否存在,且点数较少,可以使用邻接矩阵)。

尤其适用于需要对一个点的所有出边进行排序的场合。

链式前向星

方法

本质上是用链表实现的邻接表,示例代码如下:

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

const int N = 1e5+5;
int n, m;

bool vis[N];
int head[N], nxt[N], to[N], cnt;     // 链式前向星三要素

void add(int u, int v) {     // 添加一条 u->v 的边
    nxt[++cnt] = head[u];    // cnt 这条边的后继(同是 u 的出边的上一条边)
    to[cnt] = v;             // 当前边的终点是 v
    head[u] = cnt;           // 起点 u 的第一条边放到了下标 cnt 处(其实是最后一条)
}

bool find_edge(int u, int v) {
  for (int i = head[u]; ~i; i = nxt[i]) {  // ~i 表示 i != -1
    if (to[i] == v) {
        return true;
    }
  }
  return false;
}

void dfs(int u) {
    if (vis[u]) return;
    vis[u] = true;
    cout << u << ' ';
    for (int i = head[u]; ~i; i = nxt[i])
        dfs(to[i]);
}

int main() {
    cin >> n >> m;
    
    fill_n(vis, N, false);
    fill_n(head, N, -1);
    
    for (int i = 1; i <= m; ++i) {
        int u, v;
        cin >> u >> v;
        add(u, v);
    }
    dfs(1);
    return 0;
}

如果图是赋权图,即边带有权重时,此时数组定义过多,也可以写成结构体去保存,参考代码如下:

#include<bits/stdc++.h>
using namespace std;

const int N = 1e5;    //点数最大值
int n, m;             //n个点,m条边
int head[N], cnt = -1;     //head[i],表示以i为起点的第一条边在边集数组的位置(编号)

struct Edge
{
    int to, w, next;   // 终点,边权,同起点的上一条边的编号
}edge[N];//边集

void add_edge(int u, int v, int w)// 加边,u 起点,v 终点,w 边权
{
    edge[++cnt].next = head[u];    // 以u为起点上一条边的编号,也就是与这个边起点相同的上一条边的编号
    edge[cnt].to = v;          // 终点
    edge[cnt].w = w;             // 权值
    head[u] = cnt;               // 更新以u为起点上一条边的编号
}
int main()
{
    cin >> n >> m;
    int u, v, w;
    fill_n(head, N, -1);
    
    for (int i = 1; i <= m; i++) // 输入m条边
    {
        cin >> u >> v >> w;
        add_edge(u, v, w);       // 加边
        // 加双向边
        // add_edge(u, v, w);
        // add_edge(v, u, w);
    }
    // 输出每个结点的出边
    for (int i = 1; i <= n; i++)
    {
        cout << i << endl;
        for (int j = head[i]; ~j; j = edge[j].next)  // 遍历以 i为起点的边
        {
            cout << i << " " << edge[j].to << " " << edge[j].w << endl;
        }
        cout << endl;
    }
    return 0;
}
/*
5 7
1 2 1
2 3 2
3 4 3
1 3 4
4 1 5
1 5 6
4 5 7
*/

复杂度

查询是否存在 𝑢u 到 𝑣v 的边: 𝑂(𝑑+(𝑢))O(d+(u)) 。

遍历点 𝑢u 的所有出边: 𝑂(𝑑+(𝑢))O(d+(u)) 。

遍历整张图: 𝑂(𝑛+𝑚)O(n+m) 。

空间复杂度: 𝑂(𝑚)O(m) 。

应用

注意:利用链式前向星遍历的边的顺序和输入顺序是相反的!

存各种图都很适合,但是缺点也很明显, 不能快速查询一条边是否存在,也不能方便地对一个点的出边进行排序

优点是边是带编号的,有时会非常有用,而且如果边是从数组的偶数位开始存储( 按上面示例代码写法是从 0 开始存储的,cnt 的初始值为 -1),存双向边时 i ^ 1 即是 i 的反边(常用于网络流 )。

总结

图的存储方法比较多,每种方法各有优缺点,对比如下:

直接存边邻接矩阵邻接表链式前向星
使用场合需要将边按边权排序时;需要重新建图时利用直接存下的边来建图只适用于没有重边(或重边可以忽略)的情况;可以 𝑂(1)O(1) 查询边;在稠密图上效率很高消耗空间较小,各种场合都适用,尤其适用于需要对点的出边排序的场合消耗空间小,各种场合都适用
缺点遍历效率低下,一般不用于遍历图只适用于没有重边(或重边可以忽略)的情况。需熟练掌握 vector 操作?不能迅速查询边和对一个点的出边排序

总的来说,就是:

  1. 需要对所有边进行排序时,直接存边;
  2. 图很稠密,用邻接矩阵;
  3. 其他一般情况,用邻接表或链式前向星都可以。

请在理解各种方法的优缺点并掌握其代码实现以后,面对具体问题应思考选择合适的方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1671747.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于Springboot的大学生平时成绩量化管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的大学生平时成绩量化管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三…

【ARM Cortex-M 系列 2.2 -- Cortex-M7 单步调试原理及实现详细介绍】

请阅读【嵌入式开发学习必备专栏】 文章目录 单步调试概述单步执行原理Debug stepping control using the DHCSR 紧接上篇文章 【ARM Cortex-M 系列 2.1 – Cortex-M7 Debug system registers】 单步调试概述 在ARMv7-M架构中&#xff0c;通过使用单步调试&#xff08;Haltin…

采用java+B/S开发的全套医院绩效考核系统源码springboot+mybaits 医院绩效考核系统优势

采用java开发的全套医院绩效考核系统源码springbootmybaits 医院绩效考核系统优势 医院绩效管理系统解决方案紧扣新医改形势下医院绩效管理的要求&#xff0c;以“工作量为基础的考核方案”为核心思想&#xff0c;结合患者满意度、服务质量、技术难度、工作效率、医德医风等管…

电脑快速搜索文件及文件夹软件——Everything

一、前言 Everything是一款由voidtools开发的文件搜索工具&#xff0c;主要运行于Windows操作系统上。它的主要功能是快速、高效地搜索电脑上的文件和文件夹名称。Everything通过利用NTFS文件系统的MFT&#xff08;主文件表&#xff09;来索引文件&#xff0c;从而实现几乎实时…

揭秘 HTTP 代理:增强在线活动的安全性和匿名性

HTTP 代理在保护您的在线隐私、增强安全性以及允许访问受限内容方面发挥着关键作用。了解 HTTP 代理的工作原理以及如何有效地利用它们可以让您掌控自己的在线状态和浏览体验。让我们深入研究 HTTP 代理的世界&#xff0c;探索它们的优势、应用程序以及最大化其效用的最佳实践。…

4.uniapp+vue3项目使用vuex

文章目录 1. uniappvue3项目使用vuex1.1. main.js引入store1.2. 创建store/index.js1.3. 项目中引用1.4. 开始解决实际问题1.5. vuex和storage的区别 1. uniappvue3项目使用vuex 这篇文章&#xff0c;既是使用的教程&#xff0c;也是用来解决一个实际问题&#xff1a;uView自定…

软件工程期末复习(5)

可行性研究 可行性研究的任务 可行性研究的目的&#xff1a; 用最小的代价&#xff0c;在尽可能短的时间内确定问题是否能够解决。 可行性研究的实质&#xff1a; 就是一次压缩、简化了的系统分析和设计的过程。 可行性研究的路线&#xff1a; 分析和澄清问题定义&#…

在word中创建宏来多级列表的编号不显示的bug

出现问题的示意图如下&#xff0c;可以看出标题前面1.1消失了 第一步&#xff1a;选择开发工具 第二步&#xff1a; 第三步&#xff1a;选择当前文件&#xff08;创建宏后&#xff0c;方便查找&#xff09; 第四步&#xff1a; 第五步&#xff1a;打卡VB 第七步&#xf…

汇昌联信:拼多多入驻条件是哪些?

在电商领域&#xff0c;拼多多以其独特的团购模式迅速崛起&#xff0c;吸引了众多商家的目光。想要在拼多多上开店&#xff0c;了解其入驻条件是必不可少的第一步。下面将详细解读拼多多的入驻条件&#xff0c;帮助有意加入的商家们做好准备。 一、企业资质要求 想要成功入驻拼…

人工智能中的概率魔法:解锁不确定性的智慧之钥

在人工智能&#xff08;AI&#xff09;的广阔天地中&#xff0c;概率论以其独特的魅力&#xff0c;成为了连接现实世界与智能决策的桥梁。从语音识别到图像识别&#xff0c;从自然语言处理到机器翻译&#xff0c;从智能推荐到自动驾驶&#xff0c;概率论知识在这些领域中发挥着…

SpringCloud 集成 RocketMQ 及配置解析

文章目录 前言一、SpringCloud 集成 RocketMQ1. pom 依赖2. yml 配置3. 操作实体4. 生产消息4.1. 自动发送消息4.2. 手动发送消息 5. 消费消息 二、配置解析1. spring.cloud.stream.function.definition 前言 定义 Spring Cloud Stream 是一个用来为微服务应用构建消息驱动能力…

文件流-二进制文件(中北大学-程序设计基础(2))

目录 题目 源码 结果示例 题目 建立两个二进制磁盘文件f1.dat,f2.dat&#xff0c;编程实现以下工作&#xff1a; &#xff08;1&#xff09;将20个整数&#xff08;可在程序中初始化&#xff09;&#xff0c;分别存放到两个磁盘文件中&#xff0c;前10个放到f1.dat中&…

C++类和对象下——实现日期类

前言 在学习了类和对象的六大成员函数后&#xff0c;为了巩固我们学习的知识可以手写一个日期类来帮助我们理解类和对象&#xff0c;加深对于其的了解。 默认函数 构造函数 既然是写类和对象&#xff0c;我们首先就要定义一个类&#xff0c;然后根据实际需要来加入类的数据与函…

windows和Linux卸载移动磁盘

文章目录 Linux卸载磁盘target is busy.window卸载磁盘打开事件查看器 Linux卸载磁盘target is busy. #查看有哪些进程访问挂载点 lsof /media/lei/repository/#杀死进程 pkill node window卸载磁盘 #提示 #该设备正在使用中. 请关闭可能使用该设备的所有程序或窗口,然后重试…

【React】redux开发者工具redux-devtools-extension的安装和使用

前言 redux-devtools-extension: 是一个用于Redux的开发者工具扩展。适合用于需要调试和监控Redux应用的状态管理。特点是可以提供实时的状态查看、行动日志和错误检测等 安装 chrome安装redux-devtools-extension 项目中安装并引入redux-devtools-extension yarn add re…

强化学习——马尔可夫奖励过程的理解

目录 一、马尔可夫奖励过程1.回报2.价值函数 参考文献 一、马尔可夫奖励过程 在马尔可夫过程的基础上加入奖励函数 r r r 和折扣因子 γ \gamma γ&#xff0c;就可以得到马尔可夫奖励过程&#xff08;Markov reward process&#xff09;。一个马尔可夫奖励过程由 < S , …

C++语言的字符数组

存放字符数据的数组是字符数组&#xff0c;字符数组中的一个元素存放一个字符。字符数组具有数组的共同属性。 1. 声明一个字符数组 char c[5]; 2. 字符数组赋值方式 &#xff08;1&#xff09;为数组元素逐一赋值 c[0]H c[1]E c[2]L c[3]L c[4]O &#xff08;2&…

【JVM】从可达性分析,到JVM垃圾回收算法,再到垃圾收集器

《深入理解Java虚拟机》[1]中&#xff0c;有下面这么一段话&#xff1a; 在JVM的各个区域中&#xff0c;如虚拟机栈中&#xff0c;栈帧随着方法的进入和退出而有条不紊的执行者出栈和入栈操作。每一个栈帧中分配多少内存基本上是在类结构确定下来时就已知的&#xff08;尽管在…

【qt】数值的输入与输出

数值的输入与输出 一.与c中的输入与输出的区别二.QString转数值三.数值转QString1.number()2.asprintf() 四.小项目1.总价和进制2.QSpinBox代替3.QSlider滑动块4.QScrollBar滚动条5.QDial表盘6.QLcdnumber lcd显示 五.总结一下下 一.与c中的输入与输出的区别 在c中我们一般通过…

java项目之相亲网站的设计与实现源码(springboot+mysql+vue)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的相亲网站的设计与实现。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 相亲网站的设计与实…