图相关的一些算法 java

1、制定图的模板结构:

package learn;

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<Integer, Node>();
        edges=new HashSet<Edge>();
    }
}
package learn;

import java.util.ArrayList;

public class Node {
    public int value;
    public int in;//有多少入度
    public int out;//出度
    public ArrayList<Node> nexts;//Node指向的邻接点
    public ArrayList<Edge> edges;//属于Node的边

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

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

2、将题目给定的图结构转化为模板结构
例子:

package learn;

public class Demo {
    public static Graph creatGraph(Integer[][] matrix) {//将二维数组存储的图结构转化为模板图结构
        Graph g=new Graph();
        for(int i=0;i<matrix.length;i++) {//matrix.length 获取行数
            Integer weight = matrix[i][0];
            Integer from=matrix[i][1];
            Integer to=matrix[i][2];
            
            //如果graph的nodes中没有form to两点,将其加入点集
            if(!g.nodes.containsKey(from)){
                g.nodes.put(from,new Node(from));
            }
            if(!g.nodes.containsKey(to)){
                g.nodes.put(from,new Node(to));
            }
            
            Node fromNode=g.nodes.get(from);
            Node toNode=g.nodes.get(to);
            Edge e=new Edge(weight,fromNode,toNode);
            g.edges.add(e);//加入图的边集
            
            fromNode.out++;
            toNode.in++;
            fromNode.nexts.add(toNode);
            fromNode.edges.add(e);
        }
        return g;
    }
}

3、BFS: 队列和set

package learn;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

public class BFS_Code {
    public static void bfs(Node node) {
        if(node==null)return;
        Queue<Node> q=new LinkedList<>();
        HashSet<Node> s=new HashSet<>();
        q.add(node);
        s.add(node);
        while (!q.isEmpty()){
            Node n=q.poll();
            System.out.println(n.value);
            for(Node next:n.nexts){
                if(!s.contains(next)){
                    q.add(next);
                    s.add(next);
                }
            }
        }
    }
}

4、DFS:栈和set

package learn;

import java.util.HashSet;
import java.util.Stack;

public class DFS {
    public static void dfs(Node node) {
        if(node==null)return;
        Stack<Node> s=new Stack<>();
        HashSet<Node> hs=new HashSet<>();
        s.add(node);
        hs.add(node);
        System.out.println(node.value);
        while (!s.isEmpty()){
            Node n=s.pop();//不能pop的时候输出,因为pop过的节点可能被重新压入后再次pop
            for(Node next:n.nexts){
                if(!hs.contains(next)){
                    s.add(n);
                    s.add(next);
                    hs.add(next);
                    System.out.println(next.value);
                    break;
                }
            }
        }
    }
}

5、拓扑排序:

package learn;

import java.util.*;

public class TopologySort {
    public static List<Node> sort(Graph graph) {
        HashMap<Node,Integer> hs=new HashMap<>();//记录node的剩余入度
        //入度为0的进入队列 供选择输出
        Queue<Node> q=new LinkedList<>();
        List<Node> result=new ArrayList<>();//将最终排序结果放入result
        
        //.values获取所有键值对象
        for(Node node:graph.nodes.values()){
            hs.put(node,node.in);
            if(node.in==0){
                q.add(node);
            }
        }
        
        while (!q.isEmpty()){
            Node n=q.poll();
            result.add(n);
            for(Node next:n.nexts){
                hs.put(next,hs.get(next)-1);
                if(hs.get(next)==0){
                    q.add(next);
                }
            }
        }
        
        return result;
    }
}

6、最小生成树:
(1)Kruskal: 加边,判断一边的两点是否在一个同一个集合中

package learn;

import java.util.*;

public class Kruskal {
    //定制一个集合,实现判断是否在同一个集合,合并两点所属的集合
    public static class MySets {
        public HashMap<Node, List<Node>> hs;
        public MySets(List<Node> nodes) {
            for (Node n : nodes) {//将每个点加入不同的集合,各成分支
                List<Node> l = new ArrayList<>();
                l.add(n);
                hs.put(n, l);
            }
        }

        public boolean isSameSet(Node from,Node to){
            List<Node> l1=hs.get(from);
            List<Node> l2=hs.get(to);
            return l1==l2;
        }

        public void union(Node from,Node to) {
            List<Node> l1=hs.get(from);
            List<Node> l2=hs.get(to);

            //将l2中的点并入l1,并修改l2中的点在map中对应集合为l1
            for(Node n:l2){
                l1.add(n);
                hs.put(n,l1);
            }
        }
    }

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

    public static Set<Edge> kruskalMST(Graph graph) {
        MySets ms=new MySets((List<Node>) graph.nodes.values());//类型转化
        PriorityQueue<Edge> pq=new PriorityQueue<>(new EdgeComparator());//小根堆
        Set<Edge> result=new HashSet<>();
        for (Edge e:graph.edges){
            pq.add(e);
        }
        while (!pq.isEmpty()){
            Edge edge=pq.poll();
            if(!ms.isSameSet(edge.from,edge.to)){
                result.add(edge);
                ms.union(edge.from,edge.to);
            }
        }
        return result;
    }
}

(2)Prim: 加点

package learn;

import java.util.Comparator;
import java.util.HashSet;
import java.util.PriorityQueue;
import java.util.Set;

public class Prim {
    public static class EdgeComparator implements Comparator<Edge>{
        public int compare(Edge o1,Edge o2){
            return o1.weight-o2.weight;
        }
    }
    public static Set<Edge> PrimMST(Graph graph) {
        PriorityQueue<Edge> pq=new PriorityQueue<>(new EdgeComparator());//将已经解锁的边放入其中
        HashSet<Node> hs=new HashSet<>();//将已经并入的点加入该集合
        Set<Edge> result=new HashSet<>();//将结果边放入

        for(Node node:graph.nodes.values()){//可能出现所有节点并非连通的状态 类似森林
            if(!hs.contains(node)){
                hs.add(node);//从该节点起生成一个最小生成树
                for(Edge edge:node.edges){
                    pq.add(edge);
                }
                while (!pq.isEmpty()){
                    Edge e= pq.poll();//弹出解锁边中最小的边
                    Node toNode =e.to;
                    if(!hs.contains(toNode)){
                        hs.add(toNode);
                        result.add(e);
                        for(Edge nextEdge:toNode.edges){
                            pq.add(nextEdge);
                        }
                    }
                }
            }
        }
        return result;
    }
}

7、Dijkstra: 单源最短路径

package learn;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.Entry;

public class Dijkstra {
    public static HashMap<Node,Integer> dijkstral(Node head) {
        HashMap<Node,Integer> distanceMap=new HashMap<>();//记录从源点出发到node的当前最小距离
        HashSet<Node> selectedNodes=new HashSet<>();//已经确定从源点到自身最小距离路径的node,锁定在集合中
        distanceMap.put(head,0);//源点到源点距离为0

        Node minNode=getMinDistanceAndUnselectedNode(distanceMap,selectedNodes);//找到不在锁定节点中,且所有路径中,达到该节点是最短的节点
        while (minNode!=null){
            int distance=distanceMap.get(minNode);
            for (Edge edge : minNode.edges) {
                Node toNode = edge.to;
                //if (!selectedNodes.contains(toNode)) {//此if判断可有可无
                    if (!distanceMap.containsKey(toNode)) {
                        distanceMap.put(toNode, distance + edge.weight);
                    } else {
                        distanceMap.put(toNode, Math.min(distanceMap.get(toNode), distance + edge.weight));
                    }
                }
            //}
            selectedNodes.add(minNode);
            minNode=getMinDistanceAndUnselectedNode(distanceMap,selectedNodes);
        }
        return distanceMap;
    }

    public static Node getMinDistanceAndUnselectedNode(HashMap<Node,Integer> d,HashSet<Node> s){
        Node minNode=null;
        int minDistance=Integer.MAX_VALUE;
        for(Entry<Node,Integer> entry:d.entrySet()){
            Node node=entry.getKey();
            if(!s.contains(node)){//当节点都在s中时,无法进入if中,minNode最终会等于null
                int distance=entry.getValue();
                if(distance<minDistance){
                    minNode=node;
                    minDistance=distance;
                }
            }
        }
        return minNode;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值