有向图

栏目: 数据库 · 发布时间: 7年前

内容简介:《Algorithm》(Sedgewick)笔记:有向图一幅有称一条有向边由第一个顶点

《Algorithm》(Sedgewick)笔记:有向图

术语

一幅有 方向性的图 (或 有向图 )是由一组 顶点 和一组 有方向的边 组成的,每条有方向的边都连接着有序的一对顶点。

称一条有向边由第一个顶点 指出指向 第二个顶点。

一个顶点的 出度 为由该顶点指出的边的总数,一个顶点的 入度 为指向该顶点的边的总数。

一条有向边的第一个顶点成为它的 ,第二个顶点称为它的

在一幅有向图中, 有向路径 由一系列顶点组成,对于其中的每个顶点都存在一条有向边从它指向序列中的下一个顶点。

有向环为一条至少含有一条边且起点和终点相同的有向路径。 简单有向环 是一条除了起点和终点必须相同之外,不含有重复的顶点和边的环。

路径或环的 长度 即为其中所包含的边数。

图示

有向图

表示

使用邻接表表示

有向图

数据类型

public class DiGraph {
    private 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 v = 0; v < V; v++)
            adj[v] = new Bag<>();
    }
    //输入初始化构造函数
    public DiGraph() {
        Scanner in = new Scanner(System.in);
        V = in.nextInt();
        adj = (Bag<Integer>[]) new Bag[V];
        for (int v = 0; v < V; v++)
            adj[v] = new Bag<Integer>();
        int e = in.nextInt();
        for (int i = 0; i < e; i++) {
            int v = in.nextInt();
            int w = in.nextInt();
            addEdge(v, w);
        }
    }
    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 R = new DiGraph(V);
        for (int v = 0; v < V; v++)
            for (int w : adj[v])
                R.addEdge(w, v);
        return R;
    }
    public String toString() {
        String s = V + " vertices, " + E + " edges\n";
        for (int v = 0; v < V; v++) {
            s += v + ": ";
            for (int w : this.adj[v])
                s += w + " ";
            s += "\n";
        }
        return s;
    }
}

源代码

https://github.com/XutongLi/Algorithm-Learn/tree/master/src/S4_Graphs/S4_2_Directed_Graph/S4_2_2_DiGraph

有向图的深度优先搜索

图示

有向图

使用

使用DFS可以检测有向图的可达性,即解决“是否存在一条从s到达给定顶点v的有向路径”或“是否存在一条从结合中的任意顶点到达给定顶点v的有向路径”等问题。

递归代码

public class DiDFS {
    private boolean[] marked;
      //单源
    public DiDFS(DiGraph G, int s) {
        marked = new boolean[G.V()];
        dfs(G, s);
    }
      //多源
    public DiDFS(DiGraph G, Iterable<Integer> sources) {
        marked = new boolean[G.V()];
        for (int s : sources)
            if (!marked[s]) dfs(G, s);
    }
    private void dfs(DiGraph G, int v) {
        marked[v] = true;
        for (int w : G.adj(v))
            if (!marked[w]) dfs(G, w);
    }
    public boolean marked(int v) {
        return marked[v];
    }
}

非递归代码

public class DiDFS_Nonrecur {
    private boolean[] marked;

    public DiDFS_Nonrecur(DiGraph G, int s) {
        marked = new boolean[G.V()];
        Iterator<Integer>[] adj = (Iterator<Integer>[]) new Iterator[G.V()];
        for (int v = 0; v < G.V(); v++) {
            adj[v] = G.adj(v).iterator();
        }
        Stack<Integer> stack = new Stack<>();
        marked[s] = true;
        stack.push(s);
        while (!stack.isEmpty()) {
            int v = stack.peek();
            if (adj[v].hasNext()) {
                int w = adj[v].next();
                if (!marked[w]) {
                    marked[w] = true;
                    stack.push(w);
                }
            }
            else {
                stack.pop();
            }
        }
    }

    public DiDFS_Nonrecur(DiGraph G,Iterable<Integer> sources) {
        marked = new boolean[G.V()];
        Iterator<Integer>[] adj = (Iterator<Integer>[]) new Iterator[G.V()];
        for (int v = 0; v < G.V(); v++) {
            adj[v] = G.adj(v).iterator();
        }
        for (int s : sources) {
            Stack<Integer> stack = new Stack<>();
            marked[s] = true;
            stack.push(s);
            while (!stack.isEmpty()) {
                int v = stack.peek();
                if (adj[v].hasNext()) {
                    int w = adj[v].next();
                    if (!marked[w]) {
                        marked[w] = true;
                        stack.push(w);
                    }
                }
                else {
                    stack.pop();
                }
            }
        }
    }

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

源代码

https://github.com/XutongLi/Algorithm-Learn/tree/master/src/S4_Graphs/S4_2_Directed_Graph/S4_2_3_DiDFS

深度优先搜索路径

代码

public class DiDFSPath {
    private boolean[] marked;
    private int[] edgeTo;
    private int s;

    public DiDFSPath(DiGraph G, int s) {
        marked = new boolean[G.V()];
        edgeTo = new int[G.V()];
        this.s = s;
        dfs(G, s);
    }
    private void dfs(DiGraph G, int v) {
        marked[v] = true;
        for (int 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> stack = new Stack<>();
        for (int x = v; x != s; x = edgeTo[x]) {
            stack.push(x);
        }
        stack.push(s);
        Queue<Integer> queue = new LinkedList<>();
        while (!stack.isEmpty()) {
            queue.offer(stack.pop());
        }
        return queue;
    }
}

源代码

https://github.com/XutongLi/Algorithm-Learn/tree/master/src/S4_Graphs/S4_2_Directed_Graph/S4_2_3_DiDFSPath

广度优先搜索路径

代码

public class DiBFSPath {
    private final int INFINITY = Integer.MAX_VALUE;
    private boolean[] marked;
    private int [] edgeTo;
    private int[] distTo;
    private int s;

    public DiBFSPath(DiGraph G, int s) {
        marked = new boolean[G.V()];
        edgeTo = new int[G.V()];
        distTo = new int[G.V()];
        this.s = s;
        for (int v = 0; v < G.V(); v++) {
            distTo[v] = INFINITY;
        }
        bfs(G, s);
    }
    private void bfs(DiGraph G, int s) {
        Queue<Integer> q = new LinkedList<>();
        q.offer(s);
        marked[s] = true;
        distTo[s] = 0;
        while (!q.isEmpty()) {
            int v = q.poll();
            for (int w : G.adj(v)) {
                if (!marked[w]) {
                    marked[w] = true;
                    distTo[w] = distTo[v] + 1;
                    edgeTo[w] = v;
                    q.offer(w);
                }
            }
        }
    }
    public boolean hasPathTo(int v) {
        return marked[v];
    }
    public int distTo(int v) {
        return distTo[v];
    }
    public Iterable<Integer> pathTo(int v) {
        if (!hasPathTo(v))   return null;
        Stack<Integer> stack = new Stack<>();
        for (int x = v; x != s; x = edgeTo[x]) {
            stack.push(x);
        }
        stack.push(s);
        Queue<Integer> queue = new LinkedList<>();
        while (!stack.isEmpty()) {
            queue.offer(stack.pop());
        }
        return queue;
    }
}

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Web站点优化

Web站点优化

金 / 2009-10 / 55.00元

《Web站点优化》为您提供有效的策略以及精准的技术,让您的网站吸引更多用户,并成功地将他们都转换为最终的购买者。这绝对是现在网络营销成功之路上的指明灯!几年前,所谓“优化过”的网站不过是指加载速度快、兼容绝大多数浏览器而已。而现在,为了提升商业竞争力,网站优化需要做的远不止这些:它需要吸引客户、与客户交互以及说服客户等。 《Web站点优化》就为您提供了众多来自首席专家们的意见,囊括了在线营销......一起来看看 《Web站点优化》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具