这篇博客很早之前就写好了,但是一直没有发出来。。。。。。
在进行详细解说之前,我们需要先借用图的概念,图就是由一些小圆点(称为顶点)和连接这些小圆点的直线(称为边)组成的。如下图是由5个顶点(1,2,3,4,5)和5条边(1-2,1-2,1-4,2-5,3-4)组成的。
现在我们从一号顶点开始遍历这个图,使用深度优先搜索来遍历这个图将会得到如下的结果:
使用深度优先搜索来遍历这个图的过程具体是:首先从一个未走到过的顶点作为起始顶点,比如以1号顶点作为起点。沿1号顶点的边去尝试访问其他走到过得顶点,首先访问2号顶点还没有走到过,于是来到2号顶点。再以2号顶点作为出发点继续尝试访问其他未走过的顶点,这样又来到了4号顶点,再以4号顶点作为出发点继续尝试访问其他未走到过的顶点。但是,此时沿4号顶点的边,已经不能访问到其他未走到过的顶点了,所以需要返回到2号顶点。返回到2号顶点后,发现沿2号顶点的边也不能再访问到其他未走到过的顶点。因此还需要继续返回到1号顶点。再继续沿1号顶点的边看看还能否访问到其他为走到过的顶点。此时又会来到5号顶点。到此,所有的顶点都走到了,遍历结束。
深度优先遍历的主要思想是:首先以一个未访问过的顶点作为起始顶点,沿当前顶点的边走到未访问过的顶点;当没有未访问过的顶点时,则回到上一个顶点,继续试探访问别的访问,知道所有的顶点都被访问过。显然,深度优先搜索的遍历先沿着图的某一条分支遍历直到末端,然后回溯,再沿着另一条进行同样的遍历,直到所有的顶点都被访问过为止。
在用深度优先搜索时,最常使用的方法是用一个二维数组e来存储。二维数组中的第i行第j列表示的就是顶点i到顶点j是否有边,1表示有边,∞表示没有边。这里我们将自己到自己设为0(即I=j),我们将这种存储的方法称为图的邻接矩阵存储法。
广度优先遍历的主要思想就是:首先以一个未被访问过得顶点作为起始顶点,访问其所有的相邻的顶点,然后对每个相邻的顶点,再访问他们相邻的未被访问过的顶点,直到所有的顶点都被访问过,遍历结束。广度优先遍历往往是要用到队列这个概念的。
深度优先搜索和广度优先搜索的区别:
例1:小哼和小哈一同坐飞机去旅游,他们现在位于1号城市,目标是5号城市,可是1号城市并没有5号城市的直航。不过小哼已经收集了很多航班的信息,吸纳子啊小哼希望找到一种乘坐方式,使得转机的次数最少,该如何解决?(题目来源于:阿哈雷写的《啊哈,算法!》)
下面分别用两种方式来解决这个问题:
深度优先搜索:
#include<stdio.h>
int e[100][100];
int book[100];
int min = 9999999;
int end; //结束的站点
int n;//n个城市
void dfs(int cur,int sum)
{
int i;
if(sum > min)
{
return;
}
if(cur == end)
{
if(sum < min)
{
min = sum;
}
return;
}
for(i = 0; i < n; i++)
{
if(book[i] == 0 && e[cur][i] != 99999999)
{
book[i] = 1;
dfs(i,sum+e[cur][i]);
book[i] = 0;
}
}
}
int main()
{
int a;
int b;
int i;
int j;
int m;//m个航线
int start;//开始的站点
scanf("%d %d",&n,&m);
printf("m = %d\n",m);
scanf("%d %d",&start,&end);
for(i = 0; i < n; i++)
{
for(j = 0; j < n; j++)
{
if(i == j)
{
e[i][j] = 0;
}
else
{
e[i][j] = 99999999;
}
}
}//初始化数组
//获取两个站点之间的航线
for(i = 0; i < m; i++)
{
scanf("%d %d",&a,&b);
e[a][b] = 1;
e[b][a] = 1;
}
book[start] = 1;
dfs(start,0);
printf("min = %d\n",min);
}
结果:
法二:广度优先搜索
#include<stdio.h>
struct queue
{
int n;//城市次数
int sum;//转机次数
};
int main()
{
struct queue que[100];
int e[100][100];
int book[100];
int n;
int m;
int start;
int end;
int flag;
int i;
int j;
int a;
int b;
int head = 1;
int tail = 1;
scanf("%d %d",&n,&m);
scanf("%d %d",&start,&end);
for(i = 1; i <= n; i++)
{
for(j = 1; j <= n; j++)
{
if(i == j)
{
e[i][j] = 0;
}
else
{
e[i][j] = 99999999;
}
}
}
for(i = 1; i <= m; i++)
{
scanf("%d %d",&a,&b);
e[a][b] = 1;
e[b][a] = 1;
}
que[tail].n = start;
que[tail].sum = 0;
tail++;
book[start] = 1;
while(head < tail)
{
int cur = que[head].n;//当前的城市
for(i = 1; i <= n; i++)
{
if(e[cur][i] != 99999999 && book[i] == 0)
{
que[tail].n = i;
que[tail].sum = que[head].sum + 1;
tail++;
book[i] = 1;
}
if(que[tail-1].sum == end)
{
flag = 1;
break;
}
}
if(flag == 1)
{
break;
}
head++;
}
printf("min = %d",que[tail-1].sum);
}
结果:
以上:我也不知道自己写了些啥?最近效率有点低。。。。。。。