数据结构与算法:图

文章目录

      • 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;

    @Override
    public 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)); // +1
        v2.edges = java.util.List.of(new Edge(v3)); // +1
        v3.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  v4
            v1  0   ∞   -2  ∞
            v2  4   0   3   ∞
            v3  ∞   ∞   0   2
            v4  ∞   -1  ∞   0

                k=0 借助v1到达其它顶点
                v1  v2  v3  v4
            v1  0   ∞   -2  ∞
            v2  4   0   2   ∞
            v3  ∞   ∞   0   2
            v4  ∞   -1  ∞   0

                k=1 借助v2到达其它顶点
                v1  v2  v3  v4
            v1  0   ∞   -2  ∞
            v2  4   0   2   ∞
            v3  ∞   ∞   0   2
            v4  3   -1  1   0

                k=2 借助v3到达其它顶点
                v1  v2  v3  v4
            v1  0   ∞   -2  0
            v2  4   0   2   4
            v3  ∞   ∞   0   2
            v4  3   -1  1   0

                k=3 借助v4到达其它顶点
                v1  v2  v3  v4
            v1  0   -1   -2  0
            v2  4   0   2   4
            v3  5   1   0   2
            v4  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);
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

前后端分离,使用vue3整合SpringSecurity加JWT实现登录校验

前段时间写了一篇spring security的详细入门&#xff0c;但是没有联系实际。 所以这次在真实的项目中来演示一下怎样使用springsecurity来实现我们最常用的登录校验。本次演示使用现在市面上最常见的开发方式&#xff0c;前后端分离开发。前端使用vue3进行构建&#xff0c;用到…

vue生命周期图示

详见&#xff1a;官网介绍

梳理一下若依框架的权限过滤系统

梳理一下若依框架的权限过滤系统 首先&#xff0c;我们直入主题&#xff0c;且看这段代码 /*** 获取用户列表*/ PreAuthorize("ss.hasPermi(system:user:list)") GetMapping("/list") public TableDataInfo list(SysUser user) {startPage();List<SysU…

OpenHarmony当前进展和未来趋势

操作系统自20世纪50年代诞生&#xff0c;经历了从专用操作系统到通用操作系统的转变。整体可以将操作系统的发展历史分为3个阶段&#xff1a;PC时代、移动互联网时代、万物互联时代。 PC时代主要以计算机为主&#xff0c;用户规模从1970年的10亿增长到1990年的30亿。这一时代诞…

QComboBox 下拉框

文章目录 1、简介2、functions3、Signal QT 官方文档参考地址&#xff1a;https://doc.qt.io/qt-5/qcombobox.html 1、简介 QComboBox 是下拉列表框组件类&#xff0c;它提供一个下拉列表供用户选择&#xff0c;也可以直接当作一个 QLineEdit 用作输入。 2、functions 1、voi…

供应商导添加预扣税字段

文章目录 1 Introduction2 Code3 Summary 1 Introduction I only think I can assign value to them and I implement it by the following code . 2 Code LOOP AT gt_bukrs INTO gs_bukrs WHERE lifnr gs_alv1-lifnr.CLEAR:ls_company.ls_company-task M.ls_company-data…

mybatis----动态Sql

1.if标签 通过if标签构建动态条件&#xff0c;通过其test属性的true或false来判断该添加语句是否执行。 mapper接口 public interface AccountMapper {List<Account> selectAllByCondition(Account account); } 映射文件 <select id"selectAllByCondition&q…

具有运动模糊的大规模场景的混合神经绘制

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 摘要Abstract文献阅读&#xff1a;具有运动模糊的大规模场景的混合神经绘制1、研究背景2、方法提出3、视点依赖归一化方法4、训练方法5、试验细节及对比 YOLO模型1、…

.NET高速开发分层架构,ASPNETCore,IOC开发

分层架构,ASPNETCore,IOC开发 大家好,我是行不更名,坐不改姓的宋晓刚。今天我将带领大家深入了解分层架构、ASP.NET Core、IoC 开发,以及共同开发的魅力。我们将一同探索如何利用这些先进技术构建高效、可维护的数据库应用程序。 家人们,如果有什么不懂,可以留言,或者…

【JS逆向学习】国家加密系列-SM算法实例

SM系列 1、国家加密算法介绍 事实上从 2010 年开始&#xff0c;我国国家密码管理局就已经开始陆续发布了一系列国产加密算法&#xff0c;其中SM1、SM4、SM7、祖冲之密码&#xff08;ZUC&#xff09;是对称算法&#xff1b;SM2、SM9是非对称算法&#xff1b;SM3是哈希算法。目…

大数据导论(4)---大数据应用

文章目录 1. 在互联网中的应用1.1 推荐系统1.2 长尾理论1.3 推荐方法与模型1.4 推荐系统应用 2. 在其他领域的应用2.1 企业营销2.2 智慧交通 1. 在互联网中的应用 1.1 推荐系统 1. 推荐系统产生&#xff1a;  (1) 互联网的飞速发展使我们进入了信息过载的时代&#xff0c;搜索…

二叉树题目:二叉树的序列化与反序列化

文章目录 题目标题和出处难度题目描述要求示例数据范围 前言解法一思路和算法代码复杂度分析 解法二思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;二叉树的序列化与反序列化 出处&#xff1a;297. 二叉树的序列化与反序列化 难度 8 级 题目描述 要求 序列…

数据结构:堆与堆排序

目录 堆的定义&#xff1a; 堆的实现&#xff1a; 堆的元素插入&#xff1a; 堆元素删除&#xff1a; 堆初始化与销毁&#xff1a; 堆排序&#xff1a; 堆的定义&#xff1a; 堆是一种完全二叉树&#xff0c;完全二叉树定义如下&#xff1a; 一棵深度为k的有n个结点的二…

微信小程序的nodejs+vue课堂在线学习系统教学辅助平台PHP设计与实现

小程序主要实现功能&#xff1a;一、用户的登录与实现 二、课程页面。学生们可以观看课程视频【课程视频有章程】&#xff0c;搜索课程&#xff0c;课程签到&#xff0c;评论课程&#xff0c;课后答题&#xff08;课后成绩&#xff09;&#xff0c;课程互动&#xff08;在视频下…

【深度学习】手把手教你使用 Auto DL 远程服务器连接 PyCharm

前言 文章性质&#xff1a;实操记录 &#x1f4bb; 主要内容&#xff1a;主要记录了如何租用 Auto DL 服务器&#xff0c;以及如何在 PyCharm 中连接远程服务器。 相关文档&#xff1a;如何使用 Auto DL 远程服务器连接 PyCharm 运行代码 - 知乎 冷知识1&#xff1a;小伙伴们不…

c++:string相关的oj题(把字符串转换成整数、344.反转字符串、387. 字符串中的第一个唯一字符、917. 仅仅反转字母)

文章目录 1.把字符串转换成整数题目详情代码思路 2. 344.反转字符串题目详情代码1思路1代码2思路 3. 387. 字符串中的第一个唯一字符题目详情代码思路 4. 917. 仅仅反转字母题目详情代码思路 1.把字符串转换成整数 传送门 题目详情 代码 class Solution { public:int StrToI…

提升用户体验的利器——TTS语音合成软件盘点

提升用户体验的利器——TTS语音合成软件盘点 在当今信息爆炸的时代&#xff0c;人们每天都要处理大量的文本信息。因此&#xff0c;将文本信息转化为语音信息&#xff0c;使得信息能够以更自然、更方便的方式传达给人们&#xff0c;就显得尤为重要。这就是TTS&#xff08;Text…

【C++修行之道】竞赛常用库函数(sort,min和max函数,min_element和max_element、nth_element)

目录 一、sort 1.1sort简介 语法 参数 功能 适用容器 1.2sort的用法 1.3自定义比较函数 示例 1265蓝桥题 —— 排序 二、min和max函数 三、min_element和max_element 497蓝桥题 —— 成绩分析 四、nth_element 一、sort 1.1sort简介 sort函数包含在头文件<a…

手机软件的测试主要有哪些方面去测试,性能测试用什么去测试好?

手机App软件与Web软件系统的架构是不一样的&#xff0c;手机是基于CS架构&#xff0c;而Web系统是基于BS架构的&#xff0c;所以测试手机App软件那么要考虑的东西会更多一些。 分析题主的问题包含两块&#xff1a; 1、手机软件(App)测试主要有哪些方面&#xff1f; 2、手机软件…

【C/C++】C/C++编程——为什么学习 C++?

当提到C的时候&#xff0c;很多人会觉得语法复杂、学习曲线陡峭&#xff0c;并且好像与C语言还有点"纠缠不清"。尽管如此&#xff0c;C仍然是当今世界上最受欢迎和最有影响力的编程语言之一。特别是在当今快速发展的人工智能&#xff08;AI&#xff09;领域&#xff…