图的深度优先遍历(DFS)
1、深度优先搜索遍历过程
图的深度优先搜索(Depth First Search),和树的先序遍历比较类似。
它的思想:假设初始状态是图中所有顶点均未被访问,则从某个顶点v出发,首先访问该顶点,然后依次从它的各个未被访问的邻接点出发深度优先搜索遍历图,直至图中所有和v有路径相通的顶点都被访问到。 若此时尚有其他顶点未被访问到,则另选一个未被访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。
显然,深度优先搜索是一个递归的过程
深度优先遍历特点是,选定一个出发点后进行遍历,能前进则前进,若不能前进,回退一步再前进,或再回退一步后继续前进。依此重复,直到所有与选定点相通的所有顶点都被遍历。
2、示例
下图的深度优先遍历结果:A B F H C D G I E
下图的广度优先遍历结果:A B C D E F G H I
创建图(C++)
//图结构体
struct Graph
{
//顶点的名称
string vertex[MaxVertex];
//边的数组
int edge[MaxVertex][MaxVertex];
//顶点的数量
int vertexNum;
//边的数量
int edgeNum;
};
int LocalVertex(Graph g, string name)
{
for (int i = 0; i < g.vertexNum; ++i)
{
if (g.vertex[i] == name)
{
return i;
}
}
return -1;
}
//创建图
void CreateGraph(Graph &g)
{
cout << "请输入顶点和边的数量:" << endl;
cin >> g.vertexNum >> g.edgeNum;
cout << "请输入" << g.vertexNum << "个顶点的名称:" << endl;
for (int i = 0; i < g.vertexNum; ++i)
{
cin >> g.vertex[i];
}
//初始化
for (int i = 0; i < g.vertexNum; ++i)
{
for (int j = 0; j < g.vertexNum; ++j)
{
g.edge[i][j] = 0;
}
}
cout << "请输入" << g.edgeNum << "条边,顶点1 顶点2" << endl;
string v1, v2;
for (int i = 0; i < g.edgeNum; ++i)
{
cin >> v1 >> v2;
int m = LocalVertex(g, v1);
int n = LocalVertex(g, v2);
g.edge[m][n] = 1;
g.edge[n][m] = 1;
}
}
DFS代码(C++)
非递归遍历(有向图和无向图的DFS代码都一样)
需要用到栈
//深度优先遍历
void DFS(Graph g)
{
bool* visit = new bool[g.vertexNum];//标记顶点是否被访问过
for (int i = 0; i < g.vertexNum; ++i)
{
visit[i] = false;
}
//从顶点的第一个开始访问
stack<int> st;
visit[0] = true;
cout << g.vertex[0] << " ";
st.push(0);
while (!st.empty())
{
for (int i = 0; i < g.vertexNum; ++i)
{
int top = st.top();
if (!visit[i] && g.edge[top][i] > 0)
{
visit[i] = true;
cout << g.vertex[i] << " ";
st.push(i);
}
}
st.pop();
}
delete[]visit;
cout << endl;
}
递归遍历
v 是顶点所在所在数组中的位置
void DFS(int v)
{
int n=vertexNum;//顶点数目
if(v<0||v>=n) throw "位置出错";
cout<<vertex[v]<<" ";//输出顶点v
visited[v]=1;//被访问过
for(int j=0;j<n;j++)
if(visited[j]==0&&adj[v][j]==1)//没被访问过且存在边(v,j)
DFS(j);
}
BFS代码(C++)
需要用到队列
//广度优先遍历
void BFS(Graph g)
{
bool* visit = new bool[g.vertexNum];
queue<int> queue;
//初始化所有顶点的状态
for (int i = 0; i < g.vertexNum; ++i)
{
visit[i] = false;
}
visit[0] = true;
cout << g.vertex[0] << " ";
queue.push(0);
while (!queue.empty())
{
int top = queue.front();
queue.pop();
for (int i = 0; i < g.vertexNum; ++i)
{
if (!visit[i] && g.edge[top][i] > 0)
{
visit[i] = true;
cout << g.vertex[i] << " ";
queue.push(i);
}
}
}
delete[] visit;
}