图论01-【无权无向】-图的基本表示-邻接矩阵/邻接表

文章目录

  • [1. 代码仓库](#1. 代码仓库)
  • [2. 图的基本表示的比较](#2. 图的基本表示的比较)
  • [3. 邻接矩阵:Array和TreeSet](#3. 邻接矩阵:Array和TreeSet)
    • [3.1 图示](#3.1 图示)
    • [3.2 Array主要代码解析](#3.2 Array主要代码解析)
    • [3.3 测试输出](#3.3 测试输出)
    • [3.4 使用TreeSet的代码](#3.4 使用TreeSet的代码)
  • [4. 邻接表:LinkedList](#4. 邻接表:LinkedList)
    • [4.1 图示](#4.1 图示)
    • [4.2 LinkedList主要代码解析](#4.2 LinkedList主要代码解析)
    • [4.3 测试输出](#4.3 测试输出)
  • [5. 完整代码](#5. 完整代码)
    • [5.1 邻接表 - Array](#5.1 邻接表 - Array)
    • [5.2 邻接表-TreeSet](#5.2 邻接表-TreeSet)
    • [5.3 邻接矩阵-LinkedList](#5.3 邻接矩阵-LinkedList)
    • [5.4 输入文件](#5.4 输入文件)

1. 代码仓库

https://github.com/Chufeng-Jiang/Graph-Theory/tree/main/src/Chapt01_Adjacency

2. 图的基本表示的比较

3. 邻接矩阵:Array和TreeSet

3.1 图示

3.2 Array主要代码解析

代码有删减

java 复制代码
public AdjMatrix(String filename){
    File file = new File(filename);
    try(Scanner scanner = new Scanner(file)){       
        V = scanner.nextInt(); //读取第一行第一个数,代表图中的顶点数
        
        //构造邻接矩阵
        adj = new int[V][V]; 
        E = scanner.nextInt(); //读取第一行第二个数,代表图中边的数量
        
        // E是边的数量,在g.txt中表示为第二行开始的E行
        for (int i = 0; i < E; i++) {
            int a = scanner.nextInt(); //读取边的一个顶点
            int b = scanner.nextInt(); //读取边的另一个顶点

            adj[a][b] = 1; //存在边则设置为1
            adj[b][a] = 1;
        }
    }
}

3.3 测试输出

3.4 使用TreeSet的代码

代码有删减
只需要改动一行

adj = new TreeSet[V]; //构造邻接表, V行,V个LinkedList

4. 邻接表:LinkedList

4.1 图示

4.2 LinkedList主要代码解析

代码有删减

java 复制代码
public class AdjList {
    private int V;
    private int E;
    private LinkedList<Integer>[] adj;

    public AdjList(String filename){
        File file = new File(filename);
        try(Scanner scanner = new Scanner(file)){
            V = scanner.nextInt();
            
            /*构造邻接表, V行,V个LinkedList*/
            adj = new LinkedList[V]; 
            for (int i = 0; i < V; i++) {
               adj[i] = new LinkedList<Integer>();
            }

            E = scanner.nextInt(); //读取第一行第二个数

            // E是边的数量,在g.txt中表示为第二行开始的E行
            for (int i = 0; i < E; i++) {
                int a = scanner.nextInt(); //读取边的一个顶点
                int b = scanner.nextInt(); //读取边的另一个顶点
                adj[a].add(b);
                adj[b].add(a);
            }
        }
    }

4.3 测试输出

5. 完整代码

5.1 邻接表 - Array

java 复制代码
package Chapt01_Adjacency;

import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.Scanner;


public class AdjList {
    private int V;
    private int E;
    private LinkedList<Integer>[] adj;

    public AdjList(String filename){
        File file = new File(filename);
        try(Scanner scanner = new Scanner(file)){
            V = scanner.nextInt();
            if(V < 0) throw new IllegalArgumentException("V must be non-negative");

            adj = new LinkedList[V]; //构造邻接表, V行,V个LinkedList
            for (int i = 0; i < V; i++) {
               adj[i] = new LinkedList<Integer>();
            }

            E = scanner.nextInt(); //读取第一行第二个数
            if(E < 0) throw new IllegalArgumentException("E must be non-negative");

            // E是边的数量,在g.txt中表示为第二行开始的E行
            for (int i = 0; i < E; i++) {
                int a = scanner.nextInt(); //读取边的一个顶点
                validateVertex(a);
                int b = scanner.nextInt(); //读取边的另一个顶点
                validateVertex(b);

                if(a == b) throw new IllegalArgumentException("Self Loop is Detected"); //判断是够存在自环边
                if(adj[a].contains(b)) throw new IllegalArgumentException("Parallel Edges are Detected"); //判断是够存在平行l边

                adj[a].add(b);
                adj[b].add(a);
            }
        }
        catch (IOException e){
            e.printStackTrace();
        }
    }

    private void validateVertex(int v){
        if(v < 0 || v >= V)
            throw new IllegalArgumentException("vertex" + v + "is invalid");
    }

    public int V(){
        return V;
    }

    public int E(){
        return E;
    }

    public boolean hasEdge(int v, int w){
        validateVertex(v);
        validateVertex(w);
        return adj[v].contains(w);
    }

    public LinkedList<Integer> adj(int v){
        validateVertex(v);
        return adj[v];
    }

    public int degree(int v){
        return adj(v).size();
    }

    @Override
    public String toString(){
        StringBuilder sb = new StringBuilder();
        sb.append(String.format("V = %d, E = %d\n", V, E));

        for (int i = 0; i < V; i++) {
            sb.append(String.format("%d:",i));
            for (int w: adj[i]) {
                sb.append(String.format("%d ",w));
            }
            sb.append('\n');
        }
        return sb.toString();
    }

    public static void main(String[] args){
        AdjList adjList = new AdjList("g1.txt"); //新建邻接矩阵,并从文件内容初始化
        System.out.println(adjList);
    }
}

5.2 邻接表-TreeSet

java 复制代码
package Chapt01_Adjacency;

import java.io.File;
import java.io.IOException;
import java.util.Scanner;
import java.util.TreeSet;

public class AdjSet {
    private int V;
    private int E;
    private TreeSet<Integer>[] adj;

    public AdjSet(String filename){
        File file = new File(filename);
        try(Scanner scanner = new Scanner(file)){
            V = scanner.nextInt();
            if(V < 0) throw new IllegalArgumentException("V must be non-negative");
            adj = new TreeSet[V]; //构造邻接表, V行,V个LinkedList
            for (int i = 0; i < V; i++) {
               adj[i] = new TreeSet<Integer>();
            }

            E = scanner.nextInt(); //读取第一行第二个数
            if(E < 0) throw new IllegalArgumentException("E must be non-negative");

            // E是边的数量,在g.txt中表示为第二行开始的E行
            for (int i = 0; i < E; i++) {
                int a = scanner.nextInt(); //读取边的一个顶点
                validateVertex(a);
                int b = scanner.nextInt(); //读取边的另一个顶点
                validateVertex(b);

                if(a == b) throw new IllegalArgumentException("Self Loop is Detected"); //判断是够存在自环边
                if(adj[a].contains(b)) throw new IllegalArgumentException("Parallel Edges are Detected"); //判断是够存在平行l边

                adj[a].add(b);
                adj[b].add(a);
            }
        }
        catch (IOException e){
            e.printStackTrace();
        }
    }

    private void validateVertex(int v){
        if(v < 0 || v >= V)
            throw new IllegalArgumentException("vertex" + v + "is invalid");
    }

    public int V(){
        return V;
    }

    public int E(){
        return E;
    }

    public boolean hasEdge(int v, int w){
        validateVertex(v);
        validateVertex(w);
        return adj[v].contains(w);
    }

    public Iterable<Integer> adj(int v){ // 可以是TreeSet,但是数组、链表、红黑树都是实现了Iterable的接口,因此可以统一写成这样
        validateVertex(v);
        return adj[v];
    }

    public int degree(int v){
        validateVertex(v);
        return adj[v].size(); // Iterable没有size()方法
    }

    @Override
    public String toString(){
        StringBuilder sb = new StringBuilder();
        sb.append(String.format("V = %d, E = %d\n", V, E));

        for (int i = 0; i < V; i++) {
            sb.append(String.format("%d:",i));
            for (int w: adj[i]) {
                sb.append(String.format("%d ",w));
            }
            sb.append('\n');
        }
        return sb.toString();
    }

    public static void main(String[] args){
        AdjSet adjSet = new AdjSet("g1.txt"); //新建邻接矩阵,并从文件内容初始化
        System.out.println(adjSet);
    }
}

5.3 邻接矩阵-LinkedList

java 复制代码
package Chapt01_Adjacency;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;

public class AdjMatrix {
    private int V;
    private int E;
    private int[][] adj;

    // 构造函数,从文件内容初始化邻接矩阵
    public AdjMatrix(String filename){
        File file = new File(filename);
        try(Scanner scanner = new Scanner(file)){
            V = scanner.nextInt(); //读取第一行第一个数,代表图中的顶点数
            if(V < 0) throw new IllegalArgumentException("V must be non-negative");

            adj = new int[V][V]; //构造邻接矩阵

            E = scanner.nextInt(); //读取第一行第二个数,代表图中边的数量
            if(E < 0) throw new IllegalArgumentException("E must be non-negative");

            // E是边的数量,在g.txt中表示为第二行开始的E行
            for (int i = 0; i < E; i++) {
                int a = scanner.nextInt(); //读取边的一个顶点
                validateVertex(a);
                int b = scanner.nextInt(); //读取边的另一个顶点
                validateVertex(b);

                if(a == b) throw new IllegalArgumentException("Self Loop is Detected"); //判断是够存在自环边
                if(adj[a][b] == 1) throw new IllegalArgumentException("Parallel Edges are Detected"); //判断是否存在平行l边

                adj[a][b] = 1; //存在边则设置为1
                adj[b][a] = 1;
            }
        }
        catch (IOException e){
            e.printStackTrace();
        }
    }

    private void validateVertex(int v){
        if(v < 0 || v >= V)
            throw new IllegalArgumentException("vertex" + v + "is invalid");
    }

    public int V(){
        return V;
    }

    public int E(){
        return E;
    }

    public boolean hasEdge(int v, int w){
        validateVertex(v);
        validateVertex(w);
        return adj[v][w] == 1;
    }

    public ArrayList<Integer> adj(int v){
        validateVertex(v);
        ArrayList<Integer> res = new ArrayList<>();
        for (int i = 0; i < V; i++) {
           if(adj[v][i] == 1) res.add(i);
        }
        return res;
    }

    public int degree(int v){
        return adj(v).size(); //adj(v)是上方的adj方法,size()是ArrayList的接口
    }

    // 用于在控制台打印该临接矩阵
    @Override
    public String toString(){
        StringBuilder sb = new StringBuilder();
        sb.append(String.format("V = %d, E = %d\n", V, E)); //打印顶点数和边的数量

        for (int i = 0; i < V; i++) { //行
            for (int j = 0; j < V; j++) { //列
                sb.append(String.format("%d",adj[i][j])); //读取矩阵的值
            }
            sb.append('\n'); //行尾换行
        }
        return sb.toString(); //返回该邻接矩阵
    }

    public static void main(String[] args){
        AdjMatrix adjMatrix = new AdjMatrix("g1.txt"); //新建邻接矩阵,并从文件内容初始化
        System.out.println(adjMatrix);

    }
}

5.4 输入文件

go 复制代码
7 9
0 1
0 3
1 2
1 6
2 3
2 5
3 4
4 5
5 6
相关推荐
逝去的秋风2 天前
【代码随想录训练营第42期 Day57打卡 - 图论Part7 - Prim算法与Kruskal算法
算法·图论·prim算法
热爱编程的OP3 天前
图论篇--代码随想录算法训练营第六十一天打卡| Floyd 算法,A*算法
数据结构·c++·学习·算法·图论
Aurora_th3 天前
图论三元环(并查集的高级应用)
c++·算法·图论·并查集·观察力·三元环
EllinY3 天前
CF 231 E Cactus 题解(仙人掌图上找环)
c++·笔记·算法·深度优先·图论
人才程序员3 天前
CSP-J 算法基础 图论
开发语言·数据结构·c++·算法·青少年编程·图论·编程比赛
热爱编程的OP3 天前
图论篇--代码随想录算法训练营第五十八天打卡|拓扑排序,dijkstra(朴素版),dijkstra(堆优化版)精讲
数据结构·c++·算法·图论
wh233z4 天前
Codeforces Round 969 (Div. 2) (A~D)
c语言·开发语言·数据结构·c++·算法·图论
那一抹阳光多灿烂4 天前
代码随想录训练营 Day58打卡 图论part08 拓扑排序 dijkstra朴素版 + 堆优化版
数据结构·python·算法·图论
buaichifanqie4 天前
拓扑排序算法
c++·算法·排序算法·图论·拓扑排序
背水4 天前
再次探讨最小生成树Prim算法
算法·图论