【数据结构】图的存储结构—邻接表

article/2025/8/27 22:18:53

目录

什么是邻接表?

邻接表:定义

邻接表:相关类

邻接表:基本操作

1)创建无向网

2)创建有向网

3)顶点定位

4)插入边

5)第一个邻接点

6)查询下一个邻接点

小试牛刀

对比邻接表与邻接矩阵

💟 创作不易,不妨点赞💚评论❤️收藏💙一下


💟作者简介:大家好呀!我是路遥叶子,大家可以叫我叶子哦!❣️    
📝个人主页:【路遥叶子的博客】
🏆博主信息:四季轮换叶,一路招摇胜!

               专栏

        【安利Java基础】

        【数据结构-Java语言描述】

🐋希望大家多多支持😘一起进步呀!~❤️
🌈若有帮助,还请【关注点赞收藏】,不行的话我再努力努力呀!💪
————————————————
🍁想寻找共同成长的小伙伴,请点击【Java全栈社区】

前言

由于图的结构比较复杂,任意两个顶点之间都可能存在关系(边),无法通过存储位置表示这种任意的逻辑关系,所以,图无法采用顺序存储结构。这一点同其他数据结构(如线性表、树)不同。

因为图中的顶点具有相对概念,没有固定的位置,且顶点和顶点之间通过添加和删除边,维持着不同的关系。考虑图的定义,图是由顶点和边组成的。所以,分别考虑如何存储顶点和边。图常用的存储结构有邻接矩阵、邻接表、十字链表和邻接多重表。那么对于一般情况下该怎么存储图的数据结构呢?这里我们主要分两个章节详细介绍两种常用的图存储结构 — 邻接矩阵、邻接表


什么是邻接表?

在图论和计算机科学中,邻接表【Adjacency List】是用来表示有限图的无序表的集合。每个列表描述图中一个顶点的邻域集。这是计算机程序中常用的几种图形表示法之一。

1. 邻接表,存储方法跟树的孩子链表示法相类似,是一种顺序分配和链式分配相结合的存储结构。如这个表头结点所对应的顶点存在相邻顶点,则把相邻顶点依次存放于表头结点所指向的单向链表中。

2. 实际上就是一种由链表组成的图形数据结构,对其每一个顶点,都用链表来记录它的出边。   

3. 对于无向图来说,使用邻接表进行存储也会出现数据冗余,表头结点A所指链表中存在一个指向C的表结点的同时,表头结点C所指链表也会存在一个指向A的表点。   

邻接表:定义

对于无向图,n个顶点e条边的无向图的邻接表表示中,有n个顶点表结点和2e个边表结点。

对于有向图,vi的邻接表中每个表结点都对应于以vi为始点射出的一条边。因此,将有向图的邻接表称为出边表。

1、邻接表是图的一种链式存储方法

2、邻接表由一个顺序存储的顶点表和n个链式存储的边表组成。

  • 顶点表由顶点结点组成

  • 边表:

     无向图:由 边 结点组成的一个单链表,表示所有依附于顶点vi的边。

    有向图:由 弧 结点组成的一个单链表,表示所有以顶点vi为始点的弧。

  • 链式存储结点:

    • 图结点由2部分组成:第一个邻接点、下一个邻接点

    • 网结点有3部分组成:第一个邻接点、权值、下一个邻接点

无向图:对应的邻接表某行上边结点个数为该行表示结点的度。

  • 如果无向图(网)中有e条边,则对应邻接表有2e个边结点。

  • 无向网邻接表


有向图:

  • 邻接表:边表表示所有以vi为始点的弧。

    • 对应的邻接表某行上边结点个数为该结点的出度。

    • 在有向图的邻接表中不易找到指向该顶点的弧。

逆邻接表:边表表示所有以vi为终点的弧。

  • 对应的逆邻接表某行上边结点个数为该结点的入度。

  •  如果有向图(网)中有e条边,则对应邻接表有e个边结点。


邻接表:相关类

  • 顶点结点类:

//图的邻接表存储表示中的顶点结点类
public class VNode {public Object data;			//顶点信息public ArcNode firstArc;	//指向第一个依附于该顶点的弧
}
  • 边(弧)结点类:

//图的邻接表存储表示中的边(弧)结点类
public class ArcNode {public int adjVex;			//该弧所指向的顶点位置public int value;			//边(或弧)的权值public ArcNode nextArc;		//指向下一条弧
}
  • 邻接表类
//创建邻接表
public class ALGraph implements IGraph {private GraphKind kind;			//图的种类标志private int vexNum, arcNum;		//图的当前顶点数和边数private VNode[] vexs;			//顶点private void createUDN() {		//创建无向网}private void createDN() {		//创建有向网}// 给定顶点的值vex,返回其在图中的位置,若图中不包含该顶点的,则返回-1public int locateVex(Object vex) {}// 在图中插入边结点public void addArc(int v, int u, int value) {}// 返回v的第一个邻接点,若v没有邻接点则返回-1。其中 0 <= v <= vexNumpublic int firstAdjVex(int v) throws Exception {}// 返回v相对于w的下一个邻接点,若w是v的最后一个邻接点,则返回-1。其中 0 <= v,w <= vexNumpublic int nextAdjVex(int v, int w) throws Exception {}
}

邻接表:基本操作

1)创建无向网

  • 步骤:

    1. 输入顶点数和边数

    2. 构建顶点向量

    3. 根据图的边数,确定输入边的数目

    4. 根据输入的每条边生成结点,并在相应位置插入边结点

  • 代码

// 无向网的创建算法
private void createUDN() {//初始化变量Scanner sc = new Scanner(System.in);System.out.println("请分别输入图的顶点数、图的边数:");vexNum = sc.nextInt(); //顶点数narcNum = sc.nextInt(); //边数e//输入图中各顶点vexs = new VNode[vexNum];System.out.println("请分别输入图的各顶点:");// 构造顶点向量for (int v = 0; v < vexNum; v++)vexs[v] = new VNode(sc.next());//输入图中各边信息System.out.println("请输入各边的顶点及其权值:");for (int k = 0; k < arcNum; k++) {int v = locateVex(sc.next());   // 弧尾int u = locateVex(sc.next());  	// 弧头int value = sc.nextInt();		// 权值addArc(v, u, value);   //加入边addArc(u, v, value);   //加入边}
}

2)创建有向网

	// 创建有向网private void createDN() {Scanner sc = new Scanner(System.in);System.out.println("请分别输入图的顶点数、图的边数:");vexNum = sc.nextInt();arcNum = sc.nextInt();vexs = new VNode[vexNum];System.out.println("请分别输入图的各顶点:");for (int v = 0; v < vexNum; v++)// 构建顶点向量vexs[v] = new VNode(sc.next());System.out.println("请输入各边的顶点及其权值:");for (int k = 0; k < arcNum; k++) {int v = locateVex(sc.next());// 弧尾int u = locateVex(sc.next());// 弧头int value = sc.nextInt();addArc(v, u, value);		// 一个方向}}

3)顶点定位

// 给定顶点的值vex,返回其在图中的位置,若图中不包含该顶点的,则返回-1public int locateVex(Object vex) {for (int v = 0; v < vexNum; v++)if (vexs[v].data.equals(vex))return v;return -1;}

4)插入边

  • 核心思想:往链式存储的边表头插入一个新结点。

// 在图中插入边结点public void addArc(int v, int u, int value) {ArcNode arc = new ArcNode(u, value);	//u为边的终点,生成边结点arc.nextArc=vexs[v].firstArc;			//v为边的起点,将边结点插入顶点v 的链表表头vexs[v].firstArc=arc;					//生成新表头}

5)第一个邻接点

// 已知图中的一个顶点v,返回v的第一个邻接点,如果v没有连接点,则返回-1,其中0 <= v < vexNumpublic int firstAdjVex(int v) throws Exception {if (v < 0 || v >= vexNum)throw new Exception("第" + v + "个顶点不存在!");VNode vex = vexs[v];if (vex.firstArc != null)return vex.firstArc.adjVex;elsereturn -1;}

6)查询下一个邻接点

public int nextAdjVex(int v, int w) throws Exception {if (v < 0 || v >= vexNum)throw new Exception("第" + v + "个顶点不存在!");VNode vex = vexs[v];ArcNode arcvw = null;// 获得w结点在链表中所在的位置for (ArcNode arc = vex.firstArc; arc != null; arc = arc.nextArc)if (arc.adjVex == w) {arcvw = arc;break;}// 返回w的下一个邻接点if (arcvw != null && arcvw.nextArc != null)return arcvw.nextArc.adjVex;elsereturn -1;}

小试牛刀

回顾前一章节,我们一起学习了图的邻接矩阵和邻接表。下面我们来练习练习,给出下图,试着画出图对应的邻接表和邻接矩阵吧!检验一下学习成果。

 你学会了吗?快来对对答案吧!


对比邻接表与邻接矩阵

1、对于稀疏图,邻接表比邻接矩阵更节省存储空间。

邻接表的空间使用与图中的边和顶点的数量成正比,而对于以这种方式存储的邻接矩阵,其空间与顶点数的平方成正比。然而,通过使用由顶点对索引的哈希表而不是数组,可以更有效地存储邻接矩阵的空间,从而匹配邻接表的线性空间使用。

2、邻接表上很容易找到任意一个顶点的邻接点和 ,但若要判定任意两个邻接点是否有边相连,则需遍历单链表,不如邻接矩阵方便。

3、邻接表和邻接矩阵之间的另一个显著区别是它们执行操作的效率

在邻接表中,每个顶点的邻居可以有效地列出,在时间上与顶点的程度成正比。在邻接矩阵中,这个操作需要的时间与图中顶点的数量成正比,而顶点的数量可能明显高于度。此外,邻接矩阵允许测试两个顶点是否在固定的时间内彼此相邻;邻接表支持这一操作的速度较慢。

不同的数据结构也有着不同的操作。在邻接表中找到与给定顶点相邻的所有顶点就像读取邻接表一样简单。对于邻接矩阵,必须扫描整行,这就需要花费时间。


写到最后

四季轮换,已经数不清凋零了多少, 愿我们往后能向心而行,一路招摇胜!

🐋 你的支持认可是我创作的动力

💟 创作不易,不妨点赞💚评论❤️收藏💙一下

😘 感谢大佬们的支持,欢迎各位前来不吝赐教

想要了解更多吗?没时间解释了,快来点一点!

路遥叶子的博客_CSDN博客-数据结构,安利Java零基础,spring领域博主https://blog.csdn.net/zsy3757486?spm=1010.2135.3001.5343


http://chatgpt.dhexx.cn/article/T92I10tt.shtml

相关文章

图的存储结构---邻接表

1. 邻接表&#xff08;无向图&#xff09; 对于边数相对顶点较少的图&#xff0c;可采取邻接表。把数组与链表结合在一起来存储&#xff0c;这种方式在图结构也适用&#xff0c;称为邻接表&#xff08;AdjacencyList&#xff09;。 2. 邻接表&#xff08;有向图&#xff09…

图的存储结构——邻接表

图的存储结构之邻接表 一、邻接表表示法无向图的邻接表有向图的邻接表有向图的逆邻接表 二、图的邻接表存储表示三、采用邻接表表示法创建无向网 一、邻接表表示法 回忆在线性表时&#xff0c;顺序存储结构就存在预先分配内存可能造成存储空间浪费的问题&#xff0c;于是引出了…

vivado实现FFT和IFFT信号处理

一&#xff0c;FFT的物理意义 FFT是离散傅立叶变换的快速算法&#xff0c;可以将一个信号变换到频域。有些信号在时域上是很难看出什么特征的&#xff0c;但是如果变换到频域之后&#xff0c;就很容易看出特征了。这就是很多信号分析采用FFT变换的原因。另外在频谱分析方面&a…

ifft java_OpenCV DFT_INVERSE与Matlab的ifft不同

我尝试使用opencv的dft函数过滤信号 . 我试图这样做的方式是在时域中获取信号&#xff1a; x [0.0201920000000000 -0.0514940000000000 0.0222140000000000 0.0142460000000000 -0.00313500000000000 0.00270600000000000 0.0111770000000000 0.0233470000000000 -0.00162700…

4.8 IFFT/FFT

4.8.1 IFFT/FFT原理 1. IFFT、FFT在OFDM系统中的应用 2、IFFT/FFT原理 3、DIT的基2FFT算法 4、DIF的基2FFT运算 5、基于的频率抽选FFT算法 4.8.2 基于 DIF FFT的硬件 结构 1、各级的蝶形运算硬件实现 2、transfer12、 transfer34、transfer56硬件实现 3、transfer23、 transfe…

Python实现FFT及IFFT

运行环境及编译工具 WindowsVS Code 编程语言及库版本 库版本Python3.7.0copy无numpy1.19.2opencv3.4.2PIL8.1.0matplotlib3.4.3 可执行文件 HW_2.pyHW_2.ipynb在HW_2.ipynb中执行&#xff0c;详细程序信息在HW_2.py中 问题 1 通过计算一维傅里叶变换实现图像二维快速傅里…

matlab FFT 和IFFT

代码&#xff1a; fs100;N128; n0:N-1;tn/fs; xsin(2*pi*40*t)sin(2*pi*15*t); subplot(221);plot(n,x,b); xlabel(时间/s);ylabel(x);title(原始信号); grid on;yfft(x,N); magabs(y); fn*fs/N; subplot(222);plot(f(1:N/2),mag(1:N/2)*2/N,b); xlabel(频率/Hz);ylabel(振幅)…

基于vivado实现FFT/IFFT

文章目录 前言一、基本过程二、vivado配置1.新建工程2.调用DDS的IP核2.调用FFT的IP核 三、编写Verilog程序1.顶层文件fft.v2.仿真文件fft_tb.v 四、运行仿真1. 运行仿真设置2. 仿真波形设置3. 结果分析 前言 使用vivado2018.3实现FFT&#xff0f;IFFT&#xff0c;过程比较详细…

python fft ifft

文章目录 条件代码实例 条件 任何一个满足狄利克雷条件的函数都可以通过傅里叶基数展开。 numpy和scipy中都有fft变换&#xff0c;且效果都是一样的。 代码 import numpy as np from scipy.fftpack import fft,ifft import matplotlib.pyplot as plt from matplotlib.pylab …

FFT专题:IFFT后信号如何重建

ifft(outFFTData, g_fft_temp, inFFTData, g_twiddle_ifft, twiddle_stride, F_WLEN);//思考ifft输出的复数结果怎么给到硬件输出 之前一直关注FFT后信号奔赴到频域处理,那么频域处理完后,怎么重建信号呢? 给出一段FFT和IFFT函数源码 int nFrameRunCount 0;#pragma section…

数字信号处理基础(二):FFT和IFFT的使用以及详细分析代码书写思路

目录 1. fft和ifft的原理1.1 fft1.2 ifft 2. 书写代码思路3. 完整代码4. 结果图 1. fft和ifft的原理 1.1 fft fft是快速傅里叶变换&#xff0c;是MATLAB中计算信号频谱的函数&#xff0c;使用方法是fft(x)&#xff0c;直接对信号x进行fft计算。 由于fft函数计算信号的频谱是0…

信号处理中的反傅里叶变换(IFFT)原理

信号处理中&#xff0c;经常需要将信号转换到频域进行分析&#xff0c;有时候还会从频域转回时域&#xff0c;用到FFT和IFFT函数。 FFT变换是将信号从时域转换到频域&#xff0c;在时域看起来复杂的信号转换到频域看起来就方便容易了很多。但有时候也需要将频域信号转换到时域…

adb下载、安装、环境配置

一&#xff1a;adb安装 adb下载链接&#xff1a;https://pan.baidu.com/s/1Vd6KyZ6vT2Qtmhazwre4OQ 提取码&#xff1a;3dx1 安装&#xff1a; 1.双击adb.exe文件&#xff0c;并运行。 2.添加环境变量&#xff1a; 右击计算机–属性—高级系统设置—高级—环境变量—新建&…

windows下载安装adb(极其简单)

单独安装adb&#xff0c;不安装sdk 下载adb Google很好的心&#xff0c;直接放出ADB的档案供人下载。下档路径如下&#xff1a; Windows版本&#xff1a;https://dl.google.com/android/repository/platform-tools-latest-windows.zip Mac版本&#xff1a;https://dl.google…

ADB-adb命令安装app

下载adb 安装adb 将名称中含有adb的文件&#xff0c;和fastboot.exe复制到 c:/windows/system32目录将名称中含有adb的所有文件复制到 c:/windows/system目录将adb.exe和AdbWinApi.dll复制到c:/windows/SysWoW64目录 有线安装apk 连接上数据线&#xff0c;然后把手机开发者模…

adb详细教程(一)-下载安装与环境变量配置

对于Android开发来说&#xff0c;adb是再熟悉不过的调试工具 但其实对于移动端的测试来说&#xff0c;adb也是一个十分重要的、能够提高测试工作效率的工具。 文章目录 一、介绍二、下载地址三、安装四、配置环境变量 一、介绍 全称 adb全称全称为Android Debug Bridge&#x…

mac下载安装adb环境

目录 方法一1、下载安装包2、下载完成后进行解压&#xff0c;目录路径注意不得包含中文3、配置环境变量4、验证安装是否成功 方法二1、安装homebrew2、安装adb3、运行adb 方法一 1、下载安装包 安装包下载地址 &#xff1a;https://developer.android.com/studio/releases/pl…

adb工具下载安装

一、adb环境配置 adb即Android Debug Bridge&#xff0c;就是可以通过窗口命令&#xff0c;使在pc端可以调试安卓移动端的一个工具包 我这里是默认电脑已经安装SDK的&#xff0c;如果没有也没关系&#xff0c;直接网上下载一个adb工具包一样的https://developer.android.goo…

adb环境配置

adb环境配置 1.下载工具包 工具包&#xff1a;platform-tools_r30.0.4-windows.zip 获取途径1&#xff1a;链接: https://pan.baidu.com/s/17BiARFlgsQa2wDETmoJIvQ?pwddsd2 提取码: dsd2 获取途径2&#xff1a;https://developer.android.google.cn/studio/releases/plat…

android adb驱动官方下载,adb驱动下载

这里给你简单的介绍一下adb驱动:adb驱动就是电脑与android设备的通信的客户端驱动程序。使用它可以直接操作管理android模拟器或者真实的andriod设备。 adb驱动百科介绍: Android设备(如手机)连接PC时所需要的驱动程序,一般Android设备连接WinXP是无需安装驱动的。 adb的全称…