回溯的实现
深度遍历图最重要的思想:回溯。递归遍历二叉树就是一种回溯
递归遍历图为什么要循环 里 递归调用?
要先理解邻接矩阵:
因为是二维数组存图,既要知道行数(作为要选择路径的节点!),又要遍历列数(该节点要选择哪些路径节点!)。所以每一次进入for()循环 就是在选一个路径节点,每一次递归调用就是进入到下一个要选择路径的节点
所以需要循环(遍历找路径)里面套递归调用(找到一个节点路径,进入该节点!),并且需要传递列数作为下一层递归的行数
最后,当递归子程序跳到上一层,接着执行上一层未完的递归子程序,直到结束。
重要代码:
typedef struct
{
VertexType Vertex[VertexMax];//存顶点的一维数组
int AdjMatrix[VertexMax][VertexMax];//邻接矩阵二维数组
int vexnum, arcnum;//图的顶点数和边数
}MGraph;
//"标志"数组,代表是否访问
int visited[VertexMax];
//这里的int i 指的是每次递归的矩阵行数,即作为要选择路径的节点!所以需要先输出他,然后找下一个
void DFS(MGraph *G, int i)
{
int j;
//处理起始点
printf("%c", G->Vertex[i]);
visited[i]=1;
//递归的出口是for循环全部执行完,即j>=G->vexnum,每一个递归子程序都有自己的出口,
//跳出则进入上一层的递归
for(j=0; j<G->vexnum; j++){
//有边 && 没有被访问过 -> 递归调用
if(G->AdjMatrix[i][j]==1 && visited[j]==0){
DFS(G,j);
}
}
}
完整代码
//邻接矩阵深度遍历图
#include <stdio.h>
#include <stdlib.h>
#define VertexMax 100 //最大顶点数为100
typedef char VertexType; //每个顶点的数据类型为字符型
//图的数据结构
typedef struct
{
VertexType Vertex[VertexMax];//存顶点的一维数组
int AdjMatrix[VertexMax][VertexMax];//邻接矩阵二维数组
int vexnum, arcnum;//图的顶点数和边数
}MGraph;
void DFS(MGraph *, int );
//查找元素V在一维数组的下标
int LocationVex(MGraph *G, VertexType v)
{
int i;
for(i=0; i<G->vexnum; i++){
if(G->Vertex[i] == v){
return i;
}
}
printf("未找到该顶点%c", v);
return -1;
}
//建立图,使用邻接矩阵存储
void CreateUDG(MGraph *G)
{
int i, j;
printf("输入该图顶点数和边数:\n");
printf("顶点数 n=");
scanf("%d", &G->vexnum);
printf("边数 e=");
scanf("%d", &G->arcnum);
printf("\n");
printf("输入顶点元素名称(不需要空格隔开):");
scanf("%s", G->Vertex);
printf("\n");
//初始化矩阵
for(i=0; i<G->vexnum; i++){
for(j=0; j<G->vexnum; j++){
G->AdjMatrix[i][j] = 0;
}
}
int n, m;//两节点所在的位置,方便后续得到邻接矩阵
VertexType v1, v2;//接收输入的节点
printf("请输入边的两点信息:\n");
for(i=0; i<G->arcnum; i++){
scanf(" %c%c", &v1,&v2);
n = LocationVex(G, v1);
m = LocationVex(G, v2);
//若两节点不存在
if(m==-1 || n==-1){
printf("该边不存在!");
return;
}
//邻接矩阵赋值
G->AdjMatrix[n][m] = 1;
G->AdjMatrix[m][n] = 1;
}
}
void print(MGraph G)
{
int i, j;
printf("\n");
printf("\n邻接矩阵\n\n");
//打印横表头
printf(" ");
for(i=0; i<G.vexnum; i++){
printf(" %c", G.Vertex[i]);
}
printf("\n");
//打印列表头及邻接矩阵数据
for(i=0; i<G.vexnum; i++){
printf(" %c", G.Vertex[i]);
for(j=0; j<G.vexnum; j++){
printf(" %d", G.AdjMatrix[i][j]);
}
printf("\n");
}
}
//"标志"数组,代表是否访问
int visited[VertexMax];
void DFSTraverse(MGraph *G)
{
int i;
//初始化"标志"数组为0,代表未访问
for(i=0; i<G->vexnum; i++){
visited[i] = 0;
}
for(i=0; i<G->vexnum; i++){
if(visited[i] == 0){
DFS(G,i);
}
}
}
void DFS(MGraph *G, int i)
{
int j;
//处理起始点
printf("%c", G->Vertex[i]);
visited[i]=1;
for(j=0; j<G->vexnum; j++){
if(G->AdjMatrix[i][j]==1 && visited[j]==0){
DFS(G,j);
}
}
}
int main()
{
MGraph G;
CreateUDG(&G);
print(G);
printf("\n\n深度优先遍历:");
DFSTraverse(&G);
return 0;
}