广度优先搜索算法1-已知若干个城市的路线,求从一个城市到另外一个城市的路径,要求路径中经过的城市最少。

例8.1 城市A到城市B的交通图:
A->:b,c,d,f;
B->:a,f;
C->a,d,e;
D->a,d,g;
E->c,g,h;
F->a,b,h;
G->d,e,h;
H->e,f,g
从路线中可以看出A到H要经过若干个城市,现在要找出一条经过城市最少的路线

分析:
1.很容易想到用邻接矩阵来表示,0表示能走,1表示不能走
2.邻接矩阵最短路径想到用队列来表示
3.a数组是存储扩展节点的队列,a[i]记录经过的城市,b[i]记录前趋城市
4.将城市A入队,队首为0,队尾为1
5.将队首所指的城市所有可直通的城市入队(若出现过就不入队),将入地城市的前趋城市保存在b[i]中,
6.然后将队首加1,得到新的队首城市。重复以上步骤直到搜到H结束。
#include <iostream>
#include<bits/stdc++.h>
using namespace std;

int ju[9][9]{
        {0,0,0,0,0,0,0,0,0},
        {0,1,0,0,0,1,0,1,1},//a和a之间是1,是不能走的
        {0,0,1,1,1,1,0,1,1},
        {0,0,1,1,0,0,1,1,1},
        {0,0,1,0,1,1,1,0,1},
        {0,1,1,0,1,1,1,0,0},
        {0,0,0,1,1,1,1,1,0},
        {0,1,1,1,0,0,1,1,0},
        {0,1,1,1,1,0,0,0,1}
};
int a[101],b[101];
bool s[9];

//输出过程
void out(int d){
    cout<<char(a[d]+64);
    while(b[d]){
        d=b[d];
        cout<<"--"<<char(a[d]+64);
    }
    cout<<endl;
}

//BFS算法实现
void doit(){
    //数据初始化
    int head,tail,i;
    head=0;//队首为0
    tail=1;//队尾为1,因为a到a不能算
    a[1]=1;//记录经过的城市,现在第一个经过的是a本身
    b[1]=0;//记录前趋城市,a前面还没有城市
    s[1]=1;//表示该城市已经到过,现在已经到过a

    //循环判断
    do{
        head++;//队首加1,出队,从上一个城市往后走,第一次是从a开始
        for(i=1;i<=8;i++){//搜索可直达的城市
            if((ju[a[head]][i]==0&&(s[i]==0))){//下个城市能直达并且没被走过,就是可走
                tail++;//队尾加1
                a[tail]=i;//将i入队
                b[tail]=head;//记录tail的前趋城市
                s[i]=1;//记录该城市已经走过
                if(i==8){//第一次搜到的H城市最短
                    out(tail);
                    head=tail;
                    break;
                }
            }
        }
    }while(head<tail);
}

//主函数
int main(){
    memset(s, false, sizeof(s));
    doit();
    return 0;
}

运行结果:

总结:

广度优先搜索的核心思想
实际上是一个先进先出的队列(FIFO)
从初始节点开始,应用算符生成第一层节点,检查目标节点是否在这些后继节点中,
若没有,再用产生式规则将第一层的节点逐一扩展,得到第二层节点,并逐一检查第二层节点中是否包含目标节点,
若没有,再用算符逐一扩展到第二层的所有节点···
如此依次扩展,检查下去,直到发现目标节点为止

补充:

刚开始有点不太懂,即使懂了思想但是代码也不太理解,

但是画过图之后就比较容易理解了,这里以邻接链表为例

(参考青岛大学王卓老师的视频:https://www.bilibili.com/video/av36337654?from=search&seid=17495355141589125432

初始时: 

先访问v1,他有两个子节点,所以将v2,v3入队

(类似于邻接矩阵中的

if((ju[a[head]][i]==0&&(s[i]==0))){//下个城市能直达并且没被走过,就是可走
    tail++;//队尾加1
    a[tail]=i;//将i入队
    b[tail]=head;//记录tail的前趋城市
    s[i]=1;//记录该城市已经走过)

然后从v2开始访问,它的三个子节点是v1,v4,v5(对应序号是0,3,4)

v1访问过了,所以只用将v4,v5入对就可以了

以此类推,后面就是从v3开始,再将v6,v7入队

后面就是依次入队,出队..................

  • 5
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值