大家好,这里是一个小白的第一篇博客。好了话不多说,进入正题!!!
1,深e度优'先,这里先对其进行遍历,一定要往下看啊,下面有重点
#include <stdio.h>
int book[101],sum = 0,n,e[101][101];
void dfs(int cur)
{
int i;
printf("%d",cur);
sum++;
if(sum == n)
{
return;//这个return是满足条件时,结束这个程序
}
for(i = 1;i <= n;i++)
{
if(e[cur][i] == 1 && book[i] == 0)//cur表示当前所在点,e[cur][i]表示当前点到i点是否有边
{
book[i] = 1;
dfs(i);(1)
}
}
return;//返回上一顶点,继续检测上一个点是否有其他相邻的点 ,因为这里是无向图,所以不需要在(1)后面加上book[i] = 0;
}
int main ()
{
int i,j,m,a,b;
scanf("%d %d",&n,&m);
for(i = 1;i <= n;i++)
for(j = 1;j <= n;j++)
if(i == j) e[i][j] = 0;
else e[i][j] = 99;
//读入顶点之间的边
for(i = 1;i <= m;i++)
{
scanf("%d %d",&a,&b);
e[a][b] = 1;
e[b][a] = 1;//该图是无向图 ,如果是有向图,即确定了方向,只需用这两个中的第一个
}
book[1] = 1;
dfs(1);//即从1点开始遍历
return 0;
}
程序输入:5 5
1 2
1 3
1 5
2 4
3 5
将会得到:1 2 4 3 5;
广度优先,无向图遍历
#include <stdio.h>
int main ()
{
int i,j,n,m,a,b,cur,book[101] = {0},e[101][101];
int que[10001],head,tail;
scanf("%d %d",&n,&m);
for(i = 1;i <= n;i++)
for(j = 1;j <= n;j++)
if(i == j) e[i][j] = 0;
else e[i][j] = 999999;
for(i = 1;i <= m;i++)
{
scanf("%d %d",&a,&b);
e[a][b] = 1;//对无向图需要这么做,
e[b][a] = 1;
}
head = 1;
tail = 1;
que[tail] = 1;//起始点为1
tail++;
book[1] = 1;
while(head < tail)
{//当队列不为空
cur = que[head];
for(i = 1;i <= n;i++)
{
if(e[cur][i] == 1&&book[i] == 0)
{
que[tail] = i;
tail++;
book[i] = 1;
}
if(tail > n)//退出循环的条件
{
break;
}
}
head++;//从上一轮第一次扩展的点处继续扩展
}
for(i = 1;i <= n;i++)
printf("%d ",que[i]);
return 0;
}
这里输入和上面一样,但是输出结果1 2 3 5 4;
这是为什么呢?
这正是我要说的,深度优先是确定好一个方向,一直向前走,知道无路可走,则返回上一级,一直到某一个地方有了其他的选择
而广度优先是从起点开始,一层一层向外扩展,即先把与起点相邻且满足条件的店扩展并放进队列之中,而运用队列是为了将结果储存起来,而上面的队列之所以是这种形式,完全是题目要求只需要输出遍历顺序,不需要其他变量。
上面的例子只是最基本的,而下面的例子则不是对数据简单的排序,而加入了一些要求,即需要通过编程解决一些实际问题,
就如我们使用的高德地图,在你输入目的地之后能够为你生成一条最优路线,其中你还可以选择少换乘或是时间更多,诸如此类条件,,,,,,个人觉得都和下面的算法有关
深度优先
#include <stdio.h>
int min = 999999,book[101],n,e[101][101];
void dfs(int cur,int dis)
{
int j;
if(dis>min) return;//目的是确保输出的是最短的路程
if(cur == n)//
{
if(dis < min) min = dis;//dis即distant的缩写,代表路程
return;
}
for(j = 1;j <= n;j++)
{
if(e[cur][j] != 999999&&book[j] == 0)
{
book[j] = 1;
dfs(j,dis+e[cur][j]);
book[j] = 0;
}
}
return;
}
int main ()
{
int i,j,m,a,b,c;
scanf("%d %d",&n,&m);//n表示点数,m表示这五点见有几条路
for(i = 1;i <= n;i++)
for(j = 1;j <= n;j++)
if(i == j) e[i][j]= 0;
else e[i][j] = 999999;
for(i = 1;i <= m;i++)
{
scanf("%d %d %d",&a,&b,&c);
e[a][b] = c;
}
book[1] = 1;
dfs(1,0);//起点为1,起始路程为0
printf("%d",min);
return 0;
}
输入:5 8
1 2 2
1 5 10
2 3 3
2 5 7
3 1 4
3 4 4
4 5 5
5 3 3输出:9
#include <stdio.h>
struct note
{
int x;//城市编号
int s;//转机次数
};
int main ()
{
struct note que[2501];
int e[51][51] = {0},book[51] = {0};
int head,tail;
int i,j,n,m,a,b,cur,start,end,flag = 0;
scanf("%d %d %d %d",&n,&m,&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] = 999999;
for(i = 1;i <= m;i++)
{
scanf("%d %d",&a,&b);//补充一下这里2和4之间有连线,画图画掉了
e[a][b] = 1;//对无向图需要这么做,
e[b][a] = 1;
}
head = 1;
tail = 1;
que[tail].x = start;
que[tail].s = 0;
tail++;
book[1] = start;
while(head < tail)
{
cur = que[head].x;
for(j = 1;j <= n;j++)
{
if(e[cur][j] != 999999&&book[j] == 0)
{
que[tail].x = j;
que[tail].s = que[head].s+1;//转机次数加一
tail++;
book[j] = 1;
}
if(que[tail].x == end)
{
flag = 1;
break;
}
}
if(flag == 1)
break;
head++;
}
printf("%d ",que[tail-1].s);//因为tail指向为节点的下一个节点,所以要减去1
return 0;
}
输入:5 7 1 5
1 2
1 3
2 3
2 4
3 4
3 5
4 5输出
:2
再说一遍,队列只是为了储存你想要得到的东西。这俩个例子实际上都可以换成两种方法中的另一种方法来做,这里广度优先搜索更加适合于两点间权值相同的情况。
希望多多支持!!!