其他分享
首页 > 其他分享> > 图(1)--图的表示和搜索

图(1)--图的表示和搜索

作者:互联网

一、图的概念

 

二、图的表示

package 图;


import java.util.LinkedList;
import java.util.Queue;

public class Graph1 {
    private int V; //顶点数
    private int E;//边数
    private Queue<Integer>[] adj;//邻接表

    public Graph1(int V) {
        this.V = V;
        this.E = 0;
        this.adj = new Queue[V];
        for (int i = 0; i < V; i++) {
            adj[i] = new LinkedList<Integer>();
        }
    }

    //获取顶点数
    public int getV() {
        return V;
    }

    //获取边数
    public int getE() {
        return E;
    }


    //向图中添加一条边 v-w
    public void addEdge(int v, int w) {
         /*
        在无向图中,边是没有方向的,所以该边既可以说是从v到w的边,
        又可以说是从w到v的边,因此,需要让w出现在v的邻接表中,并且还要让v出现在w的邻接表中
        */
        adj[v].offer(w);
        adj[w].offer(v);
        E++;
    }
//向图中添加一条边 v-w,方法重载 public void addEdge(int... Edges){ if(Edges.length%2==0){ for (int i = 0; i <Edges.length ; i+=2) { addEdge(Edges[i],Edges[i+1]); } }else throw new IllegalStateException("顶点数必须为2的整数倍"); } // 获取和V相邻的所有节点 public Queue<Integer> adj(int V) { return adj[V]; } // 打印节点 @Override public String toString() { StringBuilder s = new StringBuilder("(" + V + " vertices, " + E + " edges)\n"); for (int v = 0; v < V; v++) { s.append(v).append(": "); for (int w : this.adj(v)) { s.append(w).append(" "); } s.append("\n"); } return s.toString(); } public static void main(String[] args) { Graph1 g = new Graph1(13); g.addEdge(0,1,0,2,0,6,0,5,3,5,3,4,4,5,6,4,7,8,9,10,9,11,9,12,11,12); System.out.println(g); //构建图 } }

 

三、深度优先搜索

深度优先搜索:要搜索一幅图,只需要一个递归方法来遍历所有顶点。在访问其中一个节点时将它标记为已访问,并递归的访问它的所有没有被标记过的邻居顶点。

在搜索时,如果遇到一个结点既有子结点,又有兄弟结点,那么先找子结点,然后找兄弟结点。常用于连通分量的判断

package 图;

import java.util.Stack;

public class DepthFirstPaths {
    private Graph1 graph;
    private int s;//起点
    private int[] edgeTo;//从起点到一个顶点的已知路径上的最后一个顶点
    private boolean[] visited;//标记已访问过的顶点

    public DepthFirstPaths(Graph1 graph, int s) {
        this.graph = graph;
        this.s = s;
        this.edgeTo=new int[graph.getV()];
        visited=new boolean[graph.getV()];
        dfs(graph,s);
    }
    //    深度优先搜索
    public void dfs(Graph1 graph, int s) {
       visited[s]=true;
        for (Integer v : graph.adj(s)) {
            if(!visited[v]){
                edgeTo[v]=s;
                dfs(graph,v);
            }
        }
    }

//    是否存在路径
    public boolean hasPathTo(int v){
       return visited[v];
    }
    //    存在起点到终点的路径
    public Iterable<Integer> pathTo(int v){
        if(!hasPathTo(v))return null;
        Stack<Integer> path=new Stack<>();
        for (int x = v; x!=s ; x=edgeTo[x]) {
            path.push(x);
        }
        path.push(s);
        return path;
    }
    public static void main(String[] args) {

        //准备Graph对象
        Graph1 G = new Graph1(13);
        G.addEdge(0,1);
        G.addEdge(0,2);
        G.addEdge(0,6);
        G.addEdge(0,5);
        G.addEdge(5,3);
        G.addEdge(5,4);
        G.addEdge(3,4);
        G.addEdge(4,6);
        G.addEdge(7,8);

        G.addEdge(9,11);
        G.addEdge(9,10);
        G.addEdge(9,12);
        G.addEdge(11,12);

        System.out.println(G);
        System.out.println("----------");
        DepthFirstPaths paths = new DepthFirstPaths(G, 0);
        Iterable<Integer> iterable = paths.pathTo(3);
        for (Integer integer : iterable) {
            System.out.print(integer+"--");
        }
    }
}

四、广度优先搜索

广度优先搜索:求单点最短路径常用的经典方法,可以用于求间隔的度数。

在搜索时,如果遇到一个结点既有子结点,又有兄弟结点,那么先找兄弟结点,然后找子结点。

package 图;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

public class BreadthFirstPaths {
    private Graph1 graph;
    private int s;//起点
    private int[] edgeTo;//从起点到一个顶点的已知路径上的最后一个顶点
    private boolean[] visited;//标记已访问过的顶点

    public BreadthFirstPaths(Graph1 graph, int s) {
        this.graph = graph;
        this.s = s;
        this.edgeTo=new int[graph.getV()];
        visited=new boolean[graph.getV()];
        bfs(graph,s);
    }
    //    广度优先搜索,找到的一定是最短的路径,但并不一定是唯一的最短路径
    public void bfs(Graph1 graph, int s) {
        Queue<Integer> queue = new LinkedList<>();
        visited[s]=true; //标记起点
        queue.offer(s); //加入队列
        while (!queue.isEmpty()){
            Integer w = queue.poll();  //取出邻接的一个顶点
            for (Integer v : graph.adj(w)) {  //获取该顶点的邻接节点
                if(!visited[v]){//如果没有被访问,就标记边,并入队
                    edgeTo[v]=w;
                    visited[v]=true;
                    queue.offer(v);
                }
            }
            }
        }
    //    是否存在路径
    public boolean hasPathTo(int v){
        return visited[v];
    }
    //    存在起点到终点的路径
    public Iterable<Integer> pathTo(int v){
        if(!hasPathTo(v))return null;
        Stack<Integer> path=new Stack<>();
        for (int x = v; x!=s ; x=edgeTo[x]) {
            path.push(x);
        }
        path.push(s);
        return path;
    }  public static void main(String[] args) {

        //准备Graph对象
        Graph1 G = new Graph1(13);
        G.addEdge(0,1);
        G.addEdge(0,2);
        G.addEdge(0,6);
        G.addEdge(0,5);
        G.addEdge(5,3);
        G.addEdge(5,4);
        G.addEdge(3,4);
        G.addEdge(4,6);
        G.addEdge(7,8);

        G.addEdge(9,11);
        G.addEdge(9,10);
        G.addEdge(9,12);
        G.addEdge(11,12);

        System.out.println(G);
        System.out.println("----------");
        BreadthFirstPaths paths = new BreadthFirstPaths(G, 0);
        Iterable<Integer> iterable = paths.pathTo(4);
        for (Integer integer : iterable) {
            System.out.print(integer+"--");
        }
    }
}

 

标签:表示,--,graph,public,int,搜索,顶点,adj,addEdge
来源: https://www.cnblogs.com/forever-fate/p/15772818.html