图——基本的图算法(二)图的遍历
1. 基本概念
图的遍历指的是从图中的某个顶点出发访问图中其余的顶点,且每个顶点只被访问一次的这个过程。通常来说,图的遍历次序有两种:深度优先遍历(Depth first Search, DFS)和广度优先遍历(Breadth First Search, BFS)。下面就分别来进行介绍。
2. 深度优先遍历
2.1 总体思想
深度优先遍历,也叫深度优先搜索,其基本思想是从图中的某个顶点V出发,访问这个顶点,然后从V的未被访问的邻接点出发继续对图进行深度优先遍历,直至图中所有和V有路径相通的顶点都被访问。需要注意的是,对于非连通图,需要对它的分联通分量分别进行深度优先搜索,也就是说在从某个顶点出发进行了深度优先搜索后,如果图中还存在尚未被访问的顶点,就要选取其中一个还没被访问的顶点作为起点来进行深度优先搜索遍历。
2.2 具体实现
(1)图采用邻接链表来表示
#define Maximum 1000
map<int, int>visited;
typedef struct EdgeListNode{
int adjId;
int weight;
EdgeListNode* next;
};
typedef struct VertexListNode{
int data;
EdgeListNode* firstadj;
};
typedef struct GraphAdjList{
int vertexnumber;
int edgenumber;
VertexListNode vertextlist[Maximum];
};
void DFS(GraphAdjList g, int node) {
cout<<node<<" "<<g.vertextlist[node].data<<endl;
int i;
EdgeListNode* j = g.vertextlist[node].firstadj;
while(j!=NULL) {
if(visited.count(j->adjId) == 0) {
visited[j->adjId] = 1;
DFS(g, j->adjId);
}
j = j->next;
}
}
void DFS_VISIT(GraphAdjList g) {
visited.clear();
int i;
//对每个连通分量分别进行DFS
for(i=0; i<g.vertexnumber; i++) {
if(visited.count(i) == 0) {
visited[i] = 1;
DFS(g, i);
}
}
}
(2)图采用矩阵来表示
#define Maximum 1000
typedef int VexType;
typedef int MatrixType;
map<int, int>visited;
typedef struct GraphAdjMatrix {
VexType vertexlist[Maximum];
MatrixType matrix[Maximum][Maximum];
int vertexnumber;
int edgenumber;
};
void DFS(GraphAdjMatrix g, int node) {
cout<<node<<" "<<g.vertexlist[node];
int i;
for(i=1; i<=g.vertexnumber; i++) {
if(g.matrix[node][i] && visited.count(i)==0) {
visited[i] = 1;
DFS(g, i);
}
}
}
void DFS_VISIT(GraphAdjMatrix g) {
int i;
visited.clear();
for(i=1; i<=g.vertexnumber; i++) {
if(visited.count(i) == 0) {
visited[i] = 1;
DFS(g, i);
}
}
}
(3)综合分析
一个有v个顶点和e条边的图,如果用邻接链表表示,那么查找每个顶点的邻接点所需的时间取决于顶点数和边数,因此时间复杂度为O(v+e);如果用邻接矩阵来表示,那么查找每个顶点的邻接点需要访问据正在的所有元素,因此时间复杂度为O(n^2)。
3. 广度优先搜索
3.1 总体思想
广度优先搜索的基本思想是,给定图中的一个顶点V,访问它,并把它丢进一个队列里,然后依此访问与它相邻且还未被访问过的顶点,并扔入队列里,当所有相邻的点都访问完了,就将顶点V出列;然后取出队列最前边的顶点,重复上述操作,直至所有顶点被访问完。
3.2 具体实现
(1)图采用邻接链表来表示
#define Maximum 1000
typedef struct EdgeListNode{
int adjId;
int weight;
EdgeListNode* next;
};
typedef struct VertexListNode{
int data;
EdgeListNode* firstadj;
};
typedef struct GraphAdjList{
int vertexnumber;
int edgenumber;
VertexListNode vertextlist[Maximum];
};
void BFS(GraphAdjList g) {
queue<int>q;
map<int, int>visited;
visited.clear();
while(!q.empty()) {
q.pop();
}
int temp, i;
EdgeListNode *j;
for(i=1; i<=g.vertexnumber; i++) {
if(visited.count(i) == 0) {
q.push(i);
visited[i] = 1;
while(q.empty()==0) {
temp = q.front();
q.pop();
cout<<temp<<" "<<g.vertextlist[temp].data<<endl;
j = g.vertextlist[temp].firstadj;
while(j != NULL) {
if(visited.count(j->adjId) == 0) {
visited[j->adjId] = 1;
q.push(j->adjId);
}
j = j->next;
}
}
}
}
}
(2)图采用邻接矩阵来表示
#define Maximum 1000
typedef int VexType;
typedef int MatrixType;
typedef struct GraphAdjMatrix {
VexType vertexlist[Maximum];
MatrixType matrix[Maximum][Maximum];
int vertexnumber;
int edgenumber;
};
void BFS(GraphAdjMatrix g) {
map<int, int>visited;
queue<int>q;
visited.clear();
while(!q.empty()) {
q.pop();
}
int i, j, temp;
for(i=1; i<=g.vertexnumber; i++) {
if(visited.count(i) == 0) {
visited[i] = 1;
q.push(i);
while(q.empty() == 0) {
temp = q.front();
q.pop();
cout<<temp<<" "<<g.vertexlist[temp]<<endl;
for(j=1; j<=g.vertexnumber; j++) {
if(g.matrix[i][j] && visited.count(j)==0) {
visited[j] = 1;
q.push(j);
}
}
}
}
}
}