最少转机-图的广度优先遍历

众所周知,一般来说图的遍历方式有两种,一种是深度优先,一种是广度优先
1. 深度优先:针对某一条线走到尽头,然后依次回退1步,2步,…,n步来找寻另外的可能。

(注意此处回退是使用的系统栈,因此每一步需要保留信息,以便能够回退到上一层的变量应设置为局部变量,避免被全局覆盖造成错误!)

2, 广度优先:针对某个点,先找出该点一步可以走到的所有点,然后将其加入队列的尾部,同时保存步骤信息;接着将队首出队,队首指针指向下一个位置,然后查找该点一步可以走到的所有点,加入队尾,记录步骤信息(即队首指针指向的元素的步骤+1)。此时为了避免重复,需要设置一个全局的标记数组来表示是否已被访问。若已被访问,则跳过该点。
在此处以一张无向图查询最短路径来说明:
5 7 1 5//5个城市,7条航线,初始城市为1,结束城市为5
1 2//城市的连通情况
1 3
2 3
2 4
3 4
3 5
4 5

广度优先遍历代码如下(与书中有所不同,感觉这样更好理解):

// lessTransfer_BFS.cpp : 定义控制台应用程序的入口点。
//图的广度优先遍历,啊哈算法p142
#include "stdafx.h"
#include <stdio.h>  
#define MAX 6
int cityNum, lineNum, startCity, endCity;
int map[MAX][MAX];
int book[MAX];//所需的标记数组,因为只是点的关系,而非路径的关系,因此只需要一个一维数组即可,而不需要二维数组

struct cityNode {
    int node;//路径点
    int step;//步数
}cityQueue[MAX*MAX];//最坏情况下队列中有MAX*MAX个数

int main() {
    freopen("Text.txt", "r", stdin);
    scanf("%d %d %d %d", &cityNum, &lineNum, &startCity, &endCity);
    int tmp1, tmp2;
    for (int i = 1; i <= cityNum; i++) {
        book[i] = 0;
        for (int j = 1; j <= cityNum; j++) {
            map[i][j] = 0;
        }
    }
    for (int i = 1; i <= lineNum; i++) {
        scanf("%d %d", &tmp1, &tmp2);
        map[tmp1][tmp2] = 1;
        map[tmp2][tmp1] = 1;
    }

    int front, rear;//队首指针,队尾指针
    front = 0;//队首指针设为0,因为有初始化变量
    rear = 1;//队尾指针设为1,因为已经有了队首,因此在在添加到队尾时,自然是从1开始的
    cityQueue[front].node = startCity;//初始化队首
    cityQueue[front].step = 0;//初始化队首的步数,一开始还没有移动,赋值为0
    book[startCity] = 1;//起始的点已经走过了,后面不能再走了

    while (front != rear) {//当队列不为空的时候循环
        int curNode = cityQueue[front].node;//这种表示便于进行下一步操作
        int curStep = cityQueue[front].step;
        if (curNode == endCity) break;//当前点与终止点相同时,即到了最后一步,此时终止
        for (int k = 1; k <= cityNum; k++) {//遍历城市
            if (book[k] == 0 && map[curNode][k] == 1) {//当该城市未走过(未标记过),以及当前点可以到达该点时,表示该点可以通过
                book[k] = 1;//经过了该点,将该点设为已经过
                cityQueue[rear].node = k;//将该点加入队尾
                cityQueue[rear].step = curStep + 1;//经过该点时已经花费的步数为此次的起点已经花费的步数+1
                rear++;//队尾向后移动一个单位
            }
        }
        front++;//在当前点遍历完与之相邻一个单位的所有点时,该点就再也找不到其他点了,也就是说该点就没有用了,于是该点出队,队首指针指向队列中的下一位,再次重复相同的动作
    }
    printf("%d %d", cityQueue[rear-1].node, cityQueue[rear-1].step);//因为到最后rear++又增加了一位,因此实际的最终结果应该是rear-1所指向的位置
    return 0;
}

Github:https://github.com/sinjoywong/BFS_graphTraverse
(Reference:《啊哈算法》第五章 图的遍历,P143)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值