邻接表

article/2025/8/27 22:35:29

邻接表:所谓邻接表(adjacency list),就是把从同一个顶点发出的边链接在同一个称为边链表的单链表中。边链表的每个结点代表一条边,称为边结点。每个边结点有2 个域:该边终点的序号,以及指向下一个边结点的指针。在邻接表中,还需要一个用于存储顶点信息的顶点数组。例如,图1.19(a)所示的有向图对应的邻接表如图(b)所示。在顶点数组中,每个元素有两个成员:一个成员用来存储顶点信息;另一个成员为该顶点的边链表的表头指针,指向该顶点的边链表。如果没有从某个顶点发出的边,则该顶点没有边链表,因此表头指针为空,如图1.19(b)中的顶点G。在该图中,如果指针为空,则用符号“∧”表示。


图1.19有向图的邻接表

在邻接表每个顶点的边链表中,各边结点所表示的边都是从该顶点发出的边,因此这种邻接表也称为出边表。采用邻接表存储图时,求顶点的出度很方便,只需要统计每个顶点的边链表中边结点的个数即可,但在求顶点的入度时就比较麻烦。在图1.19(b)中,顶点B 的边链表有3 个边结点,分别表示边<B, F>、<B, E>和<B, C>,因此顶点B 的出度为3;顶点C 的边链表中只有1 个边结点,表示边<C, E>,因此顶点C 的出度为1。如果需要统计各顶点的入度,可以采用逆邻接表存储表示图。所谓逆邻接表,也称为入边表,就是把进入同一个顶点的边链接在同一个边链表中。


图1.20有向图的逆邻接表

例如,图1.20(a)所示的有向图对应的逆邻接表如图(b)所示。在图1.20(b)中,顶点B 的边链表有2 个边结点,分别表示边<E, B>和<A, B>,因此顶点B 的入度为2;顶点C 的边链表中也有2个边结点,分别表示边<D, C>和<B, C>,因此顶点C 的入度也为2。

接下来以有向图为例介绍邻接表的实现方法。为了方便求解顶点的出度和入度,在实现时,把出边表和入边表同时包含在图的邻接表结构中。有向图的邻接表用一个结构体LGraph 存储表示,其中包含3 个成员:顶点数组vertexs,顶点数vexnum 和边的数目arcnum,其中顶点数组vertexs 中每个元素都是VNode 结构体变量。VNode 结构体变量存储图中每个顶点,它包含3 个成员:顶点信息、出边表的表头指针和入边表的表头指针,其中后面两个成员都是ArcNode 结构体类型的指针。ArcNode 结构体存储边链表中的边结点,它包含2 个成员:边的另一个邻接点的序号,以及指向下一个边结点的指针。

例题:

问题描述:用邻接表存储有向图,并输出各顶点的出度和入度。

输入描述输入文件中包含多个测试数据,每个测试数据描述了一个无权有向图。每个测试数据的第一行为两个正整数n 和m,1≤ n ≤ 100,1≤ m ≤ 500,分别表示该有向图的顶点数目和边数,顶点的序号从1 开始计起。接下来有m 行,每行为两个正整数,用空格隔开,分别表示一条边的起点和终点。每条边出现一次且仅一次,图中不存在自身环和重边。输入文件最后一行为0 0,表示输入数据结束。

输出描述:

对输入文件中的每个有向图,输出两行:第1 行为n 个正整数,表示每个顶点的出度;第2行也为n 个正整数,表示每个顶点的入度。每两个正整数之间用一个空格隔开,每行的最后一个正整数之后没有空格。

样例输入:

4 7
1 4
2 1
2 2
2 3
2 3
4 2
4 3

0 0

样例输出:

1 4 0 2

1 2 3 1

代码实现:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#define INF 99999999
using namespace std;
const int maxn=105;
struct ArcNode{//边结点int adjvex;//有向边的另一个邻接点的序号ArcNode *nextarc;//指向下一个边结点的指针
};
struct VNode{//顶点int data;//顶点信息ArcNode *head1;//出边表的表头指针ArcNode *head2;//入边表的表头指针
};
struct LGraph{//图的邻接表存储结构VNode vertexs[maxn];//顶点数组int vexnum,arcnum;//顶点数和边数
}LG;
void CreateLG(){ArcNode *p;//用来构造边链表的边结点指针int v1,v2;//LG.vexnum=LG.arcnum=0;//scanf("%d %d",&LG.vexnum,&LG.arcnum);for(int i=0;i<LG.vexnum;i++){//初始化表头指针为空LG.vertexs[i].head1=LG.vertexs[i].head2=NULL;}for(int i=0;i<LG.arcnum;i++){scanf("%d %d",&v1,&v2);v1--,v2--;p = new ArcNode;//假定有足够空间p->adjvex = v2;p->nextarc = LG.vertexs[v1].head1;//插入链表LG.vertexs[v1].head1=p;p = new ArcNode;p->adjvex = v1;p->nextarc = LG.vertexs[v2].head2;LG.vertexs[v2].head2=p;}
}
void DeleteLG(){ArcNode *p;//用来指向边链表中各边结点的指针for(int i=0;i<LG.vexnum;i++){p=LG.vertexs[i].head1;//释放第i个顶点出边表各边节点所占的存储空间while(p!=NULL){LG.vertexs[i].head1=p->nextarc;delete p;p=LG.vertexs[i].head1;}p=LG.vertexs[i].head2;//释放第i个顶点入边表各边节点所占的存储空间while(p!=NULL){LG.vertexs[i].head2=p->nextarc;delete p;p=LG.vertexs[i].head2;}}
}
int main()
{int id,od;//顶点的入度跟出度ArcNode *p;//用来遍历边链表的边结点指针while(scanf("%d %d",&LG.vexnum,&LG.arcnum)){if(LG.arcnum+LG.vexnum==0)break;CreateLG();for(int i=0;i<LG.vexnum;i++){//统计各顶点出度并输出od=0;p=LG.vertexs[i].head1;while(p!=NULL){od++;p=p->nextarc;}if(i==0) printf("%d",od);else printf(" %d",od);}printf("\n");for(int i=0;i<LG.vexnum;i++){//统计各顶点入度并输出id=0;p=LG.vertexs[i].head2;while(p!=NULL){id++;p=p->nextarc;}if(i==0) printf("%d",id);else printf(" %d",id);}printf("\n");DeleteLG();//释放}return 0;
}

  • 邻接表的简单实现
typedef struct  
{  int to;  int w;  int next;  
}Edge;  
Edge e[MAX];  
int pre[MAX];  
//初始化  
memset(pre,-1,sizeof(pre));  
//输入  
scanf("%d %d %d",&from,&to,&w1);  
e[i].to = to; 
e[i].w = w1; 
e[i].next = pre[from]; 
pre[from] = i++;  
上面这段代码中,边的结构体Edge由三个元素组成:弧头结点序号,边权值,下一条边的序号。e[i]指的是第i条边。pre[i]记录的是从当前输入的情况来看,序号为i的弧尾结点发出的第一条边的序号是pre[i]。



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

相关文章

图的邻接表

邻接表 图的邻接表存储方法跟树的孩子链表示法相类似&#xff0c;是一种顺序分配和链式分配相结合的存储结构。如这个表头结点所对应的顶点存在相邻顶点&#xff0c;则把相邻顶点依次存放于表头结点所指向的单向链表中。如词条概念图所示&#xff0c;表结点存放的是邻接顶点在…

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

目录 什么是邻接表&#xff1f; 邻接表&#xff1a;定义 邻接表&#xff1a;相关类 邻接表&#xff1a;基本操作 1&#xff09;创建无向网 2&#xff09;创建有向网 3&#xff09;顶点定位 4&#xff09;插入边 5&#xff09;第一个邻接点 6&#xff09;查询下一个邻…

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

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…