图处理算法

深度优先搜索算法

思路

类似于走迷宫,走尽所有没有没走过的路。

java实现

public class DepthFirstSearch{
    private boolean[] marked;  //标记数组
    private int count;  //与s的连通总数

    public DepthFirstSearch(Graph G, int s){  //构造器
        marked = new boolean [G.V()];
        dfs(G, s);
    }

    //深度优先搜索递归算法
    private dfs(Graph G, int s){  
        marked[s]  = true;       //标记此节点
        count++;
        for(int w : G.adj(s)){   //访问s的相邻节点,看其是否被访问
            if(!marked[w]) dfs(G, w);
        }
    }

    //顶点是否被访问过
    boolean marked(int s){
        return marked[s];
    }

    //与s的相连的顶点总数
    public int count(){
        return count;
    }
}

深度搜索寻找路径

寻找路径只需要比上面的遍历算法多一个数组用来记录遍历的路径即可,在下面的实现中是 edgeTo[] 数组。

java实现

// difference的地方是和DepthFirstSearch不同的地方
public class DepthFirstPaths(){
    private boolean[] marked;  //标记数组
    private int count;  //与s的连通总数
    private int[] edgeTo; //从起点到一个顶点的路径// difference
    private final int s;// difference


    public DepthFirstSearch(Graph G, int s){  //构造器
        this.s = s;
        marked = new boolean [G.V()];
        edgeTo = new int[G.V()];
        dfs(G, s);
    }

    //深度优先搜索递归算法
    private dfs(Graph G, int s){  
        marked[s]  = true;       //标记此节点
        count++;
        for(int w : G.adj(s)){   //访问s的相邻节点,看其是否被访问
            if(!marked[w]){
                edgeTo[w] = s;  // difference
                dfs(G, w);
            }
        }
    }

    //顶点是否被访问过
    boolean marked(int s){
        return marked[s];
    }

    //与s的相连的顶点总数
    public int count(){
        return count;
    }

    //寻找路径
    //判断是否存在s到顶点v的路径
    public boolean hasPathTo(int v){  // difference
        return marked[v];
    }

    //找出s到v的路径
    public Iterable<Integer> pathTo(int v){   // difference
        if(!hasPathTo(v)) return null; //不存在路径,返回空
        Stack<Integer> path = new Stack<Integer>();
        for(int w = v; w != s; w = edgeTo[w]){
            path.push(w);
        }
        path.push(s);
        return path;
    }
}

广度优先搜索

思路

广度优先算法则是根据与起点的距离远近顺序来遍历所有顶点的。
- 取队列中的下一个顶点v并标记它;
- 将与v相邻的所有未被标记的顶点加入队列中。
实现时显式的调用队列,而不会像在深度搜索中那样隐式地调用栈。

java实现

public class BreadthFirstPaths{
    private boolean[] marked;
    private int[] edgeTo;  //按照距离存储点
    private final int s; //起点

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

    //广度搜索核心代码
    private void bfs(Graph G, int s){
        marked[s] = true;
        Queue<Integer> queue = new Queue<Integer>();
        queue.enqueue(s);
        while(!queue.isEmpty()){
            int v = queue.dequeue();   //从队列中删除下一顶点
            for(int w: G.adj(v)){
                if(!marked[w]){
                    edgeTo[w] = v;
                    marked[w] = true;
                    queue.enqueue(w);   //加入队列
                }
            }
        }
    }

    //寻找路径
    //判断是否存在s到顶点v的路径
    public boolean hasPathTo(int v) {  // difference
        return marked[v];
    }
    //找出s到v的路径
    public Iterable<Integer> pathTo(int v) {   // difference
        if (!hasPathTo(v)) return null; //不存在路径,返回空
        Stack<Integer> path = new Stack<Integer>();
        for (int w = v; w != s; w = edgeTo[w]) {
            path.push(w);
        }
        path.push(s);
        return path;
    }
}

深度搜索和广度搜索的比较

1、两者都是遵循下面的搜索步骤:
- 取其中的下一个顶点并标记它;
- 将v的所有顶点而又未被标记的顶点加入数据结构。
2、两者的区别就在于遍历时获取下一个点的规则不一样,深度优先搜索时,采用的递归,隐式的栈的LIFO;而广度优先搜索时,采用的显式的队列的调用,是FIFO。
3、深度优先搜索时总是先寻找离起点最远的点;而广度优先搜索则是总是找离起点最近的点。

github链接

要运行需要下载整个工程。
源码链接

你可能感兴趣的:(java,算法,搜索,图)