每日算法总结——图的表示、图的宽度优先遍历BFS、图的深度优先遍历DFS

一、图的表示

图的算法不难,但图的表示方法很多,比如邻接表法、邻接矩阵等等。这就导致对于每一种图的表示方法,都要写出该表示方法对应的一套算法。

同时,这也是面试场合经常出现的情况,对于一种不熟悉的图表示方法,往往很难去进行相应算法的转换

对于这种情况,大佬给出的建议是熟练掌握一种图的表示方法,并掌握所有用该表示方法编写的算法。面试场合只需要去思考如何建立所给图表示方法到熟悉的图表示方法的映射即可。

  • 图类
    包含所有的点集和所有的边集

    public class Graph {
        /**
         * Integer表示点的编号,Node表示实际的点
         */
        public HashMap<Integer, Node> nodes;
        public HashSet<Edge> edges;
    
        public Graph() {
            nodes = new HashMap<>();
            edges = new HashSet<>();
        }
    }
    

    一般情况下,Node的编号就是Node的值,且编号范围固定,比如1000个城市之间的连通情况,此时HashMap可以用数组代替,可以提高查询性能

  • Node类
    包含从该点出发所指向的下一个点、以该点为起始点的有向边、该点的入度和出度

    public class Node {
        /**
         * in和out分别表示结点的入度和出度
         * nexts表示当前节点指向的下一节点
         * edges表示从当前节点出发的有向边
         */
        public int value;
        public int in;
        public int out;
        public ArrayList<Node> nexts;
        public ArrayList<Edge> edges;
    
        public Node(int data) {
            value = data;
            in = 0;
            out = 0;
            nexts = new ArrayList<>();
            edges = new ArrayList<>();
        }
    }
    
  • Edge类
    包含边的起始点、终止点、权重

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

二、图的宽度优先遍历BFS

  • 算法思想
    1. 利用队列实现
    2. 从源节点开始依次按照宽度进队列,然后弹出
    3. 每弹出一个点,把该节点所有没有进过队列的邻接点(利用HashSet判断)放入队列
    4. 直到队列变空
public class BFS {
    /**
     * 从node出发,进行宽度优先遍历
     */
    public static void bfs(Node node) {
        if (node == null) {
            return;
        }
        Queue<Node> queue = new LinkedList<>();
        // set用于记录已经遍历过的节点
        Set<Node> set = new HashSet<>();
        queue.add(node);
        set.add(node);
        while (!queue.isEmpty()) {
            Node cur = queue.poll();
            System.out.println(cur.value);
            for (Node next : cur.nexts) {
                if (!set.contains(next)) {
                    queue.add(next);
                    set.add(next);
                }
            }
        }
    }
}

三、图的深度优先遍历DFS

  • 算法思想
    1. 利用实现
    2. 从源节点开始把节点按照深度放入栈,然后弹出
    3. 每弹出一个点,就对该点的邻接点进行判断,找出第一个没有进过访问过的邻接点(利用HashSet判断),把该点和该邻接点依次放入队列,进行下一个点的判断。
    4. 直到栈变空
  • 整个过程中栈中节点的顺序就是深度优先遍历的顺序
public class DFS { 
    public static void dfs(Node node) {
        if (node == null) {
            return;
        }
        Stack<Node> stack = new Stack<>();
        Set<Node> set = new HashSet<>();
        stack.push(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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值