图的遍历:深度优先、广度优先
图的遍历是指从图中的某一顶点出发,按照一定的策略访问图中的每一个顶点。当然,每个顶点有且只能被访问一次。
在图的遍历中,深度优先和广度优先是最常使用的两种遍历方式。这两种遍历方式对无向图和有向图都是适用的,并且都是从指定的顶点开始遍历的。先看下两种遍历方式的遍历规则:
深度优先遍历也叫深度优先搜索(Depth First Search)。它的遍历规则:不断地沿着顶点的深度方向遍历。顶点的深度方向是指它的邻接点方向。
具体点,给定一图G=<V,E>,用visited[i]表示顶点i的访问情况,则初始情况下所有的visited[i]都为false。假设从顶点V0开始遍历,则下一个遍历的顶点是V0的第一个邻接点Vi,接着遍历Vi的第一个邻接点Vj,……直到所有的顶点都被访问过。
所谓的第一个是指在某种存储结构中(邻接矩阵、邻接表),所有邻接点中存储位置最近的,通常指的是下标最小的。在遍历的过程中有两种情况经常出现
/* 深度优先搜索 从vertex开始遍历,visit是遍历顶点的函数指针 */ void Graph::dfs(int vertex, void (*visit)(int)) { stack<int> s; //visited[i]用于标记顶点i是否被访问过 bool *visited = new bool[numV]; //count用于统计已遍历过的顶点数 int i, count; for (i = 0; i < numV; i++) visited[i] = false; count = 0; while (count < numV) { visit(vertex); visited[vertex] = true; s.push(vertex); count++; if (count == numV) break; while (visited[vertex]) { for (i = 0; i < numV && (visited[i] || matrix[vertex][i] == 0 || matrix[vertex][i] == MAXWEIGHT); i++); if (i == numV) //当前顶点vertex的所有邻接点都已访问完了 { if (!s.empty()) { s.pop(); //此时vertex正是栈顶,应先出栈 if (!s.empty()) { vertex = s.top(); s.pop(); } else //若栈已空,则需从头开始寻找新的、未访问过的顶点 { for (vertex = 0; vertex < numV && visited[vertex]; vertex++); } } else //若栈已空,则需从头开始寻找新的、未访问过的顶点 { for (vertex = 0; vertex < numV && visited[vertex]; vertex++); } } else //找到新的顶点应更新当前访问的顶点vertex vertex = i; } } delete[]visited; }其它代码前面已经见过,就不给出了,下面看下图的广度遍历。深度遍历和广度遍历的测试,稍后一并给出。
/* 广度优先搜索 从vertex开始遍历,visit是遍历顶点的函数指针 */ void Graph::bfs(int vertex, void(*visit)(int)) { //使用队列 queue<int> q; //visited[i]用于标记顶点i是否被访问过 bool *visited = new bool[numV]; //count用于统计已遍历过的顶点数 int i, count; for (i = 0; i < numV; i++) visited[i] = false; q.push(vertex); visit(vertex); visited[vertex] = true; count = 1; while (count < numV) { if (!q.empty()) { vertex = q.front(); q.pop(); } else { for (vertex = 0; vertex < numV && visited[vertex]; vertex++); visit(vertex); visited[vertex] = true; count++; if (count == numV) return; q.push(vertex); } //代码走到这里,vertex是已经访问过的顶点 for (int i = 0; i < numV; i++) { if (!visited[i] && matrix[vertex][i] > 0 && matrix[vertex][i] < MAXWEIGHT) { visit(i); visited[i] = true; count ++; if (count == numV) return; q.push(i); } } } delete[]visited; }
void visit(int vertex) { cout << setw(4) << vertex; } int main() { cout << "******图的遍历:深度优先、广度优先***by David***" << endl; bool isDirected, isWeighted; int numV; cout << "建图" << endl; cout << "输入顶点数 "; cin >> numV; cout << "边是否带权值,0(不带) or 1(带) "; cin >> isWeighted; cout << "是否是有向图,0(无向) or 1(有向) "; cin >> isDirected; Graph graph(numV, isWeighted, isDirected); cout << "这是一个"; isDirected ? cout << "有向、" : cout << "无向、"; isWeighted ? cout << "有权图" << endl : cout << "无权图" << endl; graph.createGraph(); cout << "打印邻接矩阵" << endl; graph.printAdjacentMatrix(); cout << endl; cout << "深度遍历" << endl; for (int i = 0; i < numV; i++) { graph.dfs(i, visit); cout << endl; } cout << endl; cout << "广度遍历" << endl; for (int i = 0; i < numV; i++) { graph.bfs(i, visit); cout << endl; } system("pause"); return 0; }
数据结构:图的遍历--深度优先、广度优先,布布扣,bubuko.com
原文地址:http://blog.csdn.net/zhangxiangdavaid/article/details/38323633