深度优先搜索:在一个图中,从某一个节点开始访问该图(作为顶点),然后标记该节点为已访问。接着去访问它的邻接未访问的节点,这个过程一直持续,直到遇到一个终点——该节点的所有邻接节点都是已访问。此时,回退到上一个节点,并尝试从这里访问未访问的节点。直到回退到起始点,并且起始点邻接的节点都是已访问。这个时候该算法结束,这个时候该节点所在的连通子图所有的节点都被访问过了。如果还有其他未访问的节点存在,那么该算法必须从其中某一个节点开始,重复上面的过程。直到该图中所有的节点都被访问过了,此时,搜索结束。
深度优先搜索(DFS)的重要应用通常在于检查图的连通性和无环性,当然也能求出一个非连通图的连通分量。
DFS这种策略是能往前多走几步是几步,总是试图走的更远更深。
标记这项工作需要额外的空间来做,否则原来的图就会被破坏。一般是用一个数组来做的。下面给出深度优先搜索的C++实现代码。(深度优先搜索邻接矩阵)
// 深度优先搜索(DFS).cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include <iostream>
#include <vector>
using namespace std;
class MyGraph
{
public:
MyGraph();
~MyGraph();
void DFS(int start);
int print(int i, int j);
private:
int v, e; //图的顶点数和边数
vector<vector<int>> matrix; //邻接矩阵
vector<int> flag; //标记数组
};
MyGraph::MyGraph()
{
cout << "请输入图的顶点数目:
";
cin >> this->v;
cout << "请输入图的边数目:
";
cin >> this->e;
vector<int> temp(this->v); //用来构造matrix用的
for (int i = 0; i < this->v; i++)
{
this->matrix.push_back(temp);
}
for (int i = 0; i < this->v; i++)
{
this->flag.push_back(0); //初始标记数组的内容为0
}
int m, n;
for (int i = 0; i < this->e; i++)
{
cout << "请输入第" << i << "条边的起始点和终点:
";
cin >> m >> n;
this->matrix[m][n] = 1; //有边用1记录
this->matrix[n][m] = 1;
}
}
MyGraph::~MyGraph()
{
}
void MyGraph::DFS(int start)
{
this->flag[start] = 1; //用1表示访问过了
cout << start << ' '; //此处深度优先搜索只是做了个输出
for (int i = 0; i < this->v; i++)
{
//未标记并且到i这个顶点有边
if (!flag[i] && this->matrix[start][i] == 1)
{
this->DFS(i); //从i这个顶点做深度优先搜索
}
}
}
int MyGraph::print(int i, int j) //这个接口函数和深度优先搜索无关
{
return this->matrix[i][j];
}
int main()
{
MyGraph graph;
cout << "深度优先搜索结果:
";
graph.DFS(0);
cout << endl;
system("pause");
}
对于深度优先搜索的分析依赖于具体的实现,如果图是邻接矩阵存储的,那么时间复杂度是O(v²);如果图是邻接表存储的,那么时间复杂度是O(v+e)。