无向图的深度优先搜索

学到无向图了,有点难度但是能克服。代码看的很慢,但是不方,任何人想变成大神都不可能一蹴而就,都是经过不懈的努力,一点一点积累起来的。所以,加油啦!
手写了一遍无向图的相关内容,为了方便复习,注释写的很详细。记录在此。

无向图Graph基类

import java.util.Arrays;

/**
 * Created by eminem on 16-12-5.
 */
//p336 Graph数据类型

/***图文件的第一行的数字是图中数的范围
 * 图文件的第二行的数字是图文件中的数字的对数,也是边数
 ***/

public class Graph {

    //顶点数目 vertices
    private final int V;
    //边数目 Edge
    private int E;
    //邻接表
    private Bag<Integer>[] adj;


    //这个构造函数用来创建邻接表
    public Graph(int V) {
        this.V = V;
        adj = (Bag<Integer>[]) new Bag[V];
        //Arrays.fill(adj, new Bag<Integer>());
        for (int i = 0; i < V; i++) {
            adj[i] = new Bag<Integer>();
        }
    }

    //这个构造函数用来读取图,并向邻接表内存储数据
    public Graph(In in) {
        this(in.readInt());
        E = in.readInt();
        for (int i = 0; i < E; i++) {
            //添加一条边
            int v = in.readInt();
            int w = in.readInt();
            addEdge(v, w);
        }
    }

    public int V() {
        return V;
    }

    public int E() {
        return E;
    }


    public void addEdge(int v, int w) {
        adj[v].add(w);
        adj[w].add(v);
        //E++;
    }


    //adj返回的是数组的一个元素,这个元素的索引v是图的某个顶点。
    // 而这个元素本身是一个Bag类型,Bag里面存放了和这个节点相邻的那些顶点
    //即adj返回的是某顶点v的相邻顶点
    public Iterable<Integer> adj(int v) {
        return adj[v];
    }


    //最后的结果类似于 1:2 3 "\n" 4:5 6"\n"7:8 9"\n"10: 11 12
    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;
    }


}

无向图的常用操作工具:

/**
 * Created by eminem on 16-12-5.
 */
public class GraphHandle {

    public static int degree(Graph G,int v){
        int degree=0;
        for(int fuck:G.adj(v)){
            degree++;
        }
        return degree;
    }

    public static int maxDegree(Graph G){
        int max=0;
        int V=G.V();

        for (int i = 0; i <V ; i++) {
            int fuck=degree(G,V);
            if(fuck>max){
                max=fuck;
            }
        }
        return max;
    }

    public static double avgDegree(Graph G){
        return 2.0*G.E()/G.V();
    }

    //检查自环
    public static int numberOfSelfLoop(Graph G){
        int count=0;
        for(int v=0;v<G.V();v++){
            //迭代和v(v是小于范围V的数字,它是图的顶点)相邻的每一个顶点fuck
            for(int fuck:G.adj(v)){
                //如果发现fuck和v相等
                if(fuck==v){
                    count++;
                }
            }
        }
        return count/2;
    }
}

无向图的深度优先搜索:

import java.util.*;

/**
 * Created by eminem on 16-12-6.
 */
public class DepthFirstSearch {
    //这个顶点调用过dfs()了吗
    private boolean[] marked;

    //从起点到一个顶点的已知路径上的最后一个顶点
    private int[] edgeTo;

    //起点
    private final int s;

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

    }

    /**
     * 函数功能:
     * 修改marked[],使marked可以被用来判断某顶点是否被访问过
     * 修改edgeTo[],使其记录连接某顶点的“上一个”顶点
     **/
    private void dfs(Graph G, int v) {
        marked[v] = true;
        //G.adj(v)返回的是和v连通的所有顶点的一个迭代器
        for (int w : G.adj(v)) {
            //对于每一个w,凡是被访问过的,marked[w]都为true
            //如果没有标记,说明还未被访问,就会去执行if()内的内容
            if (!marked[w]) {
                //如果已经访问过了,比如a-v,v第一次被a访问,edgeTo[v]==a,那么c-v时则不会执行if里的内容,不会执行edgeTo[v]=c
                //若还没有被访问,那么这次就要访问了
                // 则edgeTo[w]被写入从起点到该顶点w已知路径的最后一条边 s...w-v,用v来表示
                edgeTo[w] = v;
                //递归地去处理w这个顶点,因为也有一些顶点和w连接,adj(w)同样会返回和w连接的顶点的迭代器
                dfs(G, w);
            }
        }
    }

    public boolean hasPathTo(int v) {
        //只要被访问过,就说明对于顶点v来说有路径通向起点s
        return marked[v];
    }

        //返回起点s到v的路径,s已经在初始化DepthFirstSearch时指定了
    public Iterable<Integer> pathTo(int v) {

        //若没有路径通向起点s,则返回null
        if (!hasPathTo(v)) {
            return null;
        }

        Stack<Integer> fuck = new Stack<Integer>();

        //从某顶点v开始向前访问,没访问一次就改变x的值,并把压入栈中
        // 直到访问到顶点s为止
        for (int x = v; x != s; x = edgeTo[x]) {
            fuck.push(x);
        }

        //最后把顶点s压入栈中
        fuck.push(s);

        return fuck;

    }


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值