这篇专栏记录的是图的深度优先搜索算法(DFS)。(完整代码在最下面)
存储图,首先要定义边、顶点、图的结构体。
//边
typedef struct Edge{
int adj; //邻接点对应的的下标
Edge *next; //指向下一个结点
}Edge;
//顶点
typedef struct{
int data; //顶点信息
Edge *first; //指向第一个邻接点
}Node;
//图
typedef struct{
Node Node[15]; //顶点
int numVertex, numEdge; //顶点数,边数
}Graph;
由于访问节点不能重复,因此要定义一个数组来标记该顶点是否已经访问。
bool DFSvisited[50]; //标记结点是否被访问过
创建的图和存储图对应的邻接表如图所示。
执行顺序:
1、先访问Node[0].data(即1)。
2、由于Node[0].first.adj为1,所以访问Node[1].data(即2)。
3、由于Node[1].first.adj为4,所以访问Node[4].data(即5)。
4、由于Node[4].first为NULL,回退到Node[1].first。
5、由于Node[1].first.next为NULL,回退到Node[0].first。
6、由于Node[0].first.next.adj为2,所以访问Node[2].data(即3)。
7、由于Node[2].first为NULL,回退到Node[1].first.next。
8、由于Node[1].first.next.next.adj为3,所以访问Node[3].data(即4)。
9、由于Node[3].first已经访问过,回退,发现每一个顶点都访问过了。
完整代码:
#include <iostream>
using namespace std;
bool DFSvisited[50]; //标记结点是否被访问过
//边
typedef struct Edge{
int adj; //邻接点对应的的下标
Edge *next; //指向下一个结点
}Edge;
//顶点
typedef struct{
int data; //顶点信息
Edge *first; //指向第一个邻接点
}Node;
//图
typedef struct{
Node Node[15]; //顶点
int numVertex, numEdge; //顶点数,边数
}Graph;
//遍历,直到找到该顶点在图中的存储位置(即下标)
int local(Graph G, int val){
for(int i=0; i<G.numVertex; i++){
if(G.Node[i].data == val)
return i; //返回该顶点在图中的存储位置
}
return -1;
}
void CreateGraph(Graph &G){ //创建图,用邻接表存储
cout << "请输入顶点数和边数:";
cin >> G.numVertex >> G.numEdge;
for(int i=0; i<G.numVertex; i++){
G.Node[i].data = i+1; //结点信息初始化,也可以自己输入
G.Node[i].first = NULL;
}
int v1, v2;
cout << "请输入每条边的起点和终点:" << endl;
for(int k=0; k<G.numEdge; k++){
cin >> v1 >> v2; //输入起点和终点的顶点信息
int src = local(G, v1);
int des = local(G, v2);
if(G.Node[src].first == NULL){ //该结点的第一个邻接结点为空时
Edge *e = new Edge;
e->adj = des;
e->next = NULL;
G.Node[src].first = e; //给第一个邻接结点赋值
}
else{ //该结点的第一个邻接结点不为空时
Edge *p = G.Node[src].first;
while(p->next != NULL){
p = p->next; //先循环到最后一个邻接节点处
}
Edge *e = new Edge;
e->adj = des;
e->next = NULL;
p->next = e; //再在最后添加一个新的邻接节点
}
}
}
void Print(Graph G){ //按下标输出各个顶点信息
cout<<"所建立的邻接表如以下所示:"<<endl;
for(int i=0; i<G.numVertex; i++){
cout << "[" << i << "]" << ")"; //先输出顶点信息
Edge *e = G.Node[i].first;
while(e){ //然后就开始遍历输出每个结点的信息
cout << "-->" << "[" << e->adj << "]";
e = e->next;
}
cout << endl;
}
}
void DFS(Graph G, int i){
DFSvisited[i] = true; //标记为已访问
cout << G.Node[i].data << " "; //输出该顶点信息
Edge *p = G.Node[i].first;
while(p){
if(!DFSvisited[p->adj]) //若顶点未访问
DFS(G, p->adj); //递归调用
p = p->next;
}
}
void DFSTraverse(Graph G){ //深度搜索
for(int i=0; i<G.numVertex; i++)
DFSvisited[i] = false; //标记为未访问
cout << endl << "深度遍历:";
for(int i=0; i<G.numVertex; i++){
if(!DFSvisited[i]) //如果未访问
DFS(G, i);
}
}
int main(){
Graph G;
CreateGraph(G);
DFSTraverse(G);
return 0;
}
氷鸢鸢鸢
2020.2.13