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

2023-10-21 05:12

本文主要是介绍图论01-【无权无向】-图的基本表示-邻接矩阵/邻接表,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

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

1. 代码仓库

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

2. 图的基本表示的比较

在这里插入图片描述

3. 邻接矩阵:Array和TreeSet

3.1 图示

在这里插入图片描述

3.2 Array主要代码解析

代码有删减

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; //存在边则设置为1adj[b][a] = 1;}}
}

在这里插入图片描述

3.3 测试输出

在这里插入图片描述

3.4 使用TreeSet的代码

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

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

在这里插入图片描述

4. 邻接表:LinkedList

4.1 图示

在这里插入图片描述

4.2 LinkedList主要代码解析

代码有删减

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

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个LinkedListfor (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();}@Overridepublic 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

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个LinkedListfor (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()方法}@Overridepublic 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

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; //存在边则设置为1adj[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的接口}// 用于在控制台打印该临接矩阵@Overridepublic 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 输入文件

7 9
0 1
0 3
1 2
1 6
2 3
2 5
3 4
4 5
5 6

这篇关于图论01-【无权无向】-图的基本表示-邻接矩阵/邻接表的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/252167

相关文章

SQL BETWEEN 语句的基本用法详解

《SQLBETWEEN语句的基本用法详解》SQLBETWEEN语句是一个用于在SQL查询中指定查询条件的重要工具,它允许用户指定一个范围,用于筛选符合特定条件的记录,本文将详细介绍BETWEEN语... 目录概述BETWEEN 语句的基本用法BETWEEN 语句的示例示例 1:查询年龄在 20 到 30 岁

mysql中insert into的基本用法和一些示例

《mysql中insertinto的基本用法和一些示例》INSERTINTO用于向MySQL表插入新行,支持单行/多行及部分列插入,下面给大家介绍mysql中insertinto的基本用法和一些示例... 目录基本语法插入单行数据插入多行数据插入部分列的数据插入默认值注意事项在mysql中,INSERT I

mapstruct中的@Mapper注解的基本用法

《mapstruct中的@Mapper注解的基本用法》在MapStruct中,@Mapper注解是核心注解之一,用于标记一个接口或抽象类为MapStruct的映射器(Mapper),本文给大家介绍ma... 目录1. 基本用法2. 常用属性3. 高级用法4. 注意事项5. 总结6. 编译异常处理在MapSt

MyBatis ResultMap 的基本用法示例详解

《MyBatisResultMap的基本用法示例详解》在MyBatis中,resultMap用于定义数据库查询结果到Java对象属性的映射关系,本文给大家介绍MyBatisResultMap的基本... 目录MyBATis 中的 resultMap1. resultMap 的基本语法2. 简单的 resul

Java 枚举的基本使用方法及实际使用场景

《Java枚举的基本使用方法及实际使用场景》枚举是Java中一种特殊的类,用于定义一组固定的常量,枚举类型提供了更好的类型安全性和可读性,适用于需要定义一组有限且固定的值的场景,本文给大家介绍Jav... 目录一、什么是枚举?二、枚举的基本使用方法定义枚举三、实际使用场景代替常量状态机四、更多用法1.实现接

git stash命令基本用法详解

《gitstash命令基本用法详解》gitstash是Git中一个非常有用的命令,它可以临时保存当前工作区的修改,让你可以切换到其他分支或者处理其他任务,而不需要提交这些还未完成的修改,这篇文章主要... 目录一、基本用法1. 保存当前修改(包括暂存区和工作区的内容)2. 查看保存了哪些 stash3. 恢

MySQL基本查询示例总结

《MySQL基本查询示例总结》:本文主要介绍MySQL基本查询示例总结,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Create插入替换Retrieve(读取)select(确定列)where条件(确定行)null查询order by语句li

Python 异步编程 asyncio简介及基本用法

《Python异步编程asyncio简介及基本用法》asyncio是Python的一个库,用于编写并发代码,使用协程、任务和Futures来处理I/O密集型和高延迟操作,本文给大家介绍Python... 目录1、asyncio是什么IO密集型任务特征2、怎么用1、基本用法2、关键字 async1、async

redis中使用lua脚本的原理与基本使用详解

《redis中使用lua脚本的原理与基本使用详解》在Redis中使用Lua脚本可以实现原子性操作、减少网络开销以及提高执行效率,下面小编就来和大家详细介绍一下在redis中使用lua脚本的原理... 目录Redis 执行 Lua 脚本的原理基本使用方法使用EVAL命令执行 Lua 脚本使用EVALSHA命令

MySQL 中的 LIMIT 语句及基本用法

《MySQL中的LIMIT语句及基本用法》LIMIT语句用于限制查询返回的行数,常用于分页查询或取部分数据,提高查询效率,:本文主要介绍MySQL中的LIMIT语句,需要的朋友可以参考下... 目录mysql 中的 LIMIT 语句1. LIMIT 语法2. LIMIT 基本用法(1) 获取前 N 行数据(