Graph Theory-图的存储与遍历
Graph Theory
Intro
图是计算机科学中一种常用的数据结构,用来表示对象和对象之间的关系,直观上我们用圆点来表示对象,点之间的边表示对象之间的关系。我们将一张图 G 记作\(G = (V,E)\),其中 \(V\) 是点集(Vertex),\(E\) 是边集(Edge),一条从点 u 指向点 v的边表示为 \(e(u,v)\).
根据边是否有向,图可以分为有向图和无向图,比如,在一群人之间的互为朋友关系,就可以抽象成一张无向图,其中人是顶点,互为朋友的两个人之间存在一条无向边,而例如高速公路上的几个服务站,抽象成一张图就是有向图(这里只考虑了一个边的路),服务站就是顶点,连接它们的路是有向边。
同时,边还可以带有权重,来反映某种代价,例如,在几个城市之间要修建公路,问怎样修使得总长最短,这时距离,或者花费,就可以作为权重考虑进来。
图的存储
树是无环连通图,因此是一种特殊的图,图分为有向图和无向图,无向图是一种特殊的有向图(连两条有向边),因此我们下面只讨论有向图,其他可以推而广之。
有向图的存储有两种方式:邻接表和邻接矩阵。
其中,稠密图(\(m\) ~ \(n^2\))一般用邻接矩阵,稀疏图(\(m\) ~ \(n\))一般用邻接表。
- 邻接矩阵
开一个二维矩阵v[][]来存边,\(v[a][b] = c\) 表示有一条a到b的有向边,边权为c,若 \(v[a][b] = 0\) 说明a与b不连通。
- 邻接表
开一个头节点数组h[],存储每个h[i]是一个单链表的头节点,h[i]为头指针的链表中存了节点i能到达的所有点的idx,e[]是他们的值(编号)。空节点是-1.
//用邻接表来存储图
int e[M],ne[M],idx,h[N];//由于是无向图,是双向连接,所以e[],ne[]要开成两倍大
//以a为根,将b连到a上
void add(int a,int b){
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
图的遍历
图的深度优先遍历
跟普通的深度优先搜索差不多,只是不用恢复现场,因为每个点只遍历一次。
void dfs(int u){
st[u] = true;//标记已遍历
for(int v = h[u]; v != -1 ; v = ne[v]){//遍历所有可达点
int j = e[v];//获取可达点编号
if(st[j])continue;
dfs(j);
}
}
图的广度优先遍历
也与普通的深度优先搜索差不多。
q.push(start);//推入初始状态
st[start] = true;//标记已遍历
while(q.size()){
Vertex v = q.front();
q.pop();
for(int i = h[v]; i != -1 ; i = ne[i]){
if(满足某些条件,如未遍历){
st[j] = true;
int j = e[i];
q.push(j);
//同时维护某些东西,进行某些操作等
}
}
}

浙公网安备 33010602011771号