《算法》——广度优先搜索与找寻找路径

单点路径问题在图的处理领域中十分重要,从输入流中读取一个图从从命令行得到一个起点,然后打印从起点到与它连通的每个顶点之间的一条路径。

深度优先找路径

下面扩展了尝试优先搜索代码,添加一一个实例变量edgeTo[]整型数组来起到Tremaux搜索中绳子的作用,这个数组可以找到从每个与s连通的顶点回到s的路径。它会记住每个顶点到起点的路径,而不是记录当前顶点到起点的路径

代码

package algorithm.graph.gopath;


import algorithm.graph.Graph;

import java.util.Stack;

/**
 * 描述:深度优先找打通的路径
 * Created by zjw on 2021/7/25 13:13
 */
public class DepthFirstPaths {
    private boolean[] marked; //这个顶点上调用过dfs()了吗?
    private int[] edgeTo;
    private final int s;

    public DepthFirstPaths(Graph G, int s) {
        marked = new boolean[G.V()];
        edgeTo = new int[G.V()];
        this.s = s;
        dfs(G, s);
    }

    private void dfs(Graph G, int v) {
        marked[v] = true;
        for (Integer w : G.adj(v)) {
            if (!marked[w]) {
                edgeTo[w] = v;
                dfs(G, w);
            }
        }
    }

    public boolean hasPathTo(int v) {
        return marked[v];
    }

    public Iterable<Integer> pathTo(int v) {
        if (!hasPathTo(v)) return null;
        Stack<Integer> path = new Stack<Integer>();
        for (int x = v; x !=s ; x=edgeTo[x]) path.push(x);
        path.push(s);
        return path;
    }
}

广度优先找路径

使用队列来保存所有已经被标记过但其邻接表还未被检查过的顶点,先将起点加入队列,然后重复以下步骤直到队列为空;

  • 取队列中的下一个顶点v并标记它
  • 将与v相邻的所有未被标记过的顶点加入队列

代码

package algorithm.graph.gopath;

import algorithm.graph.Graph;

import java.util.Stack;

/**
 * 描述:广度优先
 * Created by zjw on 2021/7/25 13:26
 */
public class BreadthFirstPaths {
    private boolean[] marked; //到达该顶点的最短路径已知吗
    private int[] edgeTo; //到达该顶点的已知路径上的最后一个顶点
    private final int s; //起点

    public BreadthFirstPaths(Graph G, int s) {
        marked = new boolean[G.V()];
        edgeTo = new int[G.V()];
        this.s = s;
        bfs(G, s);
    }

    public void bfs(Graph G, int s) {
        Queue<Integer> queue = new Queue<Integer>();
        marked[s] = true; //标记起点
        queue.enqueue(s);
        while (!queue.isEmpty()) {
            int v = queue.dequeue();//从队列中删去下一顶点
            for (Integer w : G.adj(v)) {
                if (!marked[w]) { // 每个未被标记的相邻顶点
                    edgeTo[w] = v; //保存
                    marked[w] = true;
                    queue.enqueue(w);
                }
            }
        }
    }

    public boolean hasPathTo(int v) {
        return marked[v];
    }

    public Iterable<Integer> pathTo(int v) {
        if (!hasPathTo(v)) return null;
        Stack<Integer> path = new Stack<Integer>();
        for (int x = v; x !=s ; x=edgeTo[x]) path.push(x);
        path.push(s);
        return path;
    }

    class Queue<Item> {

        private class Node{
            private Item item;
            private Queue.Node next;
        }

        private Queue.Node first;
        private Queue.Node last;
        int N = 0;

        private boolean isEmpty() {
            return N == 0;
        }

        public int size() {
            return N;
        }

        //�����
        public void enqueue(Item item) {
            Queue.Node node = new Queue.Node();
            node.item = item;
            node.next = null;
            if (isEmpty()) {
                last = node;
                first = node;
            } else {
                last.next = node;
                last = node;
            }
            N++;
        }

        //������
        public Item dequeue() {
            Node node = first;
            first = first.next;
            N--;
            return node.item;
        }

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值