深度优先搜索:假设初始状态是图中的所有顶点未曾被访问,则深度优先搜索可从图中某个顶点v出发,访问此顶点,然后依次从v的未被访问的邻接点出发深度优先遍历图,直至图中的所有和v有路径相通的顶点都被访问到;若此时图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作起始点,重复上述过程,直至图中的所有顶点都被访问到为止。
邻接表存储结构分为两部份:一是顺序表,二是链表。图中的顶点按顺序存储在顺序表中,顺序表结点分为两个域:数据域(data)和链域(firstarc),数据域存储的是图中顶点的信息,链域存储的是指针,指向该点的其中一个邻接点;在链表中存储的是顶点vi的邻接点,链表中分为邻接点域(adjvex)、链域(nextarc)和数据域(info),邻接点域(adjvex)存储的是顶点vi的邻接点在顺序表中的位置,链域(firstarc)指向顶点vi下一个邻接点,数据域存储的是网的权值。
如果图是用邻接表存储结构存储,那么在进行深度优先搜索遍历时,先从顺序表中的第一个顶点vi出发,访问该顶点(记得别忘了将已访问过的顶点做标记),然后访问vi在存储结构中的第一个邻接点vj,接着再访问vj的邻接点,不断的进行“访问邻接点的邻接点”这样一个循环,直到遇到一个顶点它的邻接点已经被访问过,循环结束,接着访问vi的下一个邻接点,直至vi的邻接点都被访问完。访问完vi的邻接点后,接着访问顺序表中的第二个顶点,直至顺序表中的所有顶点都已经被访问到。
顺序表中的结点:
链表中的结点:
图:
邻接表:
#include<iostream> ///深度优先搜索,通过有向图的邻接表存储
#include<malloc.h> ///有向图的邻接表中,第i个链表的的结点数只是顶点vi的出度,为求入度,必须遍历整个邻接表或是建立有向图的逆邻接表
#define MAX_VERTEX_NUM 20
#define MAX_NAME 5
#define OK 1
#define TRUE 1
#define FALSE -1
typedef char VertexType[MAX_NAME];
typedef int InfoType;
using std::cin;
using std::cout;
using std::endl;
typedef struct ArcNode //单链表中结点的类型
{
int adjvex; //该边指向的顶点在顺序表中的位置
struct ArcNode *nextarc;
InfoType *info; //网的权值指针
}ArcNode;
typedef struct VNode //定义顶点类型
{
VertexType data;
ArcNode *firstarc;
}VNode, AdjList[MAX_VERTEX_NUM];
typedef struct
{ AdjList vertices; //顺序表
int vexnum, arcnum;
int kind;
}ALGraph;
int LocateVex(ALGraph &G, VertexType &u) //返回顶点u在vertices中的位置
{
for(int i = 0;i < G.vexnum; ++i)
{
if(strcmp(G.vertices[i].data,u) == 0)
return i;
}
return FALSE ;
}
int CreateDG( ALGraph &G ) //有向图的邻接表
{
int i,j,k,w;
VertexType v1,v2;
cout <<"开始构造有向图:\n请输入图的顶点的个数:";
cin >> G.vexnum;
cout << "请输入图的边的数目:";
cin >> G.arcnum;
cout <<"请输入所有的顶点:\n";
for(i = 0; i < G.vexnum; ++i)
{
cout << "请输入第"<< i+1 << "个顶点:";
scanf("%s",G.vertices[i].data);
G.vertices[i].firstarc = NULL;
}
cout <<"请输入弧,例如 v1-->v2\n";
for(k = 0; k < G.arcnum; ++k)
{
cout << "请输入第" << k+1 << "条弧的弧尾";
cin >> v1;
cout << "请输入第" << k+1 << "条弧的弧头";
cin >> v2;
i = LocateVex(G,v1);
j = LocateVex(G,v2);
ArcNode *p;
p = (ArcNode *)malloc(sizeof(ArcNode));
if(!p)
{
cout << "Overflow";
return 0;
}
p->adjvex = j;
p->nextarc = G.vertices[i].firstarc; //单链表的逆序构造,即输入的第一个结点会成为最后一个结点
G.vertices[i].firstarc = p;
p->info = NULL;
} // for end
return OK;
} // CreateDG() end
void DFS(ALGraph G, int v, int *visited) //如果该图是连通图,只需从G.vertices[0]出发便可以遍历图中的所有节点
{
ArcNode *p;
int w;
visited[v] = TRUE;
cout << v + 1 << "->";
for(p = G.vertices[v].firstarc; p != NULL; p = p->nextarc)
{
if(visited[p->adjvex] == 0)
{
visited[p->adjvex] = 0;
DFS(G, p->adjvex,visited); //不断的访问节点的邻接点
}
}
} // DFS() end
void DFSTraverse( ALGraph &G )
{
int v;
int visited[MAX_VERTEX_NUM];
for( v = 0; v < G.vexnum; ++v )
visited[v] = 0; //visited 为辅助数组用于标记顶点是否被访问
for( v = 0; v < G.vexnum; ++v )
if(visited[v] == 0 )
DFS(G,v,visited);
}//DFSTraverse() end
void DestroyALGraph(ALGraph &G) //销毁分配的空间
{
ArcNode *q;
for(int i = 0; i < G.vexnum; ++i)
for(ArcNode *p = G.vertices[i].firstarc; p != NULL;)
{
G.vertices[i].firstarc = NULL;
q = p;
p = p->nextarc;
free(q);
}
}
void main()
{
ALGraph G;
cout << endl << "DFSTraverse.cpp";
cout << endl << "===================" << endl;
CreateDG(G);
cout <<"深度优先搜索:\n";
DFSTraverse(G);
DestroyALGraph(G);
}// main end
运行结果: