Dijkstra算法详细(单源最短路径算法)

我们大部分人可能比较了解BFS 和 DFS,对于Dijkstra算法他是图算法结构中解决单源最短路径问题的算法。

大概就是这样一个有权图,Dijkstra算法可以计算任意节点到其他节点的最短路径。(单源最短路径问题),Dijkstra算法只能求一个顶点到其他点的最短距离而不能任意两点。
在这里插入图片描述
首先我们先回顾一下图论的基础吧,
一幅图是由节点和边构成的,逻辑结构如下,通常我们会用邻接表或邻接矩阵来实现:
在这里插入图片描述
在这里插入图片描述
①邻接表很直观,我把每个节点 x 的邻居都存到一个列表里,然后把 x 和这个列表关联起来,这样就可以通过一个节点 x 找到它的所有相邻节点。

②邻接矩阵则是一个二维布尔数组,我们权且成为 matrix,如果节点 x 和 y 是相连的,那么就把 matrix[x][y] 设为 true(上图中绿色的方格代表 true)。如果想找节点 x 的邻居,去扫一圈 matrix[x][…] 就行了。

优缺点:
对于邻接表,好处是占用的空间少。但是,邻接表无法快速判断两个节点是否相邻。

比如说我想判断节点 1 是否和节点 3 相邻,我要去邻接表里 1 对应的邻居列表里查找 3 是否存在。但对于邻接矩阵就简单了,只要看看 matrix[1][3] 就知道了,效率高。

有向加权图的实现
如果是邻接表,我们不仅仅存储某个节点 x 的所有邻居节点,还存储 x 到每个邻居的权重。
如果是邻接矩阵,matrix[x][y] 不再是布尔值,而是一个 int 值,0 表示没有连接,其他值表示权重。

无向图怎么实现
如果连接无向图中的节点 x 和 y,把 matrix[x][y] 和 matrix[y][x] 都变成 true 不就行了;邻接表也是类似的操作。

图的遍历
图和多叉树最大的区别是,图是可能包含环的,你从图的某一个节点开始遍历,有可能走了一圈又回到这个节点。所以,如果图包含环,遍历框架就要一个 visited 数组进行辅助;

boolean[] visited;

/* 图遍历框架 */
void traverse(Graph graph, int s) {
   
    if (visited[s]) return;
    // 经过节点 s
    visited[s] = true;
    for (int neighbor : graph.neighbors(s))
        traverse(graph, neighbor);
    // 离开节点 s
    visited[s] = false;   
}

这个 visited 数组的操作很像回溯算法做「做选择」和「撤销选择」,区别在于位置,回溯算法的「做选择」和「撤销选择」在 for 循环里面,而对 visited 数组的操作在 for 循环外面。

1.二叉树层级遍历和 BFS 算法

在这里插入图片描述

// 输入一棵二叉树的根节点,层序遍历这棵二叉树
void levelTraverse(TreeNode root) {
   
    if (root == null) return 0;
    Queue<TreeNode> q = new LinkedList<>();
    q.offer(root);

    int depth = 1;
    // 从上到下遍历二叉树的每一层
    while (!q.isEmpty()) {
   
        int sz = q.size();
        // 从左到右遍历每一层的每个节点
        for (int i = 0; i < sz; i++) {
   
            TreeNode cur = q.poll();
            printf("节点 %s 在第 %s 层", cur, depth);

            // 将下一层节点放入队列
            if (cur.left != null) {
   
                q.offer(cur.left);
            }
            if (cur.right != null) {
   
                q.offer(cur.right);
            }
        }
        depth++;
    }
  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值