有向图—拓扑排序,Kosaraju算法

来源:互联网 发布:经济型酒店数据分析 编辑:程序博客网 时间:2024/04/25 11:49

有向图基本算法

  1. 对于有向图的结构,和无向图类似,甚至更简单,有疑问请留言。
    1>有向图的数据结构
package graphTheory;/**  * @author luoz   * @date 2016年9月19日 下午9:26:21 **/public class Digraph {    private final int V;    private int E;    private Bag<Integer>[] adj;    public Digraph(int V)    {        this.V = V;        this.E = 0;        adj = (Bag<Integer>[])new Bag[V];        for(int i = 0;i<V;i++)            adj[i] = new Bag<>();    }    public int V()    {        return V;    }    public int E()    {        return E;    }    public void addEdge(int v,int w)    {        adj[v].add(w);        E++;    }    public Iterable<Integer> adj(int v)    {        return adj[v];    }    public Digraph reverse()    {        Digraph g = new Digraph(V);        for(int j = 0; j<V;j++)            for(int w : adj[j])                g.addEdge(w,j);        return g;    }}
  1. 基于深度优先遍历的顶点排序
    1>前序:在递归调用之前将顶点加入队列;
    2>后序:在递归调用之后将顶点加入队列;
    3>逆后序:在递归调用之后将顶点压入栈;
package graphTheory;import java.util.*;import javax.management.Query;/**  * @author luoz   * @date 2016年9月19日 下午10:11:48 **/public class DepthFirstOrder {    private boolean[] marked;    //pre order    private Queue<Integer> pre;    //postorder    private Queue<Integer> post;    //reverse postorder    private Stack<Integer> repost;    public DepthFirstOrder(Digraph g)    {        marked = new boolean[g.V()];        pre = new LinkedList<>();        post =  new LinkedList<>();        repost = new Stack<>();        for(int i = 0;i<g.V();i++)            if(!marked[i])                dfs(g,i);    }    private void dfs(Digraph g,int v)    {        pre.add(v);        marked[v] = true;        for(int w : g.adj(v))            if(!marked[w])                dfs(g,w);        post.add(v);        repost.add(v);    }    public Iterable<Integer> pre()    {        return pre;    }    public Iterable<Integer> post()    {        return post;    }    public Iterable<Integer> reversepost() {        return repost;    }}
  1. 检测有无环
package graphTheory;import java.io.File;import java.util.Stack;/**  * @author  luoz   * @date 2016年9月19日 下午9:48:41 **/public class DirectedCycle {    private boolean[] marked;    private int[] edgeTo;    //All vertices of a directed loop    private Stack<Integer> cycle;    //resursion all vertices of the cycle     private boolean[] onStack;    private boolean marked(int v)    {        return marked[v];    }    public boolean hasCycle()    {        return cycle != null;    }    public DirectedCycle(Digraph g)    {        marked = new boolean[g.V()];        edgeTo = new int[g.V()];        onStack = new boolean[g.V()];        for(int i = 0;i<g.V();i++)            if(!marked[i])                dfs(g,i);    }    private void dfs(Digraph g,int v)    {        marked[v] = true;        onStack[v] = true;        for(int w : g.adj(v))        {            if(this.hasCycle())                return;            else if(!marked[w])            {                edgeTo[w] = v;                dfs(g,w);            }            else if(onStack[w])            {                cycle = new Stack<Integer>();                for(int i = v; i != w; i = edgeTo[i])                    cycle.push(i);                cycle.push(w);                cycle.push(v);            }            onStack[v] = false;        }           }    public Iterable<Integer> cycle()    {        return cycle;    }    /*测试代码,从文件中读取的,可以自己写测试代码*/    public static void main(String[] args) {        FileIo fileio = new FileIo();        String s = fileio.characterReader(new File("cycle.txt"));        String[] st = s.split(",");        Digraph g = new Digraph(13);        int E = st.length;        for(int i = 0;i<E;i++)        {            String[] str = st[i].split(" ");            g.addEdge(Integer.parseInt(str[0]),Integer.parseInt(str[1]));                   }        DirectedCycle cc = new DirectedCycle(g);        System.out.println(cc.hasCycle());        System.out.println(cc.cycle);    }}

拓扑排序

拓扑排序只针对有向无环图。
一幅有向无环图的拓扑排序,也就是所有顶点的逆后序排列。

package graphTheory;/**  * @author  luoz  * @date 2016年9月20日 上午8:30:05 **/public class Topological {    private Iterable<Integer> order;    public Topological(Digraph g)    {        DirectedCycle hascycle = new DirectedCycle(g);        if(!hascycle.hasCycle())        {            DepthFirstOrder df = new DepthFirstOrder(g);            order = df.reversepost();        }       }    public Iterable<Integer> order()    {        return order;    }}

Kosaraju算法

计算强连通分量的算法。
主要运用了图G的反转和顶点排序的逆后序。

package graphTheory;/**  * @author  luoz  * @date 2016年9月20日 上午9:08:53 **/public class KosarajuSCC {    private boolean[] marked;    private int[] id;    private int count;    public KosarajuSCC(Digraph g)    {        marked = new boolean[g.V()];        id = new int[g.V()];        //        DepthFirstOrder df = new DepthFirstOrder(g.reverse());         for(int i : df.reversepost())              if(!marked[i])            {                dfs(g,i);                count++;            }    }    private void dfs(Digraph g,int v)    {        marked[v] = true;        id[v] = count;        for(int w :g.adj(v))            if(!marked[w])                dfs(g,w);    }    public int count()    {        return count;    }    public boolean connected(int v,int w)    {        return id[v] == id[w];    }}

算法第四版

0 0
原创粉丝点击