首页 > 编程语言 >左神算法-基础06-图

左神算法-基础06-图

时间:2023-07-24 23:56:09浏览次数:48  
标签:Node node 06 add 左神 算法 edge new public

左神算法-基础06-图

图的存储方式

  1. 邻接表

  2. 邻接矩阵

如何表达图?生成图?

//图的节点
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;
        this.in = 0;
        this.out = 0;
        this.nexts = new ArrayList<>();
        this.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;
    }
}
//图
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++) {
            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;
    }
}

图的宽度优先遍历

  1. 利用队列实现

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

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

  4. 直到队列变空

     public static void bfs(Node node) {
         if (node == null) {
             return;
         }
         Queue<Node> queue = new LinkedList<>();
         HashSet<Node> map = new HashSet<>();
         map.add(node);
         queue.add(node);
         while (!queue.isEmpty()) {
             Node cur = queue.poll();
             System.out.println(cur.value);  //处理代码
             for (Node next : cur.nexts) {
                 if (!map.contains(next)) {
                     map.add(next);
                     queue.add(next);
                 }
             }
         }
     }
    

广度优先遍历

  1. 利用栈实现

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

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

  4. 直到栈变空

     public static void dfs(Node node) {
         if(node == null) {
             return;
         }
         Stack<Node> stack = new Stack<>();
         HashSet<Node> set = new HashSet<>();
         stack.add(node);
         set.add(node);
         System.out.println(node.value);
         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);
                     System.out.println(next.value);
                     break;
                 }
             }
         }
     }
    

拓扑排序算法

适用范围:要求有向图,且有入度为0的节点,且没有环

    public static List<Node> sortedTopology(Graph graph) {
        //key: 某一个node
        //value: 剩余的入度
        HashMap<Node, Integer> inMap = new HashMap<>();
        //入度为0的点才能进这个队列
        Queue<Node> zeroInQueue = new LinkedList<>();
        for (Node node : graph.nodes.values()) {
            inMap.put(node, node.in);
            if (node.in == 0) {
                zeroInQueue.add(node);
            }
        }
        //拓扑排序的结果以此加入result
        List<Node> result = new ArrayList<>();
        while(!zeroInQueue.isEmpty()) {
            Node cur = zeroInQueue.poll();
            result.add(cur);
            for (Node next : cur.nexts) {
                inMap.put(next, inMap.get(next) - 1);
                if (inMap.get(next) == 0) {
                    zeroInQueue.add(next);
                }
            }
        }
        return result;
    }

kruskal算法

适用范围:要求无向图

    //类并查集结构
    public static class MySets{
        public HashMap<Node, List<Node>> setMap;

        public MySets(Collection<Node> nodes) {
            for (Node node : nodes) {
                List<Node> set = new ArrayList<Node>();
                set.add(node);
                setMap.put(node, set);
            }
        }

        public boolean isSameSet(Node from, Node to) {
            List<Node> fromSet = setMap.get(from);
            List<Node> toSet = setMap.get(to);
            return fromSet == toSet;
        }

        public void union(Node from, Node to){
            List<Node> fromSet = setMap.get(from);
            List<Node> toSet = setMap.get(to);
            for (Node toNode : toSet) {
                fromSet.add(toNode);
                setMap.put(toNode, fromSet);
            }
        }
    }
    
    public static class EdgeComparator implements Comparator<Edge> {
        @Override
        public int compare(Edge o1, Edge o2) {
            return o1.weight - o2.weight;
        }
    }

    public static Set<Edge> kruskalMST(Graph graph) {
        MySets sets = new MySets(graph.nodes.values());
        PriorityQueue<Edge> priorityQueue = new PriorityQueue<>(new EdgeComparator());
        for (Edge edge : graph.edges) {
            priorityQueue.add(edge);
        }
        HashSet<Edge> result = new HashSet<>();
        while(!priorityQueue.isEmpty()) {
            Edge edge = priorityQueue.poll();
            if (!sets.isSameSet(edge.from, edge.to)) {
                result.add(edge);
                sets.union(edge.from, edge.to);
            }
        }
        return result;
    }

prim算法

适用范围:要求无向图

    public static class EdgeComparator implements Comparator<Edge> {
        @Override
        public int compare(Edge o1, Edge o2) {
            return o1.weight - o2.weight;
        }
    }

    public static Set<Edge> primMST(Graph graph) {
        //解锁的边进入小根堆
        PriorityQueue<Edge> priorityQueue = new PriorityQueue<>(new EdgeComparator());
        HashSet<Node> set = new HashSet<>();
        //依次挑选的边在result里
        Set<Edge> result = new HashSet<>();
        for (Node node : graph.nodes.values()) {
            if (!set.contains(node)) {
                set.add(node);
                for (Edge edge : node.edges) {//由一个点解锁所有相连的边
                    priorityQueue.add(edge);
                }
                while(!priorityQueue.isEmpty()) {
                    Edge edge = priorityQueue.poll();//弹出最小的边
                    Node toNode = edge.to;//可能的一个新的点
                    if (!set.contains(toNode)) {//不含有的时候就是新的点
                        set.add(toNode);
                        result.add(edge);
                        for (Edge nextEdge : toNode.edges) {
                            priorityQueue.add(nextEdge);
                        }
                    }
                }
            }
        }
        return result;
    }

Dijkstra算法

适用范围:没有权值为负数的环

    public static HashMap<Node, Integer> dijkstra(Node head) {
        //从head出发到所有点的最小距离
        //key:从head出发到达key
        //value:从head出发到达key的最小距离
        //如果在表中,没有T的记录,含义是从head出发到达T这个点的距离为正无穷
        HashMap<Node, Integer> distanceMap = new HashMap<>();
        distanceMap.put(head, 0);
        //已经求过距离的节点,存在selectedNodes中,以后再也不碰
        HashSet<Node> selectedNodes = new HashSet<>();
        Node minNode = getMinDistanceAndUnselectedNode(distanceMap, selectedNodes);
        while(minNode != null) {
            int distance = distanceMap.get(minNode);
            for (Edge edge : minNode.edges) {
                Node toNode = edge.to;
                if (!distanceMap.containsKey(toNode)) {
                    distanceMap.put(toNode, distance + edge.weight);
                } else {
                    distanceMap.put(edge.to, Math.min(distanceMap.get(toNode), distance + edge.weight));
                }
            }
            selectedNodes.add(minNode);
            minNode = getMinDistanceAndUnselectedNode(distanceMap, selectedNodes);
        }
        return distanceMap;
    }

    public static Node getMinDistanceAndUnselectedNode(HashMap<Node, Integer> distanceMap, HashSet<Node> touchedNodes) {
        Node minNode = null;
        int minDistance = Integer.MAX_VALUE;
        for (Entry<Node, Integer> entry : distanceMap.entrySet()) {
            Node node = entry.getKey();
            int distance = entry.getValue();
            if (!touchedNodes.contains(node) && distance < minDistance) {
                minNode = node;
                minDistance = distance;
            }
        }
        return minNode;
    }

标签:Node,node,06,add,左神,算法,edge,new,public
From: https://www.cnblogs.com/zhangj9/p/17578662.html

相关文章

  • list agg cause ORA-06502 PL/SQL: numeric or value error
    http://www.idb-stock.net/idb/2011/07/05/204.htmlora-06502错误主要是指数据字或值错误,包括以下子类型:字符到数据值的转换错误、字符串缓冲区太小、数值精度太高等。对空集合的调用,会报ora-06502错误declaretypecnt_typistableofnumberindexbybinary_integer;v_c......
  • 文心一言 VS 讯飞星火 VS chatgpt (65)-- 算法导论6.5 4题
    四、在MAX-HEAP-INSERT的第2行,为什么我们要先把关键字设为-∞,然后又将其增加到所需的值呢?文心一言:在MAX-HEAP-INSERT算法的第二行将关键字设为-∞,是为了保持堆的性质。堆是一种二叉树结构,其中每个节点的值都大于或等于其子节点的值。在MAX-HEAP-INSERT算法中,我们需要在......
  • 算法练习-day29
    贪心算法435.无重叠区间题意:给定一个区间的集合 intervals ,其中intervals[i]=[starti,endi] 。返回需要移除区间的最小数量,使剩余区间互不重叠 。实例:思路:本题和452.用最少数量的箭引爆气球做法非常类似,大家可以先看看我之前的文章。本题我们只需要统计重叠的区域,代码如......
  • 文心一言 VS 讯飞星火 VS chatgpt (65)-- 算法导论6.5 4题
    四、在MAX-HEAP-INSERT的第2行,为什么我们要先把关键字设为-∞,然后又将其增加到所需的值呢?文心一言:在MAX-HEAP-INSERT算法的第二行将关键字设为-∞,是为了保持堆的性质。堆是一种二叉树结构,其中每个节点的值都大于或等于其子节点的值。在MAX-HEAP-INSERT算法中,我们需要......
  • 算法练习-day28
    贪心算法860.柠檬水找零题意:在柠檬水摊上,每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品,(按账单bills支付的顺序)一次购买一杯。每位顾客只买一杯柠檬水,然后向你付5美元、10美元或20美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付5美元。注意,一开......
  • CF506E Mr. Kitayuta's Gift 思考--zhengjun
    妙妙题。首先可以有一个\(O(kn^2)\)的dp,但是显然不行。但是,发现其中的大多数转移都浪费在自环上了,所以考虑不要这个东西。这个dp一共有三种转移:左右端点一起向内移动一格;左端点或右端点单独移动;左右端点都不动。所以考虑加一维\(k\)表示走了\(k\)次转移1......
  • MCU基于非对称算法的伪安全启动方案
    一、概述随着软件定义汽车理念的普及,汽车上代码量不断膨胀,功能不断智能化,用户体验不断升级。从传统汽车不需要联网,到职能汽车具有联网功能已是标配,汽车触网必将带来更多信息安全问题。汽车的信息安全问题比IT领域更加重要,因为可能危及生命安全。故国家也出台强标《汽车整车信息安......
  • JavaScript数据结构和算法简述——数组
    为什么先讲数组数据结构可以简单的被分为线性结构和非线性结构。线性结构大致包括:数组(连续存储);链表(离散存储);栈(线性结构常见应用,由链表或数组增删和改进功能实现);队列(线性结构常见应用,由链表或数组增删和改进功能实现);非线性结构大致包括:树;图;其中,数组是应用最广泛的数据存储结构。它被......
  • 第二届粤港澳大湾区(黄埔)国际算法算例大赛正式开启报名
    据悉,2023第二届“粤港澳大湾区(黄埔)国际算法算例大赛”(以下简称“大赛”)已于7月15日正式开赛。粤港澳大湾区(黄埔)国际算法算例大赛是受广州市黄埔区政府委托,由琶洲实验室(黄埔)于2022年创办的算法算例领域国际性赛事。旨在通过发挥实验室在数字经济领域的引领和带动作用,推动大湾......
  • ORA-10635:无效的段或表空间类型
    错误信息【汉】ORA-10635:无效的段或表空间类型【英】ORA-10635:Invalidsegmentortablespacetype例在正常运行的Oracle数据库中,执行收缩段(表)报错。版本Oracle【11.2.0.3.0】、【11.2.0.1.0】、【11.2.0.4.0】原因无法收缩段,因为Oracle在收缩前检测到,段(表)不在自动段空间管理......