5月16-5月18日学习内容
文章目录
- 一、图是什么
- 二、图的存储
- 1、直接存边法
- 2、邻接矩阵法
- 3、邻接表法
- 4、链式前向星
- 时间复杂度分析
- 三、图的遍历
- DFS
- BFS
- 四、拓扑排序(今天实在没时间写了,明天写)
一、图是什么
这是oi.wiki给的定义
简而言之,图就是一些点和边所组成的数据结构。而图,也有很多分类,如一些图是连在一起的,称为连通图;另一些不联通的图呢,则称为非连通图。一些图标有方向,称为有向图;另一些图没有方向,称为无向图。而更复杂的图呢,带有权值,另一些图则没有权值。对于点来说,与他相连的边的个数称为它的度数,而在有向图中,一个点发出去的边的个数称为出度,反之为入度。
二、图的存储
一般来说,图的存储分为4种形式:直接存边、邻接矩阵、邻接表和链式前向星
1、直接存边法
这种方法呢,比较简单,没有用到队列、链表等数据结构。但是,正因为没有用到高级数据结构,时间复杂度就会很高。
直接存边法:每次输入u,v,直接将u,v存入数组a[][2]中。
for(int i = 1; i <= m; i++){
cin >> u >> v;
a[i][1] = u, a[i][2] = v;
}
2、邻接矩阵法
这种方法是用一个布尔类型的二维数组实现的,是一种很常用的方法。
邻接矩阵法:若a[u][v]==1,说明u->v存在直接路径,反之,则不存在直接路径。
for(int i = 1; i <= m; i++){
cin >> u >> v;
a[u][v] = 1;//有向图
a[u][v] = a[v][u] = 1;//无向图
此方法只适用于稠密图,不适用于稀疏图。(空间复杂度大)
3、邻接表法
邻接表法:用一个二维vector来实现,i代表着从第i个位置出发,而若a[i][n]=p,则从i出发,有到p的直接路径。
for(int i = 1; i <= m; i++){
cin >> u >> v;
a[u].push_back(v);
4、链式前向星
本质上用链表实现的邻接表。
时间复杂度分析
直接存边 | 邻接矩阵 | 邻接表 |
---|---|---|
O(m) | O(1) | O(d+(u)) |
O(m) | O(m) | O(d+(u)) |
O(nm) | O(n*n) | O(n+m) |
O(m) | O(n*n) | O(m) |
三、图的遍历
DFS
深度优先
从一个点开始,找到它的所有相邻点,在一次遍历相邻点,一个点遍历完后在遍历另一个相邻点。
//直接存边
void dfs(int u){
vis[i] = 1;
for(int i - 1; i <= m; i++){
if(adj[i][1] == u && vis[adj[i][2]] == 0){
dfs(adj[i][2]);
}
}
}
//邻接矩阵
void dfs(int u){
vis[u] = 1;
for(int i = 1; i <= n; i++){
if(adj[u][i] == 1 && vis[i] == 0){
dfs(i);
}
}
}
//邻接表
void dfs(int u){
vis[u] = 1;
for(int i = 1; i <= adj[u].size(); i++){
if(vis[adj[u][i]] == 0){
dfs(adj[u][i]);
}
}
}
//链式前向星
void dfs(int u) {
vis[u] = 1;
for (int i = head[u]; i; i = e[i].x) {
if (!vis[e[i].t]) {
dfs(v);
}
}
}
BFS
广度优先
与深搜不同的是,广搜是把一个点的相邻点遍历了再遍历这些点的相邻点。也就是一层一层的,深搜则可以看做一列一列的。
//直接存边
void bfs(int u){
while(!q.empty()) q.pop();
q.push(u), vis[u] = 1;
while(!q.empty(){
u = q.front();
q.pop();
for(int i = 1; i <= m; i++){
if(adj[i][1] == u && vis[adj[i][2]] == 0){
q.push(adj[i][2]);
vis[adj[1][2]] = 1;
}
}
}
}
//邻接矩阵
for(int i = 1; i <= m; i++){
if(adj[i][1] == u && vis[i] == 0){
q.push(i);
vis[i] = 1;
}
}
//邻接表
for(int i = 1; i <= m; i++){
if(vis[adj[u][i] == 0){
q.push(vis[adj[u][i]);
vis[adj[u][i]] = 1;
}
}
//链式前向星
void bfs(s) {
q = new queue()
q.push(s), visited[s] = true
while (!q.empty()) {
u = q.pop()
for each edge(u, v) {
if (!visited[v]) {
q.push(v)
visited[v] = true
}
}
}
}