博客
关于我
vector构建邻接表和原始邻接表
阅读量:295 次
发布时间:2019-03-03

本文共 3349 字,大约阅读时间需要 11 分钟。

邻接表构造与遍历

在编程中,邻接表是一种常用的数据结构,用于表示图的边。它通过将每个节点的邻接信息存储在表中,使得节点的访问和遍历更加高效。以下将详细介绍如何使用邻接表构造图,并进行遍历操作。

1. 邻接表的构造

邻接表可以使用数组或向量来模拟。在本文中,我们将分别使用数组和向量两种方式来实现。

1.1 数组模拟邻接表

假设我们有 N 个节点,我们可以使用一个数组 s 来表示邻接表。每个节点 i 的邻接信息存储在 s[i] 中,具体包括以下结构:

struct st {    int to;  // 结点编号    int w;  // 权值    struct st *nx;  // 指向下一个结点};ll *link;  // 类型声明s[N];  // 邻接表的表头

初始化时,我们需要为每个节点分配空间,并将其下一个结点指针初始化为 NULL

for (int i = 1; i <= n; i++) {    s[i].next = NULL;}

然后,通过 add 函数添加边。add 函数会为指定的两个节点创建相应的邻接结点:

void add(int from, int to, int w) {    link p;    p = new ll;    p->to = to;    p->w = w;    p->nx = s[from].next;    s[from].next = p;}

这里需要注意,由于 s 是一个数组,我们需要预先分配足够的空间来存储所有节点的邻接信息。

1.2 向量模拟邻接表

除了数组,向量在现代编程中更为常用,特别是考虑到其动态分配特性。在向量中,我们可以使用结构体 st 来存储每个邻接信息:

#include 
using namespace std;struct st { int to; int w;};vector
s[N];

向量的初始化与数组类似,只需为每个节点清空邻接表:

for (int i = 1; i <= n; i++) {    s[i].clear();}

添加边的逻辑与数组版本一致,只是通过向量的 push_back 方法实现:

void add(int from, int to, int w) {    st t;    t.to = to;    t.w = w;    s[from].push_back(t);}

这种方式更加灵活,尤其是当节点数量不确定时。

2. 邻接表的遍历

邻接表的遍历可以通过深度优先搜索(DFS)或广度优先搜索(BFS)来实现。以下分别介绍这两种遍历方法。

2.1 深度优先搜索(DFS)

DFS通过递归的方式逐层访问节点,直到所有节点都被访问。实现时,可以使用递归函数,并使用一个标记数组 book 来记录已访问的节点:

void dfs(int x) {    book[x] = 1;    cout << x << " ";    link p;    p = s[x].next;    while (p) {        if (book[p->to] == 0) {            book[p->to] = 1;            dfs(p->to);        }        p = p->nx;    }}

这种方法适用于稀疏图,递归深度较大的情况下可能会导致栈溢出。

2.2 广度优先搜索(BFS)

BFS通过队列来逐层访问节点,实现时可以使用队列数据结构。以下是 bfs 函数的实现:

void bfs(int x) {    link p;    int q[N];    int r = 0, f = 0;    book[x] = 1;    q[r++] = x;    while (r != f) {        int t = q[f++];        p = s[t].next;        while (p) {            if (book[p->to] == 0) {                book[p->to] = 1;                q[r++] = p->to;            }            p = p->nx;        }    }}

这种方法在稠密图中表现更好,避免了递归深度的问题。

3. 示例代码

以下是完整的代码示例,展示了如何构造并遍历邻接表:

#include 
#include
using namespace std;struct st { int to; int w;};vector
s[N];void dfs(int x) { book[x] = 1; cout << x << " "; vector
::iterator it; it = s[x].begin(); while (it != s[x].end()) { if (book[it->to] == 0) { book[it->to] = 1; dfs(it->to); } it++; }}void bfs(int x) { int q[n]; int r = 0, f = 0; book[x] = 1; q[r++] = x; while (r != f) { int t = q[f++]; vector
current = s[t]; for (int i = 0; i < current.size(); i++) { if (book[current[i].to] == 0) { book[current[i].to] = 1; cout << current[i].to << " "; } q[r++] = current[i].to; } }}void add(int from, int to, int w) { st t; t.to = to; t.w = w; s[from].push_back(t);}int main() { int n; cin >> n; for (int i = 1; i <= n; i++) { s[i].clear(); } for (int i = 1; i <= n - 1; i++) { int x, y, w; scanf("%d %d %d", &x, &y, &w); add(x, y, w); add(y, x, w); } cout << "邻接表" << endl; for (int i = 1; i <= n; i++) { cout << "[" << i << "] "; for (auto p : s[i]) { cout << p.to << " "; } cout << endl; }}

4. 总结

通过上述方法,我们可以轻松构造并遍历邻接表。无论是使用数组还是向量,核心逻辑保持一致,主要区别在于数据结构的选择和使用方式。理解邻接表的构造与遍历是掌握图算法的基础,后续的高级算法如最短路径、连通性检查等都会基于此进行扩展。

转载地址:http://trel.baihongyu.com/

你可能感兴趣的文章
python 利用pandas读取本地中CSV文件的指定列 列名重命名 并保存回本地
查看>>
python 利用pyspark读取HDFS中CSV文件的指定列 列名重命名 并保存回HDFS
查看>>
python 利用pyttsx3文字转语音
查看>>
python 利用已有Ner模型进行数据清洗合并
查看>>
python 到大数据开发工程师_如何成为一个大数据开发工程师?
查看>>
python 加密解密(base64, AES)
查看>>
Python 和Java 哪个更适合做自动化测试?
查看>>
python 图片转ico
查看>>
python 图片转文字、语音转文字、文字转语音保存音频并朗读
查看>>
python 在包含类似字符\x16、\x12、\x某某的数组中将以\x开头的字符找出来的方法
查看>>
Python 在并行进程之间共享字典
查看>>
Python 垃圾收集器文档
查看>>
python 基于 wordcloud + jieba + matplotlib 生成词云
查看>>
python 基于detectron或mask_rcnn的mask遮罩区域进行图片截取
查看>>
Python编程:Tkinter图形界面设计(2)
查看>>
Python 基础 - Day 5 Learning Note - 模块 之 标准库:time (1)
查看>>
Python 基础一
查看>>
Python 基础知识点整理与分享,期盼你的交流!
查看>>
python 基础第七篇
查看>>
Python编程:Tkinter图形界面设计(1)
查看>>