深入理解邻接表存储结构

邻接表是一种用于存储图的数据结构,它以链表的方式存储相邻顶点之间的关系并记录对应权值。在图论中,邻接表也是一种常用的存储方式。

一、邻接表的定义

邻接表是指将每个顶点出边的信息存储在该顶点的链表中,由数组与链表组成。它表示了顶点之间的邻接关系,并且具有较好的扩展性,因为我们只需要新建一个链表即可实现顶点的添加。

邻接表的实现可以使用数组存储顶点元素,每个数组元素对应一个顶点,该元素存储了一个指向链表头部的指针,它指向该顶点的出边链表。链表中的每个节点则表示该顶点的一条出边,其中包含了该边指向的邻接节点。

// 伪代码示例
struct EdgeNode {
    int adjVex; // 邻接点的索引
    int weight; // 权值
    EdgeNode* next; // 指向下一个邻接节点的指针
};

struct VertexNode {
    DataType data; // 顶点数据域
    EdgeNode* firstEdge; // 指向第一条邻接边的指针
};

VertexNode adjList[maxSize]; // 定义邻接表

二、邻接表的优缺点

1. 优点

邻接表存储结构对于拥有稀疏的图来说,其空间复杂度相比于邻接矩阵来说,得到了极大的优化。因为邻接表只需存储每个顶点周边的关系,而邻接矩阵需要维护每个节点间的具体连接状态,所以邻接表尤其适合拥有大量存在孤立节点或连通度较低的图。

邻接表还能够表现图中的权值,因为每个节点都可以储存它的出边的权。这对于计算图的最短路、最小生成树等问题非常有用。

2. 缺点

邻接表的缺点在于它不擅长回答某些涉及到“定点目标”的问题,例如判断节点A和节点B是否相连。邻接表需要遍历A的所有邻接点才能判断A和B是否连通,这一点对时间复杂度有一定影响。

另外,相比于邻接矩阵,邻接表的建图时间和遍历时间都需要更多时间。

三、邻接表的实现

下面通过 C++ 代码实现从文件中读取图数据并将其存储为邻接表。本示例将读取文件中每一行数据,并通过空格分隔两个节点和对应的边权,最后将所有数据存储在邻接表中。

#include 
#include 
#include 
#include 
using namespace std;

const int MAXVEX = 100;
const int MAXSIZE = 10000;

typedef struct EdgeNode { // 边表节点结构体
    int adjvex; // 邻接点域,存储该顶点对应的下标
    int weight; // 权值
    struct EdgeNode* next; // 链域,指向下一个邻接点
} EdgeNode;

typedef struct VertexNode { // 顶点表节点结构体
    string data; // 顶点域,存储顶点信息
    int in; // 记录节点入度
    EdgeNode* firstedge; // 边表头指针
} VertexNode, AdjList[MAXVEX];

typedef struct GraphAdjList { // 定义邻接表结构体
    AdjList adjList;
    int numVertexes, numEdges; // 图的当前节点数和边数
} GraphAdjList;

bool createFromFile(string filename, GraphAdjList& GL); // 从文件中读取数据,建立邻接表

int main() {
    GraphAdjList G;
    if (createFromFile("input.txt", G)) {
        cout << "Read successfully." << endl;
    } else {
        cout << "File not found." <> GL.numVertexes >> GL.numEdges; // 读取节点数和边数
    vector temp(MAXSIZE, -1); // 定义零时数组
    int k = 0;
    for (int i = 0; i > GL.adjList[i].data;
        GL.adjList[i].in = 0;
        GL.adjList[i].firstedge = nullptr;
    }
    for (int j = 0; j > x >> y >> weight;
        temp[k++] = x;
        temp[k++] = y;
        temp[k++] = weight;
    }
    int sum = k / 3;
    for (int i = 0; i adjvex = n;
        e->weight = weight;
        e->next = GL.adjList[m].firstedge; // 插入到边表头部
        GL.adjList[m].firstedge = e;
        GL.adjList[n].in++; // 记录每个节点的入度
    }
    return true;
}

四、总结

邻接表是一种经典的图存储结构,采用链表的方式便于快速存储边的信息。邻接表能够很好地处理稀疏图,具有较好的扩展性,同时还记录了边的权重信息,在计算最短路等问题中获得了广泛应用。

当然,邻接表在某些涉及到“点与点之间的关系”问题的处理速度上可能会略逊于邻接矩阵,但是对于实现图的许多算法,它们所需求的时间仅仅是与顶点数量和边长有关的,这样在规模较大的图的处理方面具有明显的优势。

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/279338.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-12-20 15:03
下一篇 2024-12-20 15:03

相关推荐

  • Vue TS工程结构用法介绍

    在本篇文章中,我们将从多个方面对Vue TS工程结构进行详细的阐述,涵盖文件结构、路由配置、组件间通讯、状态管理等内容,并给出对应的代码示例。 一、文件结构 一个好的文件结构可以极…

    编程 2025-04-29
  • Python程序的三种基本控制结构

    控制结构是编程语言中非常重要的一部分,它们指导着程序如何在不同的情况下执行相应的指令。Python作为一种高级编程语言,也拥有三种基本的控制结构:顺序结构、选择结构和循环结构。 一…

    编程 2025-04-29
  • Lidar避障与AI结构光避障哪个更好?

    简单回答:Lidar避障适用于需要高精度避障的场景,而AI结构光避障更适用于需要快速响应的场景。 一、Lidar避障 Lidar,即激光雷达,通过激光束扫描环境获取点云数据,从而实…

    编程 2025-04-27
  • 深入解析Vue3 defineExpose

    Vue 3在开发过程中引入了新的API `defineExpose`。在以前的版本中,我们经常使用 `$attrs` 和` $listeners` 实现父组件与子组件之间的通信,但…

    编程 2025-04-25
  • 深入理解byte转int

    一、字节与比特 在讨论byte转int之前,我们需要了解字节和比特的概念。字节是计算机存储单位的一种,通常表示8个比特(bit),即1字节=8比特。比特是计算机中最小的数据单位,是…

    编程 2025-04-25
  • 深入理解Flutter StreamBuilder

    一、什么是Flutter StreamBuilder? Flutter StreamBuilder是Flutter框架中的一个内置小部件,它可以监测数据流(Stream)中数据的变…

    编程 2025-04-25
  • 深入探讨OpenCV版本

    OpenCV是一个用于计算机视觉应用程序的开源库。它是由英特尔公司创建的,现已由Willow Garage管理。OpenCV旨在提供一个易于使用的计算机视觉和机器学习基础架构,以实…

    编程 2025-04-25
  • Switch C:多选结构的利器

    在编写程序时,我们经常需要根据某些条件执行不同的代码,这时就需要使用选择结构。在C语言中,有if语句、switch语句等多种选择结构可供使用。其中,switch语句是一种非常强大的…

    编程 2025-04-25
  • 深入了解scala-maven-plugin

    一、简介 Scala-maven-plugin 是一个创造和管理 Scala 项目的maven插件,它可以自动生成基本项目结构、依赖配置、Scala文件等。使用它可以使我们专注于代…

    编程 2025-04-25
  • 深入了解LaTeX的脚注(latexfootnote)

    一、基本介绍 LaTeX作为一种排版软件,具有各种各样的功能,其中脚注(footnote)是一个十分重要的功能之一。在LaTeX中,脚注是用命令latexfootnote来实现的。…

    编程 2025-04-25

发表回复

登录后才能评论