一. 遍历思想
- 给定一个图G=(V,E)和其中任意一个顶点v,从顶点v出发,访问图G中的所有顶点而且每个顶点仅被访问一次,这一过程称为图的遍历。
- 为了避免同一顶点被访问多次,在遍历图的过程中,必须记下每个已被访问过的顶点。
- 为此设一个辅助数组visited[],用以标记顶点是否被访问过,其初态应为0(false)。一旦一个顶点i被访问,则visited[ i ]=1(true)。
二. DFS(深度优先遍历)设计思想
- 访问顶点v。
- 选择一个与顶点v相邻且没被访问过的顶点w,从w出发深度优先遍历。
- 直到图中与v相邻的所有顶点都被访问过为止。
三. 具体分析
- 假设从顶点2出发进行遍历,输出顶点2的值,同时将visited 2置为1,表示顶点2已被访问过。在访问了顶点2之后,找到它的第一个邻接点1。因为1未曾访问,那么接着下一个被访问的就是顶点1。
- 而v1的第一个邻接点是v0,检查v0的标志为visited 0,此时继续访问v0顶点。
- v0顶点被访问后,找到v0的第一个邻接点v1。因为v1已被访问过,所以找到它的下一个邻接点v3并访问。
- 依次类推,v3被访问完毕以后,找到v3的第一个连接点v0,v0被访问过。v1,v2也被访问过,v4未被访问。那么访问v4。
- v4一旦被访问完毕以后,找到它的邻接点,发现它的邻接点v0,v2,v3都被访问过。
- 那么倒着回去,再看一下v4已经是v3的最后一个邻接点,接着继续回退,回退到v3,v3又继续退到v1,v1继续回退到v2。
- 此时再来检测v2的下一个邻接点v3,v3已被访问过。
- 接着访问v2的第三个邻接点v4,v4也已被访问过。
- 至此,整个遍历结束。
- v2的DFS序列:
2 1 0 3 4
四. 实现深度优先遍历的递归算法
#include<iostream>
using namespace std;
#define MAXVEX 100
typedef char VType;
typedef int EType;
typedef struct ENode
{
int Avex;
EType Weigh;
struct ENode *pNext;
}ENode;
typedef struct VNode
{
VType data;
ENode *pFirst;
}VNode,VNodeL[MAXVEX];
typedef struct
{
VNodeL VLnode;
int Vnums;
int Enums;
}ALGraph;
void CreateALGraph(ALGraph &G)
{
int i, j, k;
ENode *pE;
cin >> G.Vnums >> G.Enums;
for (i = 0; i < G.Vnums; ++i)
{
cin >> G.VLnode[i].data;
G.VLnode[i].pFirst = NULL;
}
for (k = 0; k < G.Enums; ++k)
{
cin >> i >> j;
pE = new ENode;
pE->Avex = i;
pE->pNext = G.VLnode[j].pFirst;
G.VLnode[j].pFirst = pE;
pE = new ENode;
pE->Avex = j;
pE->pNext = G.VLnode[i].pFirst;
G.VLnode[j].pFirst = pE;
}
}
bool VTag[MAXVEX];
void Visit(VType e)
{
cout << e << " ";
}
void DFS(ALGraph G,int i)
{
ENode *pE;
VTag[i] = true;
Visit(G.VLnode[i].data);
pE = G.VLnode[i].pFirst;
while (pE)
{
if (!VTag[pE->Avex])
DFS(G, pE->Avex);
pE = pE->pNext;
}
}
void DFSPrint(ALGraph G)
{
int i;
for (i = 0; i < G.Vnums; ++i)
VTag[i] = false;
for (i = 0; i < G.Vnums; ++i)
if (!VTag[i])
DFS(G, i);
}
int main(void)
{
ALGraph G;
CreateALGraph(G);
DFSPrint(G);
return 0;
}