> 引用:[https://blog.csdn.net/zjw\_python/article/details/85158998](https://blog.csdn.net/zjw_python/article/details/85158998)
[toc]
# 图的存储
存储分为以下方法:
- 邻接矩阵
- 邻接表
- 十字链表
- 邻接多重表
## 邻接矩阵
用 `二维数组` 的方式来存储图结构。
- 无向图
![](https://img.kancloud.cn/76/eb/76eb4d4eca469db8f6400f86e7761736_492x718.png)
缺点:
1. 太浪费空间
2. 图中的顶点经常是动态的,需要添加和删除,二维数组尺寸是固定的不方便
- 有向图
![](https://img.kancloud.cn/bc/41/bc4174129bba3418a50bc147445bfd17_472x718.png)
- 有向带权图
![](https://img.kancloud.cn/7e/45/7e45162cd53057c6c51893372e24aa9c_1246x422.png)
## 邻接表
`数组+链表` 进行存储。
图的每一个顶点都是一个头节点,其后连接着该顶点能够直接达到的相邻顶点。
![](https://img.kancloud.cn/ff/a6/ffa66da7e9b5a08d1f1f4842a6d32942_832x330.png)
## 邻接多重表
邻接多重表是 `无向图` 的一种存储方式。
![](https://img.kancloud.cn/47/67/47670f4d3f5a577a10e2a1dcf56cdefd_1462x548.png)
## 逆邻接表
每一个顶点作为链表的头节点,后继节点所存储的是 `能够直接达到该顶点` 的相邻顶点。
![](https://img.kancloud.cn/13/c2/13c2f1d9f1d510dc148ca05d65779fc4_1542x596.png)
## 十字链表
每一个顶点作为链表的头节点,都可以有两个链:
1. 所有这个节点可以到达的节点
2. 所有可以到达该节点的节点
![](https://img.kancloud.cn/3d/bd/3dbd8dca0cfb3defc23c4bb517cef377_1598x1412.png)
# 代码实现-邻接表
~~~
class Graph {
constructor () {
this.vertices = []; // 用来存放图中的顶点
this.adjList = new Set(); // 用来存放图中的边
}
// 向图中添加一个新顶点
addVertex (v) {
if (!this.vertices.includes(v)) {
this.vertices.push(v);
this.adjList.set(v, []);
}
}
// 向图中添加a和b两个顶点之间的边
addEdge (a, b) {
// 如果图中没有顶点a,先添加顶点a
if (!this.adjList.has(a)) {
this.addVertex(a);
}
// 如果图中没有顶点b,先添加顶点b
if (!this.adjList.has(b)) {
this.addVertex(b);
}
this.adjList.get(a).push(b); // 在顶点a中添加指向顶点b的边
this.adjList.get(b).push(a); // 在顶点b中添加指向顶点a的边
}
// 获取图的vertices
getVertices () {
return this.vertices;
}
// 获取图中的adjList
getAdjList () {
return this.adjList;
}
toString() {
let s = '';
this.vertices.forEach((v) => {
s += `${v} -> `;
this.adjList.get(v).forEach((n) => {
s += `${n} `;
});
s += '\n';
});
return s;
}
}
~~~