构造无向图--邻接表--dfs与bfs遍历

/**
 * 无向图
 */
public class UndirectedGraph {

    private final int v;    //记录顶点数量
    private int e;  //记录边的数量
    private Queue<Integer>[] adj;   //邻接表

    public UndirectedGraph(int v){
        this.v = v;
        this.e = 0;
        this.adj = new Queue[v];
        for (int i = 0; i < adj.length; i++) {
            adj[i] = new LinkedList<Integer>();
        }
    }

    /**
     * 获取图中顶点的数量
     * @return
     */
    public int v(){
        return v;
    }

    /**
     * 获取图中边的数量
     * @return
     */
    public int e(){
        return e;
    }

    /**
     * 向图中添加一条边 v-w
     * 需要向v中加入w,也需要向w中加入v
     * @param v
     * @param w
     */
    public void addEdge(int v, int w){
        adj[v].add(w);  //向v邻接表中加入w
        adj[w].add(v); //向w邻接表中加入v
        e++;    //边+1
    }

    /**
     * 获取和顶点v相邻的所有顶点
     * @param v
     * @return
     */
    public Queue<Integer> adj(int v){
        return adj[v];
    }
}

使用dfs遍历无向图:

/**
 * 深度优先搜索
 */
public class DepthFirstSearch {

    private boolean[] visited;  //索引代表节点,值表示当前顶点是否已经被搜索过
    private int count;  //记录有多少顶点与s顶点相通

    /**
     * 构造深度优先搜索对象,使用深度优先搜索找出g图中与s顶点相通的所有顶点
     * @param g 图对象
     * @param s 顶点
     */
    public DepthFirstSearch(UndirectedGraph g, int s){
        this.visited = new boolean[g.v()];
        this.count = 0;
        dfs(g,s);
    }

    /**
     * 深度优先搜索找出图中与v顶点的所有相通顶点
     * @param g
     * @param v
     */
    private void dfs(UndirectedGraph g, int v){
        //标记v顶点已经被访问过
        visited[v] = true;
        //获取顶点v的所有相邻节点,进行递归调用
        LinkedList<Integer> adj = (LinkedList<Integer>) g.adj(v);
        for (int i = 0; i < adj.size(); i++) {
            //相邻节点未访问过,则dfs
            if(!visited[adj.get(i)]){
                dfs(g,adj.get(i));
            }
        }
        //相邻节点数量+1
        count++;
    }

    /**
     * 判断w顶点与顶点s是否相通
     * @param w
     * @return
     */
    public boolean isVisited(int w){
        return visited[w];
    }

    /**
     * 获取顶点s相通的所有顶点的总数
     * @return
     */
    public int count(){
        return this.count;
    }
}
测试:

在这里插入图片描述

public class DepthFirstSearchTest {
    public static void main(String[] args) {
        //构造有13个节点的无向图
        UndirectedGraph graph = new UndirectedGraph(13);
        graph.addEdge(0, 1);
        graph.addEdge(0, 2);
        graph.addEdge(0, 5);
        graph.addEdge(0, 6);
        graph.addEdge(5, 3);
        graph.addEdge(5, 4);
        graph.addEdge(3, 4);
        graph.addEdge(4, 6);

        graph.addEdge(7, 8);

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

        DepthFirstSearch search = new DepthFirstSearch(graph, 0);
        System.out.println("与节点0相通的节点个数:" + search.count());
        System.out.println("节点0和节点5是否相通:" + search.isVisited(5));
        System.out.println("节点0和节点7是否相通:" + search.isVisited(7));
        System.out.println("节点0和节点9是否相通:" + search.isVisited(9));
    }
}
使用bfs遍历无向图:
/**
 * 广度优先搜索
 */
public class BreadthFirstSearch {

    private boolean[] visited;  //索引代表顶点,值表示当前节点是否已经被搜索
    private int count;  //记录有多少个顶点与s顶点相通
    private Queue<Integer> waitSearch;  //用来存储待搜索邻接表的点

    //构造广度优先搜索对象,使用广度优先搜索找出图g中s顶点的所有相邻顶点
    public BreadthFirstSearch(UndirectedGraph g, int s){
        this.visited = new boolean[g.v()];
        this.count = 0;
        this.waitSearch = new LinkedList<Integer>();
        bfs(g,s);
    }

    //使用广度优先搜索找出图g中v顶点的所有相邻节点
    private void bfs(UndirectedGraph g, int v){
        visited[v] = true;
        waitSearch.add(v);
        while(!waitSearch.isEmpty()){
            Integer w = waitSearch.poll();  //出队
            //遍历w顶点的邻接表
            LinkedList<Integer> adj = (LinkedList<Integer>) g.adj(w);
            for (int i = 0; i < adj.size(); i++) {
                if(!visited[adj.get(i)]){
                    bfs(g,adj.get(i));
                }
            }
        }
        this.count++;
    }

    //判断顶点w是否与顶点s相通
    public boolean isVisited(int w){
        return visited[w];
    }

    //获取与顶点s相通的所有顶点的总数
    public int count(){
        return count;
    }
}
测试:
public class BreadthFirstSearchTest {
    public static void main(String[] args) {
        //构造有13个节点的无向图
        UndirectedGraph graph = new UndirectedGraph(13);
        graph.addEdge(0, 1);
        graph.addEdge(0, 2);
        graph.addEdge(0, 5);
        graph.addEdge(0, 6);
        graph.addEdge(5, 3);
        graph.addEdge(5, 4);
        graph.addEdge(3, 4);
        graph.addEdge(4, 6);

        graph.addEdge(7, 8);

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

        BreadthFirstSearch search = new BreadthFirstSearch(graph, 0);
        System.out.println("与节点0相通的节点个数:" + search.count());
        System.out.println("节点0和节点5是否相通:" + search.isVisited(5));
        System.out.println("节点0和节点7是否相通:" + search.isVisited(7));
        System.out.println("节点0和节点9是否相通:" + search.isVisited(9));
    }
}

练习:

在这里插入图片描述

public class Exercise_graph {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("trffic_project.txt")));
        //读取城市个数
        Integer cities = Integer.parseInt(br.readLine());
        //初始化图,并构建
        UndirectedGraph g = new UndirectedGraph(cities);
        //读取已修的道路数量及道路
        Integer has_road = Integer.parseInt(br.readLine());
        for (Integer i = 0; i < has_road; i++) {
            String line = br.readLine();
            String[] arr = line.split(" ");
            int v = Integer.parseInt(arr[0]);
            int w = Integer.parseInt(arr[1]);
            g.addEdge(v,w);
        }
        //构建深度优先搜索,搜索与9顶点相通的相邻节点
        DepthFirstSearch search = new DepthFirstSearch(g, 9);
        System.out.println("9号城市是否与10号城市相通:" + search.isVisited(10));
        System.out.println("9号城市是否与8号城市相通:" + search.isVisited(8));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值