13-图的基础:存储与表示

C语言数据结构系列:图基础篇

C语言数据结构系列(十三):图的基础------存储与表示

🎯 本篇目标 :理解图的概念,掌握邻接矩阵和邻接表两种存储方式!

📝 摘要 :本文是 C 语言数据结构系列第十三篇,系统讲解图(Graph)的基础概念与两种核心存储方式。首先介绍图的定义、术语(顶点、边、有向/无向、带权等)与类型;随后重点剖析邻接矩阵 (二维数组,查询快 O(1),适合稠密图)和邻接表(链表存储,节省空间 O(V+E),适合稀疏图)的原理、图解、创建代码及优缺点;最后通过对比表格总结两者适用场景,并给出完整可运行的 C 语言示例。适合正在学习数据结构、想掌握图存储实现的读者。


一、前言

哈喽小伙伴们!👋

今天我们进入图(Graph)的世界!图是最复杂的数据结构,可以表示各种关系

  • 🗺️ 地图导航
  • 👥 社交网络
  • 🌐 互联网
  • 📊 依赖关系

#mermaid-svg-cjZ0o2yAXcFXjDof{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-cjZ0o2yAXcFXjDof .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-cjZ0o2yAXcFXjDof .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-cjZ0o2yAXcFXjDof .error-icon{fill:#552222;}#mermaid-svg-cjZ0o2yAXcFXjDof .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-cjZ0o2yAXcFXjDof .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-cjZ0o2yAXcFXjDof .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-cjZ0o2yAXcFXjDof .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-cjZ0o2yAXcFXjDof .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-cjZ0o2yAXcFXjDof .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-cjZ0o2yAXcFXjDof .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-cjZ0o2yAXcFXjDof .marker{fill:#333333;stroke:#333333;}#mermaid-svg-cjZ0o2yAXcFXjDof .marker.cross{stroke:#333333;}#mermaid-svg-cjZ0o2yAXcFXjDof svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-cjZ0o2yAXcFXjDof p{margin:0;}#mermaid-svg-cjZ0o2yAXcFXjDof .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-cjZ0o2yAXcFXjDof .cluster-label text{fill:#333;}#mermaid-svg-cjZ0o2yAXcFXjDof .cluster-label span{color:#333;}#mermaid-svg-cjZ0o2yAXcFXjDof .cluster-label span p{background-color:transparent;}#mermaid-svg-cjZ0o2yAXcFXjDof .label text,#mermaid-svg-cjZ0o2yAXcFXjDof span{fill:#333;color:#333;}#mermaid-svg-cjZ0o2yAXcFXjDof .node rect,#mermaid-svg-cjZ0o2yAXcFXjDof .node circle,#mermaid-svg-cjZ0o2yAXcFXjDof .node ellipse,#mermaid-svg-cjZ0o2yAXcFXjDof .node polygon,#mermaid-svg-cjZ0o2yAXcFXjDof .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-cjZ0o2yAXcFXjDof .rough-node .label text,#mermaid-svg-cjZ0o2yAXcFXjDof .node .label text,#mermaid-svg-cjZ0o2yAXcFXjDof .image-shape .label,#mermaid-svg-cjZ0o2yAXcFXjDof .icon-shape .label{text-anchor:middle;}#mermaid-svg-cjZ0o2yAXcFXjDof .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-cjZ0o2yAXcFXjDof .rough-node .label,#mermaid-svg-cjZ0o2yAXcFXjDof .node .label,#mermaid-svg-cjZ0o2yAXcFXjDof .image-shape .label,#mermaid-svg-cjZ0o2yAXcFXjDof .icon-shape .label{text-align:center;}#mermaid-svg-cjZ0o2yAXcFXjDof .node.clickable{cursor:pointer;}#mermaid-svg-cjZ0o2yAXcFXjDof .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-cjZ0o2yAXcFXjDof .arrowheadPath{fill:#333333;}#mermaid-svg-cjZ0o2yAXcFXjDof .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-cjZ0o2yAXcFXjDof .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-cjZ0o2yAXcFXjDof .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cjZ0o2yAXcFXjDof .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-cjZ0o2yAXcFXjDof .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cjZ0o2yAXcFXjDof .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-cjZ0o2yAXcFXjDof .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-cjZ0o2yAXcFXjDof .cluster text{fill:#333;}#mermaid-svg-cjZ0o2yAXcFXjDof .cluster span{color:#333;}#mermaid-svg-cjZ0o2yAXcFXjDof div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-cjZ0o2yAXcFXjDof .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-cjZ0o2yAXcFXjDof rect.text{fill:none;stroke-width:0;}#mermaid-svg-cjZ0o2yAXcFXjDof .icon-shape,#mermaid-svg-cjZ0o2yAXcFXjDof .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cjZ0o2yAXcFXjDof .icon-shape p,#mermaid-svg-cjZ0o2yAXcFXjDof .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-cjZ0o2yAXcFXjDof .icon-shape .label rect,#mermaid-svg-cjZ0o2yAXcFXjDof .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cjZ0o2yAXcFXjDof .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-cjZ0o2yAXcFXjDof .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-cjZ0o2yAXcFXjDof :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 北京
上海
广州
深圳

让我们开始今天的学习吧! 🚀


二、图的基本概念

2.1 什么是图?

图(Graph)顶点(Vertex)边(Edge) 组成,表示多对多的关系。

2.2 图的术语

术语 说明 示例
顶点 节点 城市
连接关系 道路
有向图 边有方向 微博关注
无向图 边无方向 微信好友
带权图 边有权值 距离/费用
完全图 任意两点都有边 -
连通图 任意两点可达 -

2.3 图的类型

#mermaid-svg-tdqEfLMJ1YS5zRrr{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-tdqEfLMJ1YS5zRrr .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-tdqEfLMJ1YS5zRrr .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-tdqEfLMJ1YS5zRrr .error-icon{fill:#552222;}#mermaid-svg-tdqEfLMJ1YS5zRrr .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-tdqEfLMJ1YS5zRrr .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-tdqEfLMJ1YS5zRrr .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-tdqEfLMJ1YS5zRrr .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-tdqEfLMJ1YS5zRrr .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-tdqEfLMJ1YS5zRrr .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-tdqEfLMJ1YS5zRrr .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-tdqEfLMJ1YS5zRrr .marker{fill:#333333;stroke:#333333;}#mermaid-svg-tdqEfLMJ1YS5zRrr .marker.cross{stroke:#333333;}#mermaid-svg-tdqEfLMJ1YS5zRrr svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-tdqEfLMJ1YS5zRrr p{margin:0;}#mermaid-svg-tdqEfLMJ1YS5zRrr .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-tdqEfLMJ1YS5zRrr .cluster-label text{fill:#333;}#mermaid-svg-tdqEfLMJ1YS5zRrr .cluster-label span{color:#333;}#mermaid-svg-tdqEfLMJ1YS5zRrr .cluster-label span p{background-color:transparent;}#mermaid-svg-tdqEfLMJ1YS5zRrr .label text,#mermaid-svg-tdqEfLMJ1YS5zRrr span{fill:#333;color:#333;}#mermaid-svg-tdqEfLMJ1YS5zRrr .node rect,#mermaid-svg-tdqEfLMJ1YS5zRrr .node circle,#mermaid-svg-tdqEfLMJ1YS5zRrr .node ellipse,#mermaid-svg-tdqEfLMJ1YS5zRrr .node polygon,#mermaid-svg-tdqEfLMJ1YS5zRrr .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-tdqEfLMJ1YS5zRrr .rough-node .label text,#mermaid-svg-tdqEfLMJ1YS5zRrr .node .label text,#mermaid-svg-tdqEfLMJ1YS5zRrr .image-shape .label,#mermaid-svg-tdqEfLMJ1YS5zRrr .icon-shape .label{text-anchor:middle;}#mermaid-svg-tdqEfLMJ1YS5zRrr .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-tdqEfLMJ1YS5zRrr .rough-node .label,#mermaid-svg-tdqEfLMJ1YS5zRrr .node .label,#mermaid-svg-tdqEfLMJ1YS5zRrr .image-shape .label,#mermaid-svg-tdqEfLMJ1YS5zRrr .icon-shape .label{text-align:center;}#mermaid-svg-tdqEfLMJ1YS5zRrr .node.clickable{cursor:pointer;}#mermaid-svg-tdqEfLMJ1YS5zRrr .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-tdqEfLMJ1YS5zRrr .arrowheadPath{fill:#333333;}#mermaid-svg-tdqEfLMJ1YS5zRrr .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-tdqEfLMJ1YS5zRrr .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-tdqEfLMJ1YS5zRrr .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-tdqEfLMJ1YS5zRrr .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-tdqEfLMJ1YS5zRrr .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-tdqEfLMJ1YS5zRrr .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-tdqEfLMJ1YS5zRrr .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-tdqEfLMJ1YS5zRrr .cluster text{fill:#333;}#mermaid-svg-tdqEfLMJ1YS5zRrr .cluster span{color:#333;}#mermaid-svg-tdqEfLMJ1YS5zRrr div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-tdqEfLMJ1YS5zRrr .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-tdqEfLMJ1YS5zRrr rect.text{fill:none;stroke-width:0;}#mermaid-svg-tdqEfLMJ1YS5zRrr .icon-shape,#mermaid-svg-tdqEfLMJ1YS5zRrr .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-tdqEfLMJ1YS5zRrr .icon-shape p,#mermaid-svg-tdqEfLMJ1YS5zRrr .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-tdqEfLMJ1YS5zRrr .icon-shape .label rect,#mermaid-svg-tdqEfLMJ1YS5zRrr .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-tdqEfLMJ1YS5zRrr .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-tdqEfLMJ1YS5zRrr .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-tdqEfLMJ1YS5zRrr :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 有向图
A
B
C
无向图
A
B
C


三、邻接矩阵

3.1 什么是邻接矩阵?

💡 用二维数组 表示图,matrix[i][j]=1 表示i和j有边

c 复制代码
#define MAX_VERTEX 100

typedef struct {
    char vexs[MAX_VERTEX];     // 顶点表
    int arc[MAX_VERTEX][MAX_VERTEX];  // 邻接矩阵
    int vexNum, arcNum;
} MGraph;

3.2 图解

#mermaid-svg-nvgxat5FpwrFccV7{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-nvgxat5FpwrFccV7 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-nvgxat5FpwrFccV7 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-nvgxat5FpwrFccV7 .error-icon{fill:#552222;}#mermaid-svg-nvgxat5FpwrFccV7 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-nvgxat5FpwrFccV7 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-nvgxat5FpwrFccV7 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-nvgxat5FpwrFccV7 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-nvgxat5FpwrFccV7 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-nvgxat5FpwrFccV7 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-nvgxat5FpwrFccV7 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-nvgxat5FpwrFccV7 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-nvgxat5FpwrFccV7 .marker.cross{stroke:#333333;}#mermaid-svg-nvgxat5FpwrFccV7 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-nvgxat5FpwrFccV7 p{margin:0;}#mermaid-svg-nvgxat5FpwrFccV7 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-nvgxat5FpwrFccV7 .cluster-label text{fill:#333;}#mermaid-svg-nvgxat5FpwrFccV7 .cluster-label span{color:#333;}#mermaid-svg-nvgxat5FpwrFccV7 .cluster-label span p{background-color:transparent;}#mermaid-svg-nvgxat5FpwrFccV7 .label text,#mermaid-svg-nvgxat5FpwrFccV7 span{fill:#333;color:#333;}#mermaid-svg-nvgxat5FpwrFccV7 .node rect,#mermaid-svg-nvgxat5FpwrFccV7 .node circle,#mermaid-svg-nvgxat5FpwrFccV7 .node ellipse,#mermaid-svg-nvgxat5FpwrFccV7 .node polygon,#mermaid-svg-nvgxat5FpwrFccV7 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-nvgxat5FpwrFccV7 .rough-node .label text,#mermaid-svg-nvgxat5FpwrFccV7 .node .label text,#mermaid-svg-nvgxat5FpwrFccV7 .image-shape .label,#mermaid-svg-nvgxat5FpwrFccV7 .icon-shape .label{text-anchor:middle;}#mermaid-svg-nvgxat5FpwrFccV7 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-nvgxat5FpwrFccV7 .rough-node .label,#mermaid-svg-nvgxat5FpwrFccV7 .node .label,#mermaid-svg-nvgxat5FpwrFccV7 .image-shape .label,#mermaid-svg-nvgxat5FpwrFccV7 .icon-shape .label{text-align:center;}#mermaid-svg-nvgxat5FpwrFccV7 .node.clickable{cursor:pointer;}#mermaid-svg-nvgxat5FpwrFccV7 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-nvgxat5FpwrFccV7 .arrowheadPath{fill:#333333;}#mermaid-svg-nvgxat5FpwrFccV7 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-nvgxat5FpwrFccV7 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-nvgxat5FpwrFccV7 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nvgxat5FpwrFccV7 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-nvgxat5FpwrFccV7 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nvgxat5FpwrFccV7 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-nvgxat5FpwrFccV7 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-nvgxat5FpwrFccV7 .cluster text{fill:#333;}#mermaid-svg-nvgxat5FpwrFccV7 .cluster span{color:#333;}#mermaid-svg-nvgxat5FpwrFccV7 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-nvgxat5FpwrFccV7 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-nvgxat5FpwrFccV7 rect.text{fill:none;stroke-width:0;}#mermaid-svg-nvgxat5FpwrFccV7 .icon-shape,#mermaid-svg-nvgxat5FpwrFccV7 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nvgxat5FpwrFccV7 .icon-shape p,#mermaid-svg-nvgxat5FpwrFccV7 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-nvgxat5FpwrFccV7 .icon-shape .label rect,#mermaid-svg-nvgxat5FpwrFccV7 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nvgxat5FpwrFccV7 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-nvgxat5FpwrFccV7 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-nvgxat5FpwrFccV7 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} A
B
C

邻接矩阵:

复制代码
   A  B  C
A [0, 1, 1]
B [1, 0, 1]
C [1, 1, 0]

3.3 创建图

c 复制代码
void createGraph(MGraph *G, char vexs[], int n, int edges[][2], int m) {
    G->vexNum = n;
    G->arcNum = m;
    
    // 初始化顶点
    for (int i = 0; i < n; i++) {
        G->vexs[i] = vexs[i];
    }
    
    // 初始化矩阵
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            G->arc[i][j] = 0;
        }
    }
    
    // 填充边
    for (int i = 0; i < m; i++) {
        int v1 = edges[i][0];
        int v2 = edges[i][1];
        G->arc[v1][v2] = 1;
        G->arc[v2][v1] = 1;  // 无向图
    }
}

3.4 优缺点

优点 缺点
实现简单 空间O(V²)
查询快O(1) 稀疏图浪费空间
适合稠密图 -

四、邻接表

4.1 什么是邻接表?

💡 用链表存储每个顶点的邻接点,节省稀疏图的空间

c 复制代码
typedef struct ArcNode {
    int adjvex;
    struct ArcNode *next;
} ArcNode;

typedef struct {
    char data;
    ArcNode *first;
} VNode;

typedef struct {
    VNode vertices[MAX_VERTEX];
    int vexNum, arcNum;
} ALGraph;

4.2 图解

复制代码
图:
A -- B
A -- C
B -- C

邻接表:
A -> B -> C -> NULL
B -> A -> C -> NULL
C -> A -> B -> NULL

4.3 创建图

c 复制代码
void createGraph(ALGraph *G, char vexs[], int n, int edges[][2], int m) {
    G->vexNum = n;
    G->arcNum = m;
    
    for (int i = 0; i < n; i++) {
        G->vertices[i].data = vexs[i];
        G->vertices[i].first = NULL;
    }
    
    for (int i = 0; i < m; i++) {
        int v1 = edges[i][0];
        int v2 = edges[i][1];
        
        ArcNode *node = (ArcNode*)malloc(sizeof(ArcNode));
        node->adjvex = v2;
        node->next = G->vertices[v1].first;
        G->vertices[v1].first = node;
        
        node = (ArcNode*)malloc(sizeof(ArcNode));
        node->adjvex = v1;
        node->next = G->vertices[v2].first;
        G->vertices[v2].first = node;
    }
}

4.4 优缺点

优点 缺点
空间O(V+E) 查询慢O(度)
适合稀疏图 实现稍复杂
节省空间 -

五、两种存储方式对比

特性 邻接矩阵 邻接表
空间 O(V²) O(V+E)
查询边 O(1) O(度)
遍历邻接点 O(V) O(度)
适用场景 稠密图 稀疏图

六、完整示例

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define MAX_VERTEX 100

// 邻接矩阵
typedef struct {
    char vexs[MAX_VERTEX];
    int arc[MAX_VERTEX][MAX_VERTEX];
    int vexNum, arcNum;
} MGraph;

// 邻接表
typedef struct ArcNode {
    int adjvex;
    struct ArcNode *next;
} ArcNode;

typedef struct {
    char data;
    ArcNode *first;
} VNode;

typedef struct {
    VNode vertices[MAX_VERTEX];
    int vexNum, arcNum;
} ALGraph;

// 查找顶点下标
int locateVex(MGraph *G, char v) {
    for (int i = 0; i < G->vexNum; i++) {
        if (G->vexs[i] == v) return i;
    }
    return -1;
}

// 创建无向图(邻接矩阵)
void createMGraph(MGraph *G) {
    printf("输入顶点数和边数: ");
    scanf("%d %d", &G->vexNum, &G->arcNum);
    
    printf("输入顶点: ");
    for (int i = 0; i < G->vexNum; i++) {
        scanf(" %c", &G->vexs[i]);
    }
    
    for (int i = 0; i < G->vexNum; i++) {
        for (int j = 0; j < G->vexNum; j++) {
            G->arc[i][j] = 0;
        }
    }
    
    printf("输入边(如 AB):\n");
    for (int i = 0; i < G->arcNum; i++) {
        char v1, v2;
        scanf(" %c%c", &v1, &v2);
        int i1 = locateVex(G, v1);
        int i2 = locateVex(G, v2);
        G->arc[i1][i2] = 1;
        G->arc[i2][i1] = 1;
    }
}

// 打印邻接矩阵
void printMGraph(MGraph *G) {
    printf("\n邻接矩阵:\n  ");
    for (int i = 0; i < G->vexNum; i++) {
        printf("%c ", G->vexs[i]);
    }
    printf("\n");
    for (int i = 0; i < G->vexNum; i++) {
        printf("%c ", G->vexs[i]);
        for (int j = 0; j < G->vexNum; j++) {
            printf("%d ", G->arc[i][j]);
        }
        printf("\n");
    }
}

// 打印邻接表
void printALGraph(ALGraph *G) {
    printf("\n邻接表:\n");
    for (int i = 0; i < G->vexNum; i++) {
        printf("%c -> ", G->vertices[i].data);
        ArcNode *p = G->vertices[i].first;
        while (p) {
            printf("%d ", p->adjvex);
            p = p->next;
        }
        printf("\n");
    }
}

int main() {
    MGraph G;
    createMGraph(&G);
    printMGraph(&G);
    return 0;
}

七、应用

  1. 社交网络 👥

    • 好友关系
  2. 地图导航 🗺️

    • 路线规划
  3. 编译器依赖 ⚙️

    • 拓扑排序
  4. 网络路由 🌐

    • 最短路径

八、下篇预告

下一篇我们将学习 图的遍历:DFS与BFS
#mermaid-svg-YQFaDAPxGsTRLYmt{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-YQFaDAPxGsTRLYmt .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-YQFaDAPxGsTRLYmt .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-YQFaDAPxGsTRLYmt .error-icon{fill:#552222;}#mermaid-svg-YQFaDAPxGsTRLYmt .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-YQFaDAPxGsTRLYmt .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-YQFaDAPxGsTRLYmt .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-YQFaDAPxGsTRLYmt .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-YQFaDAPxGsTRLYmt .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-YQFaDAPxGsTRLYmt .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-YQFaDAPxGsTRLYmt .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-YQFaDAPxGsTRLYmt .marker{fill:#333333;stroke:#333333;}#mermaid-svg-YQFaDAPxGsTRLYmt .marker.cross{stroke:#333333;}#mermaid-svg-YQFaDAPxGsTRLYmt svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-YQFaDAPxGsTRLYmt p{margin:0;}#mermaid-svg-YQFaDAPxGsTRLYmt .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-YQFaDAPxGsTRLYmt .cluster-label text{fill:#333;}#mermaid-svg-YQFaDAPxGsTRLYmt .cluster-label span{color:#333;}#mermaid-svg-YQFaDAPxGsTRLYmt .cluster-label span p{background-color:transparent;}#mermaid-svg-YQFaDAPxGsTRLYmt .label text,#mermaid-svg-YQFaDAPxGsTRLYmt span{fill:#333;color:#333;}#mermaid-svg-YQFaDAPxGsTRLYmt .node rect,#mermaid-svg-YQFaDAPxGsTRLYmt .node circle,#mermaid-svg-YQFaDAPxGsTRLYmt .node ellipse,#mermaid-svg-YQFaDAPxGsTRLYmt .node polygon,#mermaid-svg-YQFaDAPxGsTRLYmt .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-YQFaDAPxGsTRLYmt .rough-node .label text,#mermaid-svg-YQFaDAPxGsTRLYmt .node .label text,#mermaid-svg-YQFaDAPxGsTRLYmt .image-shape .label,#mermaid-svg-YQFaDAPxGsTRLYmt .icon-shape .label{text-anchor:middle;}#mermaid-svg-YQFaDAPxGsTRLYmt .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-YQFaDAPxGsTRLYmt .rough-node .label,#mermaid-svg-YQFaDAPxGsTRLYmt .node .label,#mermaid-svg-YQFaDAPxGsTRLYmt .image-shape .label,#mermaid-svg-YQFaDAPxGsTRLYmt .icon-shape .label{text-align:center;}#mermaid-svg-YQFaDAPxGsTRLYmt .node.clickable{cursor:pointer;}#mermaid-svg-YQFaDAPxGsTRLYmt .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-YQFaDAPxGsTRLYmt .arrowheadPath{fill:#333333;}#mermaid-svg-YQFaDAPxGsTRLYmt .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-YQFaDAPxGsTRLYmt .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-YQFaDAPxGsTRLYmt .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YQFaDAPxGsTRLYmt .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-YQFaDAPxGsTRLYmt .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YQFaDAPxGsTRLYmt .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-YQFaDAPxGsTRLYmt .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-YQFaDAPxGsTRLYmt .cluster text{fill:#333;}#mermaid-svg-YQFaDAPxGsTRLYmt .cluster span{color:#333;}#mermaid-svg-YQFaDAPxGsTRLYmt div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-YQFaDAPxGsTRLYmt .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-YQFaDAPxGsTRLYmt rect.text{fill:none;stroke-width:0;}#mermaid-svg-YQFaDAPxGsTRLYmt .icon-shape,#mermaid-svg-YQFaDAPxGsTRLYmt .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-YQFaDAPxGsTRLYmt .icon-shape p,#mermaid-svg-YQFaDAPxGsTRLYmt .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-YQFaDAPxGsTRLYmt .icon-shape .label rect,#mermaid-svg-YQFaDAPxGsTRLYmt .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-YQFaDAPxGsTRLYmt .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-YQFaDAPxGsTRLYmt .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-YQFaDAPxGsTRLYmt :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} DFS: 深度优先
BFS: 广度优先


💡 学习建议:图的存储方式要根据稀疏/稠密选择!

觉得有帮助就点赞+收藏+关注吧! 👍

相关推荐
青山木2 小时前
Hot 100 --- 划分字母区间
java·数据结构·算法·leetcode·贪心算法
橘子汽水1683 小时前
Leetcode 208,207实现Trie前缀树,课程表
java·数据结构·算法·leetcode
wabs6663 小时前
关于二叉树【力扣116.填充每个节点的下一个右侧节点指针的思考】
数据结构·c++·算法·leetcode·二叉树·层序遍历
船厂电气自动化ai大模型3 小时前
AI大模型与数学 第73课 秩的核心定义、矩阵秩的通用求解方法
开发语言·数据结构·机器学习
动词ing3 小时前
【学习笔记】数据结构(哈希表基础+哈希集合+哈希映射+计数+查找)
数据结构·学习·哈希算法
不会就选b13 小时前
算法日常・每日刷题--<贪心>7
数据结构·算法·leetcode
爱吃苹果的日记本15 小时前
数据结构第一课
c语言·数据结构·数据库·学习·c#
张小姐的猫15 小时前
【AI大模型接入SDK】 —— Gemini接入封装
android·数据结构·数据库·c++·人工智能·python