10.1 单源无权BFS

  既然图算法的核心是图的BFS搜索。所以必须提前学习BFS搜索。
  首先为什么BFS搜索是最短路径?
  假设起点为S,终点为T。我们可以把图想象为一个个同心圆。直接与S相连的点,组成了一个以S为圆心,半径为1的圆。称之为集合 C 1 C_1 C1,以 C 1 C_1 C1直接相连的,组成了一个以S为圆心,半径为2的圆。称之为集合 C 2 C_2 C2,因为宽度搜索是按层进行的,那么顺序肯定是 S → C 1 → C 2 → … … C N S \rarr C_1 \rarr C_2 \rarr ……C_N SC1C2CN,T就在 C N C_N CN中。
  图的BFS搜索与树类似。因为图会存在环,为了避免无限循环,需要用一个hash set来&存储已访问过的数据。而找到之后,要回溯路径,需要记录上一个节点,这个时候就需要一个hashmap key为节点,value为parent节点。以下是图的BFS搜索代码:

public List<E> bfs(int first, int finalState) {
    // 宽度搜索。直接一个Deque
    HashMap<Integer,Integer> parentMap = new HashMap<>();
    HashSet<Integer> visited = new HashSet<>();

    Deque<Integer> deque = new LinkedList<>();
    deque.offer(first);

    Integer e = null;
    while (!Objects.equals(e, finalState) && !deque.isEmpty()) {
        e = deque.pollFirst();
        visited.add(e);
        List<? extends Edge> edgeList = this.edges[e];
        for (Edge edge : edgeList) {
            // 这里决定parent
            if (!visited.contains(edge.getTo())) {
                parentMap.put(edge.getTo(), edge.getFrom());
                deque.offerLast(edge.getTo());
            }
        }
    }
    List<E> path = new ArrayList<>();
    if (Objects.equals(e, finalState)) {
        for (Integer i = e; i != null; i = parentMap.get(i)) {
            Vertex<E> vertex = vertices[i];
            path.add(vertex.getValue());
        }
    }
    Collections.reverse(path);
    return path;
}

  python代码:

def bfs(self, start, end, visitor):
    parent_map = {}
    # 因为python 没有hashset,所以以字典代替
    visited = {}
    queue = []
    queue.append(start)
    e = start
    while e != end and len(queue) != 0:
        e = queue.pop(0)
        visitor(self.__vertices[e])
        visited[e] = 1
        # 把点连接的点全部放入队列中
        for child in self.__edges[e]:
            if child not in visited:
                parent_map[child] = e
                queue.append(child)
    # 没有找到
    if e != end:
        return []

    # 找到之后组装路径
    path = [end]
    while end != start:
        # 不停地找parent
        end = parent_map[end]
        path.append(end)
    path.reverse()
    return path
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

醒过来摸鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值