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;
}
七、应用
-
社交网络 👥
- 好友关系
-
地图导航 🗺️
- 路线规划
-
编译器依赖 ⚙️
- 拓扑排序
-
网络路由 🌐
- 最短路径
八、下篇预告
下一篇我们将学习 图的遍历: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: 广度优先
💡 学习建议:图的存储方式要根据稀疏/稠密选择!
觉得有帮助就点赞+收藏+关注吧! 👍