第十章 数据结构专题 —— 图(上)
10.1 图的存储
10.1.1 邻接矩阵
设图G(V,E)的顶点标号为0,1,……,N-1,那么可以令二维数组G[N][N]的二维分别表示图的顶点标号,即如果G[i][j] = 1,则说明顶点i和顶尖j之间不存在边,而这个二维数组G[][]则被称为邻接矩阵,如果存在边权,令G[i][j]存放边权,对不存在的边可以设边权为0、-1、INF
10.1.2 邻接表
设图G(V,E)的顶点标号为0,1,……,N-1,每个顶点都有可能有若干条出边,如果把同一个顶点的所有出边放在一个列表,那么N个顶点就会有N个列表(没有出边,对应空表)。这N个列表被称为图G的邻接表,记为Adj[N]
由于vector有变长数组之称,因此可以开一个vector数组Adj[N],其中N为顶点个数。这样每个Adj[i]就是一个变长数组vector,使得存储空间与图的边数有关。
如果邻接表只存放每条边的终点编号,而不存放边权,则vector中的元素类型可以直接定义为int型
vector<int> Adj[N];
如果想添加一条从1号顶点到3号顶点的有向边
Adj[1].push_back(3);
如果要同时存放边的终点和边号,可以建立结构体Node
struct Node{
int v; //边的终点编号
int w; //边权
};
vector<Node> Adj[N];
如果想要添加从1号到3号顶点的有向边,边权为4
Node temp;
temp.v=3;
temp.w=4;
Adj[1].push_back(temp);
更快的做法是定义结构体Node函数
struct Node{
int v; //边的终点编号
int w; //边权
Node(int _v,int _w):v(_v),w(_w){}
};
// 如果想要添加从1号到3号顶点的有向边,边权为4
Adj[1].push_back(Node(3,4));
10.2 深度优先搜索遍历(DFS)
//DFS 邻接矩阵
int n,G[MAXV][MAXV]; //n为顶点数,MAXV为最大顶点数
bool vis[MAXV]={false}; //如果顶点i已经被访问,则vis[i]==false。初值为false
void DFS(int u,int depth){ //u为当前访问的顶点标号,depth为深度
vis[u]=true;
//如果需要对u进行一些操作,可以在这里进行
//下面对所有从u出发能达到的分支顶点进行枚举
for(int v=0;v<n;v++){ //对每个顶点v
if(vis[v]==false && G[u][v]!=INF){ //如果v未被访问,且u可到达v
DFS(v,depth+1);//访问v,深度加1
}
}
}
void DFSTrave(){ //遍历图G
for(int u=0;u<n;u++){ //对每个顶点u
if(vis[u] == false){ //如果u未被访问
DFS(u,1);
}
}
}
//DFS 邻接表
vector<int> Adj[MAXV];
int n; //n为顶点数
bool vis[MAXV] = {false};//如果顶点i已经被访问,则vis[i]==false。初值为false
void DFS(int u,int depth){ //u为当前访问的顶点标号,depth为深度
vis[u] = true; //设置u已被访问
//如果需要对u进行一些操作,可以在此处进行
for(int i=0;i<Adj[u].size();i++){ //对从u出发可以到达
int v = Adj[u][i];
if(vis[v] == false){ //如果v未被访问
DFS(v,depth+1); //访问v,深度加1
}
}
}
void DFSTrave(){
for(int u=0;u<n;u++){ //对每个顶点u
if(vis[u] == false){ //如果u未被访问
DFS(u,1);
}
}
}
10.3 广度优先搜索(BFS)
//邻接矩阵
int n,G[MAXV][MAXV]; //n为顶点数,MAXV为最大顶点数
bool inq[MAXV] = {false}; //若顶点i曾入过队列,则inq[i]==true,初值为false
void BFS(int u){ //遍历u所在的联通块
queue<int> q;
q.push(u);
inq[u] = true; //设置u已被加入队列
while(!q.empty()){
int u = q.front(); //取出队首元素
q.pop();
for(int v=0;v<n;v++){
//如果u的邻接点v未曾加入过队列
if(inq[v]==false && G[u][v]!=INF){
q.push(v); //将v入队
inq[v] = true;
}
}
}
}
void BFSTrave(){
for(int u=0;u<n;u++){
if(inq[u]==false){
BFS(u);
}
}
}
//邻接表版
vector<int> Adj[MAXV];
int n;
bool inq[MAXV] = {false};
void BFS(int u){
queue<int> q;
q.push(u);
inq[u]=true;
while(!q.empty()){
int u = q.front();
q.pop();
for(int i=0;i<Adj[u].size();i++){
int v = Adj[u][i];
if(inq[v]==false){
q.push(v);
inq[v]=true;
}
}
}
}
void BFSTrave(){
for(int u=0;u<n;u++){
if(inq[u]==false){
BFS(u);
}
}
}