数据结构(c++版):邻接表的实现

邻接表的基本概念

定义

邻接表是一种图的存储结构,它使用"链表+数组"的组合方式来存储图中的顶点和边信息。每个顶点对应一个链表,链表中存储与该顶点直接相连的所有邻接顶点。

核心思想

  • 数组部分:存储所有顶点信息
  • 链表部分:每个顶点维护一个链表,存储从该顶点出发的所有边

数学表示

对于图 G = (V, E),其中:

  • V = {v₁, v₂, ..., vₙ} 是顶点集合
  • E 是边集合

邻接表为每个顶点 vᵢ 维护一个邻接链表,包含所有与 vᵢ 相邻的顶点。

1.头文件引入

cpp 复制代码
#include<iostream>   // 提供输入输出功能(如cout)
#include<string>     // 提供字符串处理功能
using namespace std; // 使用标准命名空间,避免重复写std::

比喻 ​:就像建设城市交通网前,需要准备施工图纸材料清单


2. 图类定义与内部结构

cpp 复制代码
class Graph
{
private:
    struct EdgeNode  // 边结点结构:记录每条路线的详细信息
    {
        int vertex;   // 目标顶点编号(路线终点站)
        int weight;   // 边权重(路线距离或成本)
        EdgeNode* next;  // 指向下一条边(下一条路线)
    };
    
    struct VertexNode  // 顶点结点结构:每个交通枢纽站
    {
        int vertex;       // 顶点编号(站点代码)
        EdgeNode* firstEdge;  // 指向该站发出的第一条路线
    };
    
    int vertices;      // 顶点总数(枢纽站数量)
    VertexNode* nodes; // 动态顶点数组(所有站点集合)

比喻​:

  • VertexNode = 交通枢纽总站(如北京西站)
  • EdgeNode = 班次时刻表(记录发往哪个城市、距离多少)
  • nodes数组 = 全国所有火车站的集合

3. 构造函数:初始化交通网络

cpp 复制代码
Graph::Graph(int vertices)  // 参数:要创建的顶点数量
{
    this->vertices = vertices;  // 设置顶点总数
    this->nodes = new VertexNode[vertices];  // 动态创建顶点数组
    for (int i = 0; i < vertices; i++)
    {
        nodes[i].vertex = i;          // 为每个顶点编号(0,1,2...)
        nodes[i].firstEdge = NULL;    // 初始时没有发出的边
    }
};

比喻 ​:政府规划建设4个城市的交通枢纽站,目前只建好了空车站大楼 ,还没有开通任何班次


4. 析构函数:拆除整个网络

cpp 复制代码
Graph::~Graph()  // 对象销毁时自动调用,清理内存
{
    for (int i = 0; i < vertices; i++)  // 遍历每个顶点
    {
        EdgeNode* curr = nodes[i].firstEdge;  // 获取该顶点的第一条边
        while (curr)  // 当还有边结点存在时循环
        {
            EdgeNode* tmp = curr;     // 临时保存当前边结点
            curr = curr->next;        // 指针移动到下一个边结点
            delete tmp;               // 删除当前边结点
        }
    }
    delete[] nodes;  // 删除整个顶点数组
}

比喻​:城市拆迁时,需要:

  1. 逐个车站清理所有班次时刻表(边结点)
  2. 最后推平车站建筑(顶点数组)
  3. 顺序不能错,否则会造成内存浪费

5. 添加边:开通新路线

cpp 复制代码
void Graph::addEdge(int u, int v, int weight)
{
    EdgeNode* newnode = new EdgeNode;  // 创建新的边结点
    newnode->vertex = v;       // 设置目标顶点(路线终点)
    newnode->weight = weight;  // 设置边权重(路线距离)
    newnode->next = nodes[u].firstEdge;  // 新结点指向原第一条边
    nodes[u].firstEdge = newnode;       // 更新头指针指向新结点
}

比喻​:北京站(u=0)新开通到上海(v=1)的高铁:

  1. 制作新班次表(创建EdgeNode)
  2. 填写目的地和里程(vertex=v, weight=10)
  3. 插到最前面:新班次表放在现有班次表前面(头插法)
  4. 更新站内指示牌(修改firstEdge指针)

6. 打印边:显示所有路线信息

cpp 复制代码
void Graph::printEdge()
{
    for (int i = 0; i < vertices; i++)  // 遍历每个顶点
    {
        EdgeNode* curr = nodes[i].firstEdge;  // 获取该顶点第一条边
        cout << "Vertex" << i << ":";  // 打印顶点编号
        while (curr)  // 遍历该顶点的所有边
        {
            // 打印目标顶点和权重
            cout << curr->vertex << "(" << curr->weight << ") ";
            curr = curr->next;  // 移动到下一条边
        }
        cout << endl;  // 换行,准备打印下一个顶点
    }
}

比喻​:记者走访每个火车站,记录发车情况:

  • ​"Vertex0:2(20) 1(10)"​ = 北京站:发往广州(20km)、上海(10km)
  • 使用while循环逐个查看所有班次表

7. 主函数:测试交通网络

cpp 复制代码
int main()
{
    Graph g(4);  // 创建4个顶点的图(建设4个城市交通网)
    
    // 添加5条交通路线(起点,终点,距离)
    g.addEdge(0, 1, 10);  // 北京→上海,10公里
    g.addEdge(0, 2, 20);  // 北京→广州,20公里  
    g.addEdge(1, 3, 30);  // 上海→深圳,30公里
    g.addEdge(2, 3, 40);  // 广州→深圳,40公里
    g.addEdge(1, 2, 50);  // 上海→广州,50公里
    
    g.printEdge();  // 打印整个交通网络
    return 0;       // 程序正常结束
}

8. 程序输出结果

cpp 复制代码
Vertex0:2(20) 1(10)    ← 北京站发往广州、上海
Vertex1:2(50) 3(30)    ← 上海站发往广州、深圳  
Vertex2:3(40)          ← 广州站发往深圳
Vertex3:               ← 深圳站为终点站,无发出路线

9. 关键特点总结

  1. 头插法效率高:新边插入链表头部,时间复杂度O(1)
  2. 内存动态管理:使用new/delete手动管理内存
  3. 逆序存储:后添加的边在链表前面(与添加顺序相反)
  4. 避免内存泄漏:析构函数确保所有动态内存被正确释放

现实比喻 ​:这套系统就像铁路调度管理系统,高效管理复杂的交通网络关系!

相关推荐
wyiyiyi2 小时前
【数据结构+算法】进栈顺序推算、卡特兰数与逆波兰表达式
汇编·数据结构·笔记·算法
guguhaohao2 小时前
map和set,咕咕咕!
数据结构·c++
TL滕2 小时前
从0开始学算法——第二天(时间、空间复杂度)
数据结构·笔记·学习·算法
旺仔老馒头.4 小时前
【数据结构与算法】手撕排序算法(二)
c语言·数据结构·算法·排序算法
努力努力再努力wz4 小时前
【Linux进阶系列】:线程(上)
java·linux·运维·服务器·数据结构·c++·redis
czhc11400756635 小时前
Java117 最长公共前缀
java·数据结构·算法
吃着火锅x唱着歌5 小时前
LeetCode 2016.增量元素之间的最大差值
数据结构·算法·leetcode
西岭千秋雪_6 小时前
Zookeeper数据结构
java·数据结构·分布式·zookeeper
qk学算法7 小时前
力扣滑动窗口题目-76最小覆盖子串&&1234替换子串得到平衡字符串
数据结构·算法·leetcode