数据结构之图(java语言版)

news/发布时间2024/8/25 18:51:15

图是比树更复杂的结构,树是一对多的关系,图是多对多的关系。

一、基本概念

1、定义:图(graph)是由一些点(vertex)和这些点之间的连线(edge)所组成的;其中,点通常被成为"顶点(vertex)",而点与点之间的连线则被成为"边或弧"(edege)。通常记为,G=(V,E)。

2、根据边是否有方向,将图可以划分为:无向图有向图

3、度,在无向图中,某个顶点的度是邻接到该顶点的边(或弧)的数目。

在有向图中,度还有"入度"和"出度"之分。
某个顶点的入度,是指以该顶点为终点的边的数目。而顶点的出度,则是指以该顶点为起点的边的数目。
顶点的度=入度+出度。

4、弧头和弧尾

有向图中:用<A,B>,<B,C>,<B,F>,A->B,A是弧尾,B是 弧头。

无向图中:用(A,B),(A,C),(B,C),弧头和弧尾没有区别。

5、权

弧如果有值的话,称为权。

二、图的存储结构

图的存储结构有许多种,有邻接矩阵,邻接表,十字链表等。

邻接矩阵

用矩阵表示,用线性表存储数据,直观简单,但是浪费空间。

在这里插入图片描述

邻接表

用数组和链表表示结构,节省空间,可伸缩。

数组中存储了链表,链表的头节点代表定点,存储着数据及下一个顶点的引用,后面的节点存储着下标和下一个顶点的引用。

在这里插入图片描述

在这里插入图片描述

图来自《大话数据结构》

邻接表实现图

顶点及索引结构

顶点存储着数据和索引。

索引结构存储着顶点在数组中的下标。

class VexNode{//顶点String data;//顶点的数据EdgeNode fnext;//指向下一个顶点public VexNode(){}public VexNode(String data){this.data=data;}}class EdgeNode{//存储索引的节点int index;//索引//int weight;//权重EdgeNode next;//指向下一个顶点
}

建立图

使用数组存储链表。

构造方法传入顶点数和弧数。

public class Graph{public VexNode[] vexTable;//表private int numNode;//顶点数量private int size;//弧数public Graph(int numNode,int size){//构造函数,确定顶点数量this.numNode=numNode;this.size=size;vexTable=new VexNode[numNode];}public VexNode[] init(){//建立邻接表Scanner scanner =new Scanner(System.in);for(int i=0;i<numNode;i++){System.out.println("输入顶点数据");String data=scanner.next();VexNode node=new VexNode(data);vexTable[i]=node;}System.out.println("输入弧数据:");for(int k=0;k<size;k++){EdgeNode eNode=new EdgeNode();System.out.println("输入弧头:");int x=scanner.nextInt();System.out.println("输入弧尾:");int y=scanner.nextInt();eNode.index=y;eNode.next=vexTable[x].fnext;//头插法插入链中vexTable[x].fnext=eNode;eNode=new EdgeNode();//无向表需要弧头弧尾相同eNode.index=x;//如果建立的是有向表,将这四行代码去除即可eNode.next=vexTable[y].fnext;vexTable[y].fnext=eNode;}return vexTable;} 
}

查看弧

图的遍历比较复杂,我们可以先通过弧来查看图是否正确。

public void display(VexNode[] vexTable){System.out.println("打印表:");for(int i=0;i<numNode;i++){EdgeNode v=vexTable[i].fnext;while(v!=null){System.out.printf("(%s %s) ",vexTable[i].data,vexTable[v.index].data);v=v.next;}System.out.println();}}

用以下图来表示,数据输入顺序代表数据在数组中的位置。所以顶点输入顺序是

abcde

弧的输入顺序代表方向,不过我们建立的表是无向图,所以无所谓。

在这里插入图片描述

主函数中测试:

    public static void main(String[] args) {Graph graph=new Graph(5,5);VexNode[] vexTable=graph.init();graph.display(vexTable);}

输入数据:

输入顶点数据
a
输入顶点数据
b
输入顶点数据
c
输入顶点数据
d
输入顶点数据
e
输入弧数据:
输入弧头:
0
输入弧尾:
1
输入弧头:
1
输入弧尾:
3
输入弧头:
3
输入弧尾:
4
输入弧头:
4
输入弧尾:
2
输入弧头:
2
输入弧尾:
0

得到结果:

无向图会打印两次,有向图只有一个指向只会打印一次。

打印表:
(a c) (a b)
(b d) (b a)
(c a) (c e)
(d e) (d b)
(e c) (e d)

遍历

图的遍历有深度优先和广度优先。

深度优先遍历是从图中某个顶点出发,访问此顶点,然后从它未被访问到的邻接点出发深度优先遍历图,直到图中所有和它有路径相通的顶点都被访问到.,类似树的先序遍历。

广度优先遍历从某个顶点出发,访问其所有相邻元素,再从某个相邻元素开始广度优先遍历,类似树的层级遍历。

深度优先遍历

对遍历过的点需要标记,以免重复遍历。

同样可以递归来遍历。

	private int[] visit;//标记顶点是否遍历,1为已遍历,0为未遍历//深度优先遍历public void DFS(VexNode[] vexTable){this.visit=new int[numNode];//默认所有顶点都未遍历,数组中值都为0System.out.println("深度优先遍历:");for(int i=0;i<numNode;i++){if(visit[i]==0){    DFSVisit(vexTable, i);}}System.out.println();}public void DFSVisit(VexNode[] vexTable,int i){//对为遍历的数据输出EdgeNode eNode;visit[i]=1;//该顶点已经遍历System.out.print(" "+vexTable[i].data);eNode=vexTable[i].fnext;while(eNode!=null){if(visit[eNode.index]==0){DFSVisit(vexTable, eNode.index);}eNode=eNode.next;}}

广度优先遍历

广度优先遍历的特点是我们需要一个先进先出的容器来保存顶点。

使用队列即可,这里的队列可以采用之前的队列,也可以通过java已经提供好的LinkedList类来实现。

我们采用之前的链表队列:

public class Queue{SingleLinkList list;public Queue(){list=new SingleLinkList();}public void enQueue(Object e) {list.add(e);System.out.println("入队");}public Object deQueue() {Object e=list.get(1);list.remove(1);System.out.println("出队");return e;}public void display() {list.display();}public int getSize(){return list.getSize();}
}

广度优先如下:

    private Queue queue;//广度优先遍历public void BFS(){this.visit=new int[numNode];//默认所有顶点都未遍历,数组中值都为0System.out.println("广度优先遍历:");this.queue=new Queue();//建立队列for(int i=0;i<numNode;i++){if(visit[i]==0){BFSVisit();}}System.out.println();}public void BFSVisit(){//遍历操作for(int i=0;i<numNode;i++){if(visit[i]==0){visit[i]=1;System.out.print(" "+vexTable[i].data);queue.enQueue(i);//入队EdgeNode eNode;while(!queue.isEmpty()){queue.deQueue();//出队eNode=vexTable[i].fnext;while(eNode!=null){if(visit[eNode.index]==0){visit[eNode.index]=1;System.out.print(" "+vexTable[eNode.index].data);queue.enQueue(eNode.index);}eNode=eNode.next;}}}}}

还是采用这个图:使用同样的输入数据在主方法中测试:

在这里插入图片描述

public static void main(String[] args) {Graph graph=new Graph(5,5);VexNode[] vexTable=graph.init();graph.DFS(vexTable);graph.BFS();}
深度优先遍历:a c e d b
广度优先遍历:a c b d e

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.liansuoyi.cn/news/88002874.html

如若内容造成侵权/违法违规/事实不符,请联系连锁易网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

在远程windows上调试Cmake项目 C++

记录一下CMake项目MSVC编译器远程调试方法 参考资料 教程:在远程 Windows 计算机上调试 CMake 项目 | Microsoft Learn 1.使用VS打开cmake项目 2.右键main.cpp文件,添加调试配置 选择C++ 3.会打开一个 launch.vs.json文件 配置一下 注意:远程机器那里写需要运行的机器号 …

mysql查询某条记录所在的行号

有时候我们想知道某条记录在表中的多少行,这样我们就可以开始继续上一次的任务了。 下面是SQL,可以直接执行,把表名改成自己真实的表名就好了,还得注意下子查询的排序,也得按自己真实需求来即可:SET @row_number = 0; SELECT index_position FROM ( SELECT author_id, @r…

echarts X轴类目名太长时隐藏,hover时显示全部

echarts图表X轴 在柱状图中,X轴类目名如果数据太长; echarts会默认进行隐藏部分字段; 如果我们想让每一个类目名都显示出来,需要进行额外的处理X轴类目名太长时,默认只显示一部分类目名 <!DOCTYPE html> <html lang="en"> <head><meta char…

IREE HLO与MLIR编译器

IREE HLO与MLIR编译器 MLIR(Multi-Level Intermediate Representation)是谷歌团队开发的开源编译器框架,提供了一套灵活的软件基础设施,以便规范中间表达式(IR)及其相互之间的转换,建立了一个友好的编译器开发平台,一些比较好的对MLIR框架解读可以参考。IREE项目也是谷歌…

【EF Core】Code first

简介 前期环境 Visual Studio 2022 .net framework 4.7.2 Sqlite3 Navicat 15 CodeFirst的三种方式使用新数据库 使用现有数据库 迁移一、使用新数据库的CodeFirst 查看:https://learn.microsoft.com/zh-cn/ef/ef6/modeling/code-first/workflows/existing-database 查看:htt…

【Azure Storage Account /ADLS】可用性指标降低的警告和是否会发生故障转移

问题描述使用存储位于Azure的存储账号和ADLS Gen2,为存储账号的可用性配置了告警。 想了解: 1) 可用性报警对业务依赖并使用存储账号的业务程序是否会产生影响,比如是否会导致依赖存储账号的程序不能正常工作,报错等 2) 当可用性降低后,存储账号是否会产生故障转移?或者是…

蓝桥杯STM32G431RBT6-各个外设的配置过程

LED,按键配置LED点亮,按键采集按键值前期准备:通过Cubemx生成一个源文件方便后续直接使用。 源文件准备完毕以后开始进行按键和LED的配置 LED  对比芯片引脚连接图可以知道8个LED分别连接在GPIOC的如下8个引脚中  Cubemx中对该8个引脚进行配置,分别配置为推挽输出模式…

高级项目管理

4、六西格玛认为业务流程改进遵循5步循环改进法,即 DMAIC模式:定义、度量、分析、改进、控制。(1)定义(Define):识别需要改进的产品或过程,确定改进项目所需的资源。(2)度量(Measure):定义缺陷,收集产品或过程的表现作为工作基准,建立改进目标。(3)分析(Analy…

python爬虫—学习笔记-3

python爬虫—学习笔记-3 ps:因为本人近一个月住院,文章为队友所著。 此次学习内容为如何搭建服务器 1.打开pycharm,创建目录server在设置中的Python解释器中安装Flask2.在创建的server1中输入本节课所学代码在网页中输入ip 端口号 子目录 本机访问127.0.0.1:5000/子目录 外…

python 使用waitress替代flask自带的web服务器

首席引入依赖安装waitrss pip intsll waitress然后在flask程序内引入依赖 使用server()函数代替app.run()函数 启动时,直接python xxx.py即可from waitress import serve from flask import Flask app = Flask(__name__)@app.route(/) def hello_world(): return Hello Wo…

sy3

一、任务详情 密码引擎API的主要标准和规范包括: 1 微软的Crypto API 2 RAS公司的PKCS#11标准 3 中国商用密码标准:GMT 0016-2012 智能密码钥匙密码应用接口规范,GMT 0018-2012密码设备应用接口规范等 研究以上API接口,总结他们的异同,并以龙脉GM3000Key为例,写出调用不同…

发布一个自己的composer包

首先我们创建一个空的目录,并且运行以下命令初始化一个空白的composer包 composer init可以在命令窗口看到有返回提示; 需要输入包名 This command will guide you through creating your composer.json config.` Package name (<vendor>/<name>) :我这里写的是c…

读所罗门的密码笔记15_数据透明度

读所罗门的密码笔记15_数据透明度1. 数据透明度与控制权 1.1. 作为人类,我们会带有偏见,而且往往不知道自己在智力和情感上的盲区 1.2. 精心制作的人工智能机器,即使有自己的缺点,也能帮助我们做出更客观的决定,为提升我们的生活质量和改善社区的生态环境做出贡献 1.3. 美…

QAT量化感知训练

QAT量化感知训练 基本原理 相比训练后量化因为其不是全局最优而导致的精度损失,QAT量化感知训练能做到基于loss优化的全局最优,而尽可能的降低量化精度损失,其基本原理是:在fp32模型训练中就提前引入推理时量化导致的权重与激活的误差,用任务loss在训练集上来优化可学习的…

树状数组快速入门

树状数组、 Fenwick Tree 或 Binary Indexed Tree ,通常用缩写 BIT 代表。 是一种 “一种基于二进制 lowbit ,用于维护(加法、位运算、max、gcd 的)前缀和的树形数组” 。 可以叫做 一个树状数组 或 一棵 Fenwick Tree 。 重要性质:同时满足即是数组又是树的性质。针对定义…

蓝桥杯2020年C组-试题I-数字三角形(简化版-少一个左右路径差不大于1条件)

1. 题目介绍上图给出了一个数字三角形。 从三角形的顶部到底部有很多条不同的路径。 对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和。 路径上的每一步只能从一个数走到下一层和它最近的左边的那个数或者右边的那个数。 输入格式 输入的第一行包…

e/易语言 按钮界面弹出气泡提示

案例本文来自博客园,作者:__username,转载请注明原文链接:https://www.cnblogs.com/code3/p/18125232

Linux安装JDK详细教程

Linux安装JDK详细教程(图文教程) 这里介绍两种方式:yum安装方式和手动安装1、yum安装 1.1 查看JDK版本,找到你想要安装的JDK版本,这里以 JDK1.8 为例 输入命令:yum -y list java*1.2 安装JDK1.8 输入命令:yum install -y java-1.8.0-openjdk.x86_64 没权限执行这行:sud…

查询下属

win +R 键sqlplus1 用户名:scott密码 :tigerselect * from emp;select * from dept;select ename,sal,comm from emp;select ename,sal+nvl(comm,0) from emp;select ename,12*(sal+nvl(comm,0))年薪 from emp;1 select empno from emp where ename=upper(king);2 select …

PHP代码审计——Day7-Bells

漏洞解析 function getUser($id) {global $config, $db;if (!is_resource($db)) {$db = new MySQLi($config[dbhost],$config[dbuser],$config[dbpass],$config[dbname]);}$sql = "SELECT username FROM users WHERE id = ?";$stmt = $db->prepare($sql); // 调用…
推荐文章