数据结构与算法:图

文章目录

      • 1) 概念
        • 有向 vs 无向
        • 路径
        • 图的连通性
      • 2) 图的表示
      • 3) Java 表示
      • 4) DFS
      • 5) BFS
      • 6) 拓扑排序
      • 7) 最短路径
        • Dijkstra
        • Bellman-Ford
        • Floyd-Warshall
      • 8) 最小生成树
        • Prim
        • Kruskal

1) 概念

图是由顶点(vertex)和边(edge)组成的数据结构,例如

A
B
C
D

该图有四个顶点:A、B、C、D 以及四条有向边,有向图中,边是单向的

有向 vs 无向

如果是无向图,那么边是双向的,下面是一个无向图的例子

A
B
C
D

是指与该顶点相邻的边的数量

A
B
C
D
E
F

例如上图中

  • A、B、C、E、F 这几个顶点度数为 2
  • D 顶点度数为 4

有向图中,细分为入度出度,参见下图

A
B
C
D
E
F
  • A (2 out / 0 in)
  • B、C、E (1 out / 1 in)
  • D (2 out / 2 in)
  • F (0 out / 2 in)

边可以有权重,代表从源顶点到目标顶点的距离、费用、时间或其他度量。

北京
武汉
广州
上海
800km
1900km
1200km
1050km
700km
路径

路径被定义为从一个顶点到另一个顶点的一系列连续边,例如上图中【北京】到【上海】有多条路径

  • 北京 - 上海
  • 北京 - 武汉 - 上海

路径长度

  • 不考虑权重,长度就是边的数量
  • 考虑权重,一般就是权重累加

在有向图中,从一个顶点开始,可以通过若干条有向边返回到该顶点,那么就形成了一个环

A
B
C
D
E
图的连通性

如果两个顶点之间存在路径,则这两个顶点是连通的,所有顶点都连通,则该图被称之为连通图,若子图连通,则称为连通分量

A
B
C
D
E
F
G
H
I
J

2) 图的表示

比如说,下面的图

A
B
C
D

邻接矩阵可以表示为:

  A B C D
A 0 1 1 0
B 1 0 0 1 
C 1 0 0 1
D 0 1 1 0

邻接表可以表示为:

A -> B -> C
B -> A -> D
C -> A -> D
D -> B -> C

有向图的例子

A
B
C
D
  A B C D
A 0 1 1 0
B 0 0 0 1
C 0 0 0 1
D 0 0 0 0
A - B - C
B - D
C - D
D - empty

3) Java 表示

顶点

public class Vertex {String name;List<Edge> edges;// 拓扑排序相关int inDegree;int status; // 状态 0-未访问 1-访问中 2-访问过,用在拓扑排序// dfs, bfs 相关boolean visited;// 求解最短距离相关private static final int INF = Integer.MAX_VALUE;int dist = INF;Vertex prev = null;@Overridepublic String toString() {return this.name;}
}

public class Edge {Vertex linked;int weight;public Edge(Vertex linked) {this(linked, 1);}public Edge(Vertex linked, int weight) {this.linked = linked;this.weight = weight;}
}

4) DFS

public class Dfs {public static void main(String[] args) {Vertex v1 = new Vertex("v1");Vertex v2 = new Vertex("v2");Vertex v3 = new Vertex("v3");Vertex v4 = new Vertex("v4");Vertex v5 = new Vertex("v5");Vertex v6 = new Vertex("v6");v1.edges = List.of(new Edge(v3), new Edge(v2), new Edge(v6));v2.edges = List.of(new Edge(v4));v3.edges = List.of(new Edge(v4), new Edge(v6));v4.edges = List.of(new Edge(v5));v5.edges = List.of();v6.edges = List.of(new Edge(v5));dfs1(v1);}private static void dfs2(Vertex v) {LinkedList<Vertex> stack = new LinkedList<>();stack.push(v);while (!stack.isEmpty()) {Vertex pop = stack.pop();pop.visited = true;System.out.println(pop.name);for (Edge edge : pop.edges) {if (!edge.linked.visited) {stack.push(edge.linked);}}}}private static void dfs1(Vertex v) {v.visited = true;System.out.println(v.name);for (Edge edge : v.edges) {if (!edge.linked.visited) {dfs(edge.linked);}}}
}

5) BFS

public class Bfs {public static void main(String[] args) {Vertex v1 = new Vertex("v1");Vertex v2 = new Vertex("v2");Vertex v3 = new Vertex("v3");Vertex v4 = new Vertex("v4");Vertex v5 = new Vertex("v5");Vertex v6 = new Vertex("v6");v1.edges = List.of(new Edge(v3), new Edge(v2), new Edge(v6));v2.edges = List.of(new Edge(v4));v3.edges = List.of(new Edge(v4), new Edge(v6));v4.edges = List.of(new Edge(v5));v5.edges = List.of();v6.edges = List.of(new Edge(v5));bfs(v1);}private static void bfs(Vertex v) {LinkedList<Vertex> queue = new LinkedList<>();v.visited = true;queue.offer(v);while (!queue.isEmpty()) {Vertex poll = queue.poll();System.out.println(poll.name);for (Edge edge : poll.edges) {if (!edge.linked.visited) {edge.linked.visited = true;queue.offer(edge.linked);}}}}
}

6) 拓扑排序

网页基础
Java Web
Java 基础
数据库
Spring框架
微服务框架
实战项目
public class TopologicalSort {public static void main(String[] args) {Vertex v1 = new Vertex("网页基础");Vertex v2 = new Vertex("Java基础");Vertex v3 = new Vertex("JavaWeb");Vertex v4 = new Vertex("Spring框架");Vertex v5 = new Vertex("微服务框架");Vertex v6 = new Vertex("数据库");Vertex v7 = new Vertex("实战项目");v1.edges = java.util.List.of(new Edge(v3)); // +1v2.edges = java.util.List.of(new Edge(v3)); // +1v3.edges = java.util.List.of(new Edge(v4));v6.edges = java.util.List.of(new Edge(v4));v4.edges = java.util.List.of(new Edge(v5));v5.edges = java.util.List.of(new Edge(v7));v7.edges = java.util.List.of();List<Vertex> graph = java.util.List.of(v1,v2,v3,v4,v5,v6,v7);for (Vertex vertex : graph) {for (Edge edge : vertex.edges) {edge.linked.inDegree += 1;}}List<Vertex> result = new ArrayList<>();Stack<Vertex> stack = new Stack<>();for (Vertex vertex : graph) {if(vertex.inDegree == 0 ){stack.push(vertex);}}while(!stack.isEmpty()){Vertex pop = stack.pop();result.add(pop);for (Edge edge : pop.edges) {edge.linked.inDegree--;if(edge.linked.inDegree == 0 && !edge.linked.visited){stack.add(edge.linked);edge.linked.visited = true;}}}if(result.size() != graph.size()){System.out.println("发现环");}for (Vertex vertex : result) {System.out.println(vertex);}}

7) 最短路径

Dijkstra
7
9
14
9
2
15
11
6
1
2
3
4
5
6

算法描述:

  1. 将所有顶点标记为未访问。创建一个未访问顶点的集合。
  2. 为每个顶点分配一个临时距离值
    • 对于我们的初始顶点,将其设置为零
    • 对于所有其他顶点,将其设置为无穷大。
  3. 每次选择最小临时距离的未访问顶点,作为新的当前顶点
  4. 对于当前顶点,遍历其所有未访问的邻居,并更新它们的临时距离为更小
    • 例如,1->6 的距离是 14,而1->3->6 的距离是11。这时将距离更新为 11
    • 否则,将保留上次距离值
  5. 当前顶点的邻居处理完成后,把它从未访问集合中删除
public class Dijkstra {public static void main(String[] args) {Vertex v1 = new Vertex("v1");Vertex v2 = new Vertex("v2");Vertex v3 = new Vertex("v3");Vertex v4 = new Vertex("v4");Vertex v5 = new Vertex("v5");Vertex v6 = new Vertex("v6");v1.edges = List.of(new Edge(v3, 9), new Edge(v2, 7), new Edge(v6, 14));v2.edges = List.of(new Edge(v4, 15));v3.edges = List.of(new Edge(v4, 11), new Edge(v6, 2));v4.edges = List.of(new Edge(v5, 6));v5.edges = List.of();v6.edges = List.of(new Edge(v5, 9));List<Vertex> graph = List.of(v1, v2, v3, v4, v5, v6);dijkstra(graph, v1);}private static void dijkstra(List<Vertex> graph, Vertex source) {ArrayList<Vertex> list = new ArrayList<>(graph);source.dist = 0;while (!list.isEmpty()) {// 3. 选取当前顶点Vertex curr = chooseMinDistVertex(list);// 4. 更新当前顶点邻居距离updateNeighboursDist(curr, list);// 5. 移除当前顶点list.remove(curr);}for (Vertex v : graph) {System.out.println(v.name + " " + v.dist);}}private static void updateNeighboursDist(Vertex curr, ArrayList<Vertex> list) {for (Edge edge : curr.edges) {Vertex n = edge.linked;if (list.contains(n)) {int dist = curr.dist + edge.weight;if (dist < n.dist) {n.dist = dist;}}}}private static Vertex chooseMinDistVertex(ArrayList<Vertex> list) {Vertex min = list.get(0);for (int i = 1; i < list.size(); i++) {if (list.get(i).dist < min.dist) {min = list.get(i);}}return min;}}

改进 - 优先级队列

  1. 创建一个优先级队列,放入所有顶点(队列大小会达到边的数量)
  2. 为每个顶点分配一个临时距离值
    • 对于我们的初始顶点,将其设置为零
    • 对于所有其他顶点,将其设置为无穷大。
  3. 每次选择最小临时距离的未访问顶点,作为新的当前顶点
  4. 对于当前顶点,遍历其所有未访问的邻居,并更新它们的临时距离为更小,若距离更新需加入队列
    • 例如,1->6 的距离是 14,而1->3->6 的距离是11。这时将距离更新为 11
    • 否则,将保留上次距离值
  5. 当前顶点的邻居处理完成后,把它从队列中删除
public class DijkstraPriorityQueue {public static void main(String[] args) {Vertex v1 = new Vertex("v1");Vertex v2 = new Vertex("v2");Vertex v3 = new Vertex("v3");Vertex v4 = new Vertex("v4");Vertex v5 = new Vertex("v5");Vertex v6 = new Vertex("v6");v1.edges = List.of(new Edge(v3, 9), new Edge(v2, 7), new Edge(v6, 14));v2.edges = List.of(new Edge(v4, 15));v3.edges = List.of(new Edge(v4, 11), new Edge(v6, 2));v4.edges = List.of(new Edge(v5, 6));v5.edges = List.of();v6.edges = List.of(new Edge(v5, 9));List<Vertex> graph = List.of(v1, v2, v3, v4, v5, v6);dijkstra(graph, v1);}private static void dijkstra(List<Vertex> graph, Vertex source) {PriorityQueue<Vertex> queue = new PriorityQueue<>(Comparator.comparingInt(v -> v.dist));source.dist = 0;for (Vertex v : graph) {queue.offer(v);}while (!queue.isEmpty()) {System.out.println(queue);// 3. 选取当前顶点Vertex curr = queue.poll();// 4. 更新当前顶点邻居距离if(!curr.visited) {updateNeighboursDist(curr, queue);curr.visited = true;}// 5. 移除当前顶点}for (Vertex v : graph) {System.out.println(v.name + " " + v.dist + " " + (v.prev != null ? v.prev.name : "null"));}}private static void updateNeighboursDist(Vertex curr, PriorityQueue<Vertex> queue) {for (Edge edge : curr.edges) {Vertex n = edge.linked;if (!n.visited) {int dist = curr.dist + edge.weight;if (dist < n.dist) {n.dist = dist;n.prev = curr;queue.remove(n); // 先删除再添加才能改变优先级queue.offer(n);}}}}}

问题

2
1
-2
1
v1
v2
v3
v4

按照 Dijkstra 算法,得出

  • v1 -> v2 最短距离2
  • v1 -> v3 最短距离1
  • v1 -> v4 最短距离2

事实应当是

  • v1 -> v2 最短距离2
  • v1 -> v3 最短距离0
  • v1 -> v4 最短距离1
Bellman-Ford
public class BellmanFord {public static void main(String[] args) {// 正常情况/*Vertex v1 = new Vertex("v1");Vertex v2 = new Vertex("v2");Vertex v3 = new Vertex("v3");Vertex v4 = new Vertex("v4");Vertex v5 = new Vertex("v5");Vertex v6 = new Vertex("v6");v1.edges = List.of(new Edge(v3, 9), new Edge(v2, 7), new Edge(v6, 14));v2.edges = List.of(new Edge(v4, 15));v3.edges = List.of(new Edge(v4, 11), new Edge(v6, 2));v4.edges = List.of(new Edge(v5, 6));v5.edges = List.of();v6.edges = List.of(new Edge(v5, 9));List<Vertex> graph = List.of(v4, v5, v6, v1, v2, v3);*/// 负边情况/*Vertex v1 = new Vertex("v1");Vertex v2 = new Vertex("v2");Vertex v3 = new Vertex("v3");Vertex v4 = new Vertex("v4");v1.edges = List.of(new Edge(v2, 2), new Edge(v3, 1));v2.edges = List.of(new Edge(v3, -2));v3.edges = List.of(new Edge(v4, 1));v4.edges = List.of();List<Vertex> graph = List.of(v1, v2, v3, v4);*/// 负环情况Vertex v1 = new Vertex("v1");Vertex v2 = new Vertex("v2");Vertex v3 = new Vertex("v3");Vertex v4 = new Vertex("v4");v1.edges = List.of(new Edge(v2, 2));v2.edges = List.of(new Edge(v3, -4));v3.edges = List.of(new Edge(v4, 1), new Edge(v1, 1));v4.edges = List.of();List<Vertex> graph = List.of(v1, v2, v3, v4);bellmanFord(graph, v1);}private static void bellmanFord(List<Vertex> graph, Vertex source) {source.dist = 0;int size = graph.size();// 1. 进行 顶点个数 - 1 轮处理for (int i = 0; i < size - 1; i++) {// 2. 遍历所有的边for (Vertex s : graph) {for (Edge edge : s.edges) {// 3. 处理每一条边Vertex e = edge.linked;if (s.dist != Integer.MAX_VALUE && s.dist + edge.weight < e.dist) {e.dist = s.dist + edge.weight;e.prev = s;}}}}for (Vertex v : graph) {System.out.println(v + " " + (v.prev != null ? v.prev.name : "null"));}}
}

负环

2
-4
1
1
v1
v2
v3
v4

如果在【顶点-1】轮处理完成后,还能继续找到更短距离,表示发现了负环

Floyd-Warshall
-2
4
3
2
-1
v1
v3
v2
v4
public class FloydWarshall {public static void main(String[] args) {Vertex v1 = new Vertex("v1");Vertex v2 = new Vertex("v2");Vertex v3 = new Vertex("v3");Vertex v4 = new Vertex("v4");v1.edges = List.of(new Edge(v3, -2));v2.edges = List.of(new Edge(v1, 4), new Edge(v3, 3));v3.edges = List.of(new Edge(v4, 2));v4.edges = List.of(new Edge(v2, -1));List<Vertex> graph = List.of(v1, v2, v3, v4);/*直接连通v1  v2  v3  v4v1  0   ∞   -2  ∞v2  4   0   3   ∞v3  ∞   ∞   0   2v4  ∞   -1  ∞   0k=0 借助v1到达其它顶点v1  v2  v3  v4v1  0   ∞   -2  ∞v2  4   0   2   ∞v3  ∞   ∞   0   2v4  ∞   -1  ∞   0k=1 借助v2到达其它顶点v1  v2  v3  v4v1  0   ∞   -2  ∞v2  4   0   2   ∞v3  ∞   ∞   0   2v4  3   -1  1   0k=2 借助v3到达其它顶点v1  v2  v3  v4v1  0   ∞   -2  0v2  4   0   2   4v3  ∞   ∞   0   2v4  3   -1  1   0k=3 借助v4到达其它顶点v1  v2  v3  v4v1  0   -1   -2  0v2  4   0   2   4v3  5   1   0   2v4  3   -1  1   0*/floydWarshall(graph);}private static void floydWarshall(List<Vertex> graph){int size = graph.size();int[][] dist = new int[size][size];for (int i = 0; i < size; i++) {  // 初始化Vertex vertex = graph.get(i);Map<Vertex, Integer> collect = vertex.edges.stream().collect(Collectors.toMap(v -> v.linked, v -> v.weight));for (int i1 = 0; i1 < size; i1++) {if(i == i1){dist[i][i1] = 0;continue;}dist[i][i1] = collect.getOrDefault(graph.get(i1),Integer.MAX_VALUE);}}for (int k = 0; k < size; k++) {for (int j = 0; j < size; j++) {int dist1;if((dist1 = dist[j][k]) < Integer.MAX_VALUE){for (int i = 0; i < size; i++) {int dist2;if((dist2 = dist[k][i]) != Integer.MAX_VALUE)dist[j][i] = Integer.min(dist1 + dist2,dist[j][i]);}}}}for (int[] ints : dist) {for (int anInt : ints) {System.out.print(anInt + " ");}System.out.println();}}
}

负环

如果在 3 层循环结束后,在 dist 数组的对角线处(i==j 处)发现了负数,表示出现了负环

8) 最小生成树

图的最小生成树是一个子图,它是连通的,包含图中所有的顶点,并且所有边的权重之和最小。在最小生成树中,没有任何一条边可以被其他边替换而使得总权重变小。也就是说,最小生成树是图的所有生成树中,边的权值总和最小的生成树。

请添加图片描述

解决最小生成树问题的常用算法有Prim算法和Kruskal算法。Prim算法从一个顶点开始,每次都添加一条与当前子图连接的权重最小的边,直到所有顶点都被包含在子图中。Kruskal算法则是从所有的边开始,每次都添加一条当前所有边中权重最小的边,但需要保证添加的边不会形成环,直到所有顶点都被连接。

Prim
public class Prim {public static void main(String[] args) {Vertex v1 = new Vertex("v1");Vertex v2 = new Vertex("v2");Vertex v3 = new Vertex("v3");Vertex v4 = new Vertex("v4");Vertex v5 = new Vertex("v5");Vertex v6 = new Vertex("v6");Vertex v7 = new Vertex("v7");v1.edges = List.of(new Edge(v2, 2), new Edge(v3, 4), new Edge(v4, 1));v2.edges = List.of(new Edge(v1, 2), new Edge(v4, 3), new Edge(v5, 10));v3.edges = List.of(new Edge(v1, 4), new Edge(v4, 2), new Edge(v6, 5));v4.edges = List.of(new Edge(v1, 1), new Edge(v2, 3), new Edge(v3, 2),new Edge(v5, 7), new Edge(v6, 8), new Edge(v7, 4));v5.edges = List.of(new Edge(v2, 10), new Edge(v4, 7), new Edge(v7, 6));v6.edges = List.of(new Edge(v3, 5), new Edge(v4, 8), new Edge(v7, 1));v7.edges = List.of(new Edge(v4, 4), new Edge(v5, 6), new Edge(v6, 1));List<Vertex> graph = List.of(v1, v2, v3, v4, v5, v6, v7);prim(graph, v1);}static void prim(List<Vertex> graph, Vertex source) {ArrayList<Vertex> list = new ArrayList<>(graph);source.dist = 0;while (!list.isEmpty()) {Vertex min = chooseMinDistVertex(list);updateNeighboursDist(min);list.remove(min);min.visited = true;System.out.println("---------------");for (Vertex v : graph) {System.out.println(v);}}}private static void updateNeighboursDist(Vertex curr) {for (Edge edge : curr.edges) {Vertex n = edge.linked;if (!n.visited) {int dist = edge.weight;if (dist < n.dist) {n.dist = dist;n.prev = curr;}}}}private static Vertex chooseMinDistVertex(ArrayList<Vertex> list) {Vertex min = list.get(0);for (int i = 1; i < list.size(); i++) {if (list.get(i).dist < min.dist) {min = list.get(i);}}return min;}
}
Kruskal
  private static void kruskal(List<Vertex> graph,Vertex v1){List<Edge> edges = new ArrayList<>();List<Vertex> pre = new ArrayList<>();for (Vertex vertex : graph) {for (Edge edge : vertex.edges) {edges.add(edge);pre.add(vertex);}}for (int i = 0; i < edges.size(); i++) {Edge minEdge = edges.get(i);int min = minEdge.weight;for (int j = i + 1 ; j < edges.size(); j++) {Edge e = edges.get(j);if(minEdge.weight > e.weight){edges.set(j,minEdge);minEdge = e;edges.set(i,e);Vertex v = pre.get(i);pre.set(i,pre.get(j));pre.set(j,v);}}}List<Vertex> used = new ArrayList<>();for (int i = 0; i < edges.size(); i++) {Vertex v = pre.get(i);Vertex e = edges.get(i).linked;if(!used.contains(v) || !used.contains(e)){System.out.println(v.name + " -> " + e.name);used.add(v);used.add(e);}}
}

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

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

相关文章

Mysql学习笔记系列(一)

本次mysql系列不会讲解具体的查询语句&#xff0c;而是放在mysql的一些性能优化和一些特性上&#xff0c;是学习笔记&#xff0c;供大家参考补充。 慢查询 MySQL的慢查询&#xff0c;全名是慢查询日志&#xff0c;是MySQL提供的一种日志记录&#xff0c;用来记录在MySQL中响应…

Meta 标签的力量:如何利用它们提高网站的可见性(上)

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

如何在ubuntu22.04安装ROS2

ubuntu22.04安装ROS2 教程 选择对应版本进行安装设置编码添加源安装ROS2设置环境变量 运行ROS2 选择对应版本 通过官方网站&#xff0c;查询Ubuntu与ros对应的版本&#xff0c;版本不一致也会出现安装不成功。 https://wiki.ros.org/ROS/Installation 每一个都可以进行点击&a…

解决电脑文件大小写不敏感问题

第一步&#xff1a;以管理员的身份运行 CMD 第二步&#xff1a; 输入下面命令 fsutil file setCaseSensitiveInfo 路径 enable 路径改成目标文件夹的路径&#xff0c;比如说我也下面 Less-24 这个文件夹里面的文件全部都大小写敏感 这样就 OK 了&#xff0c;注意路径最后要加…

GitFlow工作流

基于 Git 这一版本控制系统&#xff0c;通过定义不同的分支&#xff0c;探索合适的工作流程来完成开发、测试、修改等方面的需求。 例如&#xff1a;在开发阶段&#xff0c;创建 feature 分支&#xff0c;完成需求后&#xff0c;将此分支合并到 develop 分支上&#xff1b;在发…

深度学习常用代码总结(k-means, NMS)

目录 一、k-means 算法 二、NMS 一、k-means 算法 k-means 是一种无监督聚类算法&#xff0c;常用的聚类算法还有 DBSCAN。k-means 由于其原理简单&#xff0c;可解释强&#xff0c;实现方便&#xff0c;收敛速度快&#xff0c;在数据挖掘、数据分析、异常检测、模式识别、金…

PHP+vue+Mysql家庭理财管理系统演5x6nf

本文着重阐述了收支管理系统的分析、设计与实现&#xff0c;首先介绍开发系统和环境配置、数据库的设计&#xff0c;对系统的功能需求作出分析&#xff0c;根据需求对系统进行设计&#xff0c;明确各个部分的规范&#xff0c;来完成系统的设计。最后在对设计的系统进行一系列的…

k8s1.27.2版本二进制高可用集群部署

文章目录 环境软件版本服务器系统初始化设置关于etcd签名证书etcd集群部署负载均衡器组件安装设置关于k8s自签证书自签CAkube-apiserver 自签证书kube-controller-manager自签证书kube-scheduler自签证书kube-proxy 自签证书admin 自签证书 控制平面节点组件部署**部署kube-api…

Spring 事务原理一

从本篇博客开始&#xff0c;我们将梳理Spring事务相关的知识点。在开始前&#xff0c;想先给自己定一个目标&#xff1a;通过此次梳理要完全理解事务的基本概念及Spring实现事务的基本原理。为实现这个目标我想按以下几个步骤进行&#xff1a; 讲解事务中的一些基本概念使用Sp…

x-cmd pkg | jq - 命令行 JSON 处理器

目录 简介首次用户功能特点类似工具进一步探索 简介 jq 是轻量级的 JSON 处理工具&#xff0c;由 Stephen Dolan 于 2012 年使用 C 语言开发。 它的功能极为强大&#xff0c;语法简洁&#xff0c;可以灵活高效地完成从 JSON 数据中提取特定字段、过滤和排序数据、执行复杂的转…

Java NIO (三)NIO Channel类

1 概述 前面提到&#xff0c;Java NIO中一个socket连接使用一个Channel来表示。从更广泛的层面来说&#xff0c;一个通道可以表示一个底层的文件描述符&#xff0c;例如硬件设备、文件、网络连接等。然而&#xff0c;远不止如此&#xff0c;Java NIO的通道可以更加细化。例如&a…

【GitHub项目推荐--GitHub 上的考研神器】【转载】

如果有打算考研的读者&#xff0c;这些开源项目不能错过。把各个学校近几年考研初试真题分享给大家&#xff08;包括 408&#xff09;&#xff0c;应该能帮上大家&#xff0c;文末有下载方式。 同时&#xff0c;我把盘点的开源相关的学习项目更新到 Awesome GiHub Repo&#xf…

【GitHub项目推荐--智能家居项目】【转载】

如果你具备硬件、软件知识&#xff0c;这个项目肯定符合你的胃口。 物美智能是一套软硬件结合的开源项目&#xff0c;该系统可助你快速搭建自己的智能家居系统。你可以学习到设备的集成和软硬件交互。 PC 端或者手机与服务端通信&#xff0c;单片机可以接受遥控设备和服务器的…

硬件-11-服务器的基础知识

参考服务器基础知识大科普 1 电视剧背景 服务器被誉为互联网之魂。 电视剧《创业年代》是一部有冯绍峰和袁姗姗等人联手主演的一部讲述我国第一批科技创业者创业故事的电视剧&#xff0c;可以说是他们铲下了建设中关村的第一捧土。 电视剧《创业年代》中的潮信公司并没有…

【神经网络】火箭点火发射-诠释一场数据与学习的奇妙之旅

火箭点火发射来理解神经网络的故事细节 在一个充满科技气息的研究室里&#xff0c;一群科学家们正在忙碌地准备着一次重要的火箭点火发射。这次发射不仅是一次航天探索的壮丽征程&#xff0c;更是一场利用神经网络处理数据的智慧之旅。 在火箭发射的背后&#xff0c;神经网络…

中仕教育:研究生毕业可以考选调生吗?

选调生的报考条件之一是应届生&#xff0c;研究生毕业也属于应届生&#xff0c;所以是可以报考的。 选调生不同学历的年龄限制&#xff1a; 1.应届本科生&#xff1a;年龄在25岁以内 2.应届研究生&#xff1a;年龄在30岁以内 3.应届博士生&#xff1a;年龄在35岁以内 研究…

excel统计分析——Tukey法多重比较

参考资料&#xff1a;生物统计学 https://real-statistics.com/one-way-analysis-of-variance-anova/unplanned-comparisons/tukey-hsd/ Tukey法是基于学生化极差分布计算最小显著极差&#xff08;LSR&#xff09;&#xff0c;根据平均数个数调整最小显著极差。 LSR&#xff1…

LINUX常用工具之sudo权限控制

一、Sudo基本介绍 sudo是Linux 中用于允许特定用户以超级用户或其他特权用户的身份执行特定的命令或任务。sudo 提供了一种安全的方法&#xff0c;使用户能够临时获取额外的权限&#xff0c;而不需要以完全超级用户的身份登录系统。sudo也可以用了设置黑名单命令清单&#xff…

ROS第 13 课 TF 坐标系广播与监听的编程 实现

文章目录 第 13 课 TF 坐标系广播与监听的编程 实现1.机器人的坐标变换2.创建功能包3.编程方法3.1 编写广播和监听程序3.2 运行程序 第 13 课 TF 坐标系广播与监听的编程 实现 1.机器人的坐标变换 在进行编程前&#xff0c;先需要了解机器人的坐标变换。这里以运行海龟案例来…

有关软件测试的,任何时间都可以,软件测试主要服务项目:测试用例 报告 计划

有关软件测试的&#xff0c;任何时间都可以&#xff0c;软件测试主要服务项目&#xff1a; 1. 测试用例 2. 测试报告 3. 测试计划 4. 白盒测试 5. 黑盒测试 6. 接口测试 7.自动…