图的创建(五种创建方式)

备忘

文档前提

n = 图的节点数;m=图的边数;
{u,v,w} 分别为一条边的起点、终点、权值

1.邻接矩阵

临界矩阵创建图的方式比较适合边较多的情况,毕竟要开nn大小的空间。遍历由邻接矩阵构成的图,时间复杂度为O(nn),空间复杂度为O(n*n)。

定义:

int[][] map = new int[n][n]

建边:

map[u][v] = w

1.1构建图

 public void build(){
        //输入 节点数n 和 边的个数
        Scanner scanner = new Scanner(System.in);
        System.out.println("输入节点数:");
        int n = scanner.nextInt();       //节点数
        System.out.println("输入边数:");
        int m = scanner.nextInt();       //边数

        System.out.println("输入基本信息:");
        //初始化邻接矩阵
        arr = new int[n+1][n+1];

        visit = new int[n+1];

        Arrays.fill(visit,-1);

        for(int i = 0;i<m;i++){
           //切割数组
            String[] str = scanner.next().split(",");
             //System.out.println(Arrays.toString(str));

            int a = Integer.parseInt(str[0]);
            int b = Integer.parseInt(str[1]);
            int c = Integer.parseInt(str[2]);

            arr[a][b] = c;
            arr[b][a] = c; 
        }
    }

1.2遍历图

 public void dfs(int u){
        visit[u] = 1;
        for(int i  = 1;i<arr.length;i++){
            if(arr[u][i]!=0){
                System.out.println("起点:"+u+",终点:"+i+",权值:"+arr[u][i]);
            }
            //终点访问过 就不想下访问了
            if(visit[i] == 1){
                continue;
            }
            dfs(i);
        }
    }

2.边集数组

相比于临界矩阵,边界数组以边为出发点,构成以边为元素的数组,边的内部属性包括:起点、终点、权值。遍历由边集数组构成的图,时间复杂度为O(n*m),空间复杂度为O(m)。

定义:

class Edge{ int u;int v;int w}   
Edge[] edges= new Edge[m]

建边:

edges[i] = {u,v,w}

2.1构建图

public void build(){
        Scanner scanner = new Scanner(System.in);

        System.out.println("输入节点个数");
        int n = scanner.nextInt();
        System.out.println("输入边的个数");
        int m = scanner.nextInt();

        edges = new Edge[m];
        visit = new int[n+1];
        Arrays.fill(visit,-1);

        System.out.println("输入详细信息");

        for(int i = 0;i<m;i++){
            String[] split = scanner.next().split(",");
            int a = Integer.parseInt(split[0]);
            int b = Integer.parseInt(split[1]);
            int c = Integer.parseInt(split[2]);
            edges[i] = new Edge(a,b,c);
        }
    }

2.2遍历图

int[] visit = new int[n+1];
 public void dfs(int u){
        visit[u] = 1;
        for(int i = 0;i<edges.length;i++){
            if(edges[i].u == u){
                System.out.println("起点:"+edges[i].u+",终点:"+edges[i].v+",权值:"+edges[i].w);
                if(visit[edges[i].v]>0){
                    continue;
                }
                dfs(edges[i].v);
            }
        }
    }

3.邻接表

邻接表则考虑以图中的点作为下标构建list数组,以n1为下标的数组元素指向一个list对象,该对象中的属性为以n1为起点的边的终点、和该边的权值。遍历由邻接数组构成的图,时间复杂度为O(n+m),空间复杂度为O(n+m)。

定义:

class Edge{ int v;int w}   //定义边:终点、权值
 List<Edge>[] h = new LinkedList[n];

建边:

h[u].add(new Edge(v,w));  //新建边 并将边的引用 压入h[u]集合

3.1构建图

 public void build(){
        Scanner scanner = new Scanner(System.in);

        System.out.println("输入节点个数");
        int n = scanner.nextInt();
        System.out.println("输入边的个数");
        int m = scanner.nextInt();

        e = new LinkedList[n+1];
        for(int i = 0;i<n+1;i++){
            e[i] = new LinkedList<>();
        }

        for(int i = 0;i<m;i++){
            String[] strs = scanner.next().split(",");
            int a = Integer.parseInt(strs[0]);
            int b = Integer.parseInt(strs[1]);
            int c = Integer.parseInt(strs[2]);

            e[a].add(new Edge(b,c));
            e[b].add(new Edge(a,c));
        }

    }

3.2遍历图

//注意 这里没有考虑图中有环的情况,如需要请加入visited数组,判断

   public void dfs(int u,int fa){
        for(Edge child:e[u]){
            if(child.v==fa){
                continue;
            }
            System.out.println("起点:"+u+",终点:"+child.v+",权值:"+child.w);
            dfs(child.v,u);
        }
    }

4.链式邻接表

链式邻接表私以为可以看作邻接表的变种,将边的信息单独存储在的list集合中,不用之前的list来存储每个点的邻边,取而代之的是邻边在list集合中的索引。遍历由链式邻接表构成的图,时间复杂度为O(n+m),空间复杂度为O(n+m)

 class Edge{ int u,int v;int w}   //定义边 :起点、终点、权值
 List<Integer>[] h = new LinkedList[n];
 List<Edge> e = new LinekedList<>();

建边:

public void add(int u,int v,int w){
   e.add(new Edge(u,v,w));    //新建边 并压入 e集合
   h[u].add(e.size()-1);           //将新建立的 边的索引 压入h[u]集合(注意于邻接表区分)
}

4.1构建图

public void build(){
        Scanner scanner = new Scanner(System.in);

        //节点数量
        System.out.println("输入节点数量:");
        int n = scanner.nextInt();

        //边的数量
        System.out.println("输入边的数量:");
        int m = scanner.nextInt();


        e = new LinkedList<>();  //用来存放边
        h = new LinkedList[n+1]; //类似邻接表
        //初始化
        for(int i = 0;i<=n;i++){
            h[i] = new LinkedList<>();
        }

        System.out.println("输入边的数据");

        for(int i = 0;i<m;i++){
            String[] str = scanner.next().split(",");
            int a = Integer.parseInt(str[0]);
            int b = Integer.parseInt(str[1]);
            int c = Integer.parseInt(str[2]);

            add(a,b,c);
            add(b,a,c);
        }
    }

4.2遍历图

//注意 这里没有考虑图中有环的情况,如需要请加入visited数组,判断

public void dfs(int u,int fa){
        //遍历以u为起点的边
        for(int child:h[u]){
            Edge ee  = e.get(child);
            if(ee.v==fa){
                continue;
            }
            System.out.println("起点:"+u+",终点:"+ee.v+",权值:"+ee.w);
            dfs(ee.v,u);
        }
    }

5.链式前向星

链式前向星也是邻接表的变种,但相比于链式邻接表,这次不需要用list存储点的邻边的索引,而是直接拉一条链表存储,这就需要在边的定义中定义下一条边的索引,就像链表节点node中的next一样!遍历由链式前向星构成的图,时间复杂度为O(n+m),空间复杂度为O(n+m)。

定义

 class Edge{ int v;int w;int ne}   //定义边:终点、权值、下个边的索引
 int[] h = new int[n];
 Edge[] e = new Edge[m*2];  // 考虑无向边图,因此大小为m*2
 int ids = 0;  //为边数组的指针,始终指向待插入新数据的数组元素

建边:

public void add(int u,int v,int w){
   e[ids] = new Edge(v,w,h[u]);    //新建边 并压入 e集合
   h[u] = ids++;           //将新建立的 边的索引 压入h[u]集合(注意于邻接表区分)
}

5.1构建图

 public void build(){
        Scanner scanner = new Scanner(System.in);
        //
        System.out.println("输入节点数量:");
        int n = scanner.nextInt();

        System.out.println("输入边的数量:");
        int m = scanner.nextInt();

        e = new Edge[2*m];
        h = new int[n+1];
        //初始化h 每个下标代表一个节点 一开始节点不指向任何边 因此设为-1
        Arrays.fill(h,-1);

        ids = 0;

        for(int i = 0;i<m;i++){
            String[] str = scanner.next().split(",");
            int a = Integer.parseInt(str[0]);
            int b = Integer.parseInt(str[1]);
            int c = Integer.parseInt(str[2]);

            add(a,b,c);
            add(b,a,c);
        }
    }

5.2遍历图

//注意 这里没有考虑图中有环的情况,如需要请加入visited数组,判断


 public void dfs(int u,int fa){
        //遍历链表
        for(int i = h[u];i!=-1;i=e[i].ne){
            Edge ee = e[i];
            if(ee.v==fa){
                continue;
            }
            System.out.println("起点:"+u+",终点:"+ee.v+",权值:"+ee.w);
            dfs(ee.v,u);
        }

    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值