Java实现邻接表表示无向图,并求连通分量数

问题描述

用邻接表表示无向图,并求无向图的连通分量数

输入

结点的数据,边的数据:包括这条边的数据如权值,邻接点域,指向下一条边的指针

输出

邻接表,连通分量的个数

存储结构

邻接表

算法的基本思想

用邻接表来表示图,图的构造方法中有两个参数,第一个为一维数组,包含结点的数据;第二个为二维数组,一共n行3列,行表示边数,前两列为边的相邻两个顶点,最后一列为边的权值等信息。构造过程经过一个双层for循环,第一层遍历结点,第二层遍历边的信息,判断边的相邻两个顶点是否与顶点集中的某个元素相等,相等则添加到该顶点的后面。求连通分量,此处没有通过一个新的数组记录某个点是否被访问,而是为结点类添加一个属性标明其是否被访问,先将所有的结点标记为未被访问,然后遍历每个结点,若结点未被访问,则将结点调用dfs深度遍历方法(调用过此方法的点都被标记为已访问过),每进行完一次dfs方法,计数器加一,最后返回计数器即为连通分量的个数。

源代码

public class Edge {
    int adjVex;
    int weight;
    Edge next;
}
class Vertex {
    int data;
    Edge edgeHead;
    boolean visited;
}
class Graph {
    Vertex[] vertices;
    int location(int[] vexs,int data){  //求adjvex (即邻接点的下标)
        for (int i = 0;i < vexs.length;i++){
            if (vexs[i] == data){
                return i;
            }
        }
        return -1;
    }
    public Graph(int[] vexs,int[][] edges) {
        //edges是一个n×3的数组,边的权值等于edges[i][2],edges[i][0]指向edges[i][1]
        vertices = new Vertex[vexs.length];
        for (int i = 0; i < vexs.length; i++) {
            vertices[i] = new Vertex();
            vertices[i].data = vexs[i];
            Edge cur = null;
            for (int[] edge : edges) {
                if (edge[0] == vexs[i]) {
                    if (vertices[i].edgeHead == null) {
                        vertices[i].edgeHead = new Edge();
                        vertices[i].edgeHead.adjVex = location(vexs,edge[1]);
                        vertices[i].edgeHead.weight = edge[2];
                        cur = vertices[i].edgeHead;
                    } else {
                        while (cur.next != null) cur = cur.next;
                        cur.next = new Edge();
                        cur = cur.next;
                        cur.adjVex = location(vexs,edge[1]);
                        cur.weight = edge[2];
                    }
                } else if (edge[1] == vexs[i]) {
                    if (vertices[i].edgeHead == null) {
                        vertices[i].edgeHead = new Edge();
                        vertices[i].edgeHead.adjVex = location(vexs,edge[0]);
                        vertices[i].edgeHead.weight = edge[2];
                        cur = vertices[i].edgeHead;
                    } else {
                        while (cur.next != null) cur = cur.next;
                        cur.next = new Edge();
                        cur = cur.next;
                        cur.adjVex = location(vexs,edge[0]);
                        cur.weight = edge[2];
                    }
                }
            }
        }
    }
    void dfs(Vertex vertex){
        if (!vertex.visited){
            vertex.visited = true;
            Edge edge = vertex.edgeHead;
            while (edge != null){
                if (!vertices[edge.adjVex].visited){
                    dfs(vertices[edge.adjVex]);
                }
                edge = edge.next;
            }
        }
    }
    int countComponent(){
        int count = 0;
        for (Vertex vertex : vertices) {
            vertex.visited = false;
        }
        for (Vertex vertex : vertices) {
            if (!vertex.visited) {
                dfs(vertex);
                count++;
            }
        }
        return count;
    }
    void printGraph(){
        for (Vertex vertex : vertices) {
            Edge e = vertex.edgeHead;
            System.out.print(vertex.data);
            while(e != null){
                System.out.print("--(" +e.weight+")-->"+vertices[e.adjVex].data);
                e = e.next;
            }
            System.out.println();
        }
    }
}
class Test {
    public static void main(String[] args) {
        int[] vexs = {1,2,3,4,5,6};
        int[][] edges = {{1,2,3},{1,4,5},{2,5,7},{3,6,9},{4,5,9}};
        Graph graph = new Graph(vexs,edges);
        graph.printGraph();
        System.out.println("连通分量的个数\t"+graph.countComponent());
    }
}

时间复杂度

关于深度优先的复杂度:DFS算法是一个递归算法,需要借助一个递归工作栈,遍历图的过程实际上是对每个顶点查找其邻接点的过程。当我们使用邻接表存储时,访问顶点为O(V),查找所有的顶点的邻接点的时间为O(E),所以,总的时间复杂度为O(V+E)

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值