欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

无向图

程序员文章站 2022-03-12 09:53:30
...

1、术语

连通图 / 非连通图无环图

子图:由一幅图的所有边的一个子集(以及它们所依附的所有顶点)组成的图

无环 连通
生成树:连通图的子图,他含有图中的所有顶点且是一棵


2、无向图的数据结构

图的基本操作API

第二个构造函数的输入由 2E+2 个整数组成:首先是V(顶点数),然后是E(边数),再然后是由整数对构成的边
无向图

图的数据结构

非稠密图的标准表示为邻接表,它将每个顶点的所有相邻顶点都保存在该顶点对应的元素所指向的一张链表中。
注意,边的插入顺序决定了Graph的邻接表中顶点的出现顺序。输入的第一个相邻顶点在链表中排在最后。

这里使用Bag抽象数据类型来实现这个链表。如果需要扩展功能(如:添加删除顶点或边、检验一条边是否存在),则 可以用 符号表(ST) 或 SET 代替 Bag。
无向图

/*Graph数据类型*/
public class Graph{
    private final int V;    //顶点数目
    private int E;          //边的数目
    private Bag<Integer>[] adj; //邻接表

    public Graph(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<Integer>();
        }
    }

    public Graph(In in){
        this(in.readInt());      //读取V并将图初始化
        int E = in.readInt();    //读取E
        for(int i = 0;i < E; i++){
            int v = in.readInt();
            int w = in.readInt();
            addEdge(v, w);       //添加一条连接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++;
    }
    public Iteralbe<Integer> adj(int v){
        return adj[v];
    }

    /*图的邻接表的字符串表示*/
    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;
    }
}

最常用的图处理代码

/*计算v的度数*/
public static int degree(Graph G, int v){
    int degree = 0;
    for (int w : G.adj(v)) degree++;
    return degree;
}
/*计算所有顶点的最大度数*/
public static int maxDegree(Graph G){
    int max = 0;
    for (int v = 0; v < G.V(); v++){
        if (degree(G, v) > max)
            max = degree(G, v);
   }
}

/*计算所有顶点的平均度数*/
public static double avgDegree(Graph G){
   return 2.0*G.E()/G.V();
}
/*计算自环的个数*/
public static int numberOfSelfLoops(Graph G){
    int count = 0;
    for (int v = 0; v < G.V(); v++){
        for(int w : G.adj(v)){
            if (v == w)    count++;
       }
   }
    return count/2;   //每条边都被记过两次
}