首页 > 编程语言 >与图相关的一些算法

与图相关的一些算法

时间:2022-09-29 19:15:46浏览次数:79  
标签:Node node set import 算法 new 一些 相关 public

与图相关的一些算法

作者:Grey

原文地址:

博客园:与图相关的一些算法

CSDN:与图相关的一些算法

图的说明

线性表中的元素是“一对一”的关系,树中的元素是“一对多”的关系,图结构中的元素则是“多对多”的关系。

图(Graph)是一种复杂的非线性结构,在图结构中,每个元素都可以有零个或多个前驱,也可以有零个或多个后继,也就是说,元素之间的关系是任意的。

图中包括点集和边集,可以用以下代码来表示

import java.util.ArrayList;

public class Node {
    // 点的值
    public int value;
    // 入度
    public int in;
    // 出度
    public int out;
    // 邻居节点
    public ArrayList<Node> nexts;
    // 邻边
    public ArrayList<Edge> edges;

    public Node(int value) {
        this.value = value;
        in = 0;
        out = 0;
        nexts = new ArrayList<>();
        edges = new ArrayList<>();
    }
}

public class Edge {
    // 权值
    public int weight;
    // 起点
    public Node from;
    // 终点
    public Node to;

    public Edge(int weight, Node from, Node to) {
        this.weight = weight;
        this.from = from;
        this.to = to;
    }
}

import java.util.HashMap;
import java.util.HashSet;

public class Graph {
    // 点集
    public HashMap<Integer, Node> nodes;
    // 边集
    public HashSet<Edge> edges;

    public Graph() {
        nodes = new HashMap<>();
        edges = new HashSet<>();
    }
}

以上只是一种图的定义方式,每个人可以根据自己的习惯来定义自己熟悉的图数据结构,面对一个不熟悉的图结构,可以通过写一个转换方法来将不熟悉的图结构转换成自己熟悉的图结构。

比如,一个整数类型的二维矩阵也可以表示图,见图的二维数组表示

我们可以通过写一个转换函数把二维数组的图转换成自己熟悉的图结构

// 二维数组转换成自己熟悉的图结构
public class GraphGenerator {
    public static Graph createGraph(Integer[][] matrix) {
        Graph graph = new Graph();
        for (int i = 0; i < matrix.length; i++) {
            // matrix[0][0], matrix[0][1]  matrix[0][2]
            Integer weight = matrix[i][0];
            Integer from = matrix[i][1];
            Integer to = matrix[i][2];
            if (!graph.nodes.containsKey(from)) {
                graph.nodes.put(from, new Node(from));
            }
            if (!graph.nodes.containsKey(to)) {
                graph.nodes.put(to, new Node(to));
            }
            Node fromNode = graph.nodes.get(from);
            Node toNode = graph.nodes.get(to);
            Edge newEdge = new Edge(weight, fromNode, toNode);
            fromNode.nexts.add(toNode);
            fromNode.out++;
            toNode.in++;
            fromNode.edges.add(newEdge);
            graph.edges.add(newEdge);
        }
        return graph;
    }
}

图的深度优先遍历(DFS)

流程如下

  1. 利用栈实现;

  2. 从源节点开始把节点按照深度放入栈,然后弹出;

  3. 每弹出一个点,把该节点下一个没有进过栈的邻接点放入栈;

  4. 直到栈变空。

完整代码如下

import snippet.graph.Node;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashSet;
import java.util.List;
import java.util.Set;


public class Code_DFS {
    // 迭代版本
    public static List<Node> dfs(Node node) {
        if (node == null) {
            return new ArrayList<>();
        }
        List<Node> ans = new ArrayList<>();
        Deque<Node> stack = new ArrayDeque<>();
        HashSet<Node> set = new HashSet<>();
        stack.add(node);
        set.add(node);
        ans.add(node);
        while (!stack.isEmpty()) {
            Node cur = stack.pop();
            for (Node next : cur.nexts) {
                if (!set.contains(next)) {
                    stack.push(cur);
                    stack.push(next);
                    set.add(next);
                    ans.add(next);
                    break;
                }
            }
        }
        return ans;
    }

    // 递归版本
    public static List<Node> dfs2(Node node) {
        if (node == null) {
            return new ArrayList<>();
        }
        List<Node> ans = new ArrayList<>();
        Set<Node> set = new HashSet<>();
        dfs(node, ans, set);
        return ans;
    }

    private static void dfs(Node node, List<Node> ans, Set<Node> set) {
        ans.add(node);
        set.add(node);
        if (node.nexts != null && !node.nexts.isEmpty()) {
            for (Node n : node.nexts) {
                if (!set.contains(n)) {
                    dfs(n, ans, set);
                }
            }
        }
    }
}

图的宽度优先遍历(BFS)

流程如下

  1. 利用队列实现;

  2. 从源节点开始依次按照宽度进队列,然后弹出;

  3. 每弹出一个点,把该节点所有没有进过队列的邻接点放入队列;

  4. 直到队列变空。

import snippet.graph.Node;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

public class Code_BFS {

    public static List<Node> bfs(Node node) {
        if (null == node) {
            return new ArrayList<>();
        }
        List<Node> ans = new ArrayList<>();
        Queue<Node> queue = new LinkedList<>();
        HashSet<Node> set = new HashSet<>();
        queue.offer(node);
        set.add(node);
        while (!queue.isEmpty()) {
            Node cur = queue.poll();
            // System.out.println(cur.value);
            ans.add(cur);
            if (cur.nexts != null && !cur.nexts.isEmpty()) {
                for (Node t : cur.nexts) {
                    if (!set.contains(t)) {
                        queue.offer(t);
                        set.add(t);
                    }
                }
            }
        }
        return ans;
    }
}

更多

算法和数据结构笔记

参考资料

算法和数据结构体系班-左程云

标签:Node,node,set,import,算法,new,一些,相关,public
From: https://www.cnblogs.com/greyzeng/p/16742656.html

相关文章

  • modbus相关
    Modbus寄存器分类及地址分配python是实现ModSim寄存器读取http://t.zoukankan.com/liuwenhua-p-13746044.htmlhttps://www.cnblogs.com/liuwenhua/p/13746044.htmlhttp......
  • AcWing 算法提高课 AC自动机
    AC自动机=Trie+kmp优化:Trie图1、kmp长字符串s和模板串p都以下标1开始。(1)求next数组:kmp的next数组存的是p的自匹配,即以p[i]为结尾的后缀能够匹配的最长非平凡(不是自......
  • 从0开始学习Axure(三)Axure元件相关知识
    1.元件相关1.1画布操作在页面模块中,可以双击任意一个页面,打开相应的画布,在画布的上方也会出现相应的标签也可以通过拖动页面改变页面顺序等操作1.2元件操作若想使用......
  • 变邻域搜索算法通俗讲解
    首先声明本文是在参考《数据魔术师》公众号的《干货|变邻域搜索算法(VariableNeighborhoodSearch,VNS)超详细一看就懂》这一篇文章的基础上,并结合自己的理解撰写《VNS通......
  • 多种群遗传算法的函数优化算法(附MATLAB代码)
    最近小编终于重新拿起智能优化算法的圣经《MATLAB智能算法30个案例分析(第2版)》,每次读这本书都会有新的收获,今天要与大家分享的智能算法是多种群遗传算法。PS:文中代码来源于......
  • 用matlab调用迄今为止最强悍的求解旅行商(TSP)的算法-LKH算法
    最近小编恰好遇到这样一个问题,如何用matlab调用比较牛X的TSPsolver,小编费劲千辛万苦终于在github上找到一位大神写的LKH的matlab接口(网址链接:​​https://github.com/unr-a......
  • VRPTW合集 [CW节约算法,TS(硬约束版),TS(惩罚函数版),LNS四种方法对比(附MATLAB代码)]
    01方法回顾VRPTW系列推文终于要告一段落了,最初小编写了一篇最基本的节约算法构造VRPTW初始解推文;然后在这个基础上,小编尝试用3种不同的策略在所构造的初始解的基础上,进一步......
  • 免疫算法求解配送中心选址问题(附MATLAB代码)
    本文参考《MATLAB智能算法30个案例分析》一书,文末的源代码也来自本书本次推文为大家讲解免疫算法,隐约中记得一位小伙伴后台问我能否推出这样一篇推文,小编的参考资料很简单,依......
  • 禁忌搜索算法求解带时间窗的车辆路径问题(上)
    今天小编准备讲一下用禁忌搜索算法(下文简称TS)求解带时间窗的VRP问题(下文简称VRPTW)。下面小编带大家体会TS的思想。以VRPTW为例,VRPTW的解的形式为每辆车所经过的顾客,比如说有......
  • 基于蚁群的二维路径规划算法(附MATLAB代码)
    本文参考《MATLAB智能算法30个案例分析》一书,文末的源代码也来自本书前一段时间有小伙伴问能否出一个机器人路径规划的推文,小编最近努力查资料,然后学习一些新知识,然后才动笔......