路径搜索算法——Dijkstra算法

路径搜索算法——Dijkstra算法

一、Dijkstra 算法简介

Dijkstra 算法是由荷兰计算机科学家 Edsger W. Dijkstra 于 1956 年提出的,用于单源最短路径问题——即从一个起点出发,寻找图中所有点的最短路径(常用于路径规划中)。

🚗 在自动驾驶中,Dijkstra 常用于静态全局路径规划,如在无障碍、无启发函数的高清地图上寻找最短通行路径。


二、算法核心思想

  • 使用贪心策略

  • 每次从未访问节点中选择距离起点最近的一个节点进行扩展;

  • 一旦某节点的最短路径被确定,就不会被更新

    我们定义如下无向图(图中数字为边权):

    在这里插入图片描述

邻接表表示

graph = {
  A: [(B,1), (C,4)],
  B: [(A,1), (D,2), (E,5)],
  C: [(A,4), (F,1)],
  D: [(B,2), (E,1)],
  E: [(B,5), (D,1), (F,3)],
  F: [(C,1), (E,3)]
}

Dijkstra 算法执行过程(起点 A)

初始化:

节点最短距离说明
A0起点
B
C
D
E
F

队列:[(0, A)]


🔁 第 1 轮:处理 A,当前距离 0

邻居更新:

  • B:0 + 1 = 1
  • C:0 + 4 = 4

更新后:

节点最短距离
A0
B1 ✅
C4 ✅
D~F

队列:[(1, B), (4, C)]


🔁 第 2 轮:处理 B,当前距离 1

邻居更新:

  • D:1 + 2 = 3
  • E:1 + 5 = 6
  • A:已访问

更新后:

节点最短距离
A0
B1
C4
D3 ✅
E6 ✅
F

队列:[(3, D), (4, C), (6, E)]


🔁 第 3 轮:处理 D,当前距离 3

邻居更新:

  • E:3 + 1 = 4(比原来 6 小)→ 更新为 4

更新后:

节点最短距离
A0
B1
C4
D3
E4 ✅
F

队列:[(4, C), (4, E), (6, E)]


🔁 第 4 轮:处理 C,当前距离 4

邻居更新:

  • F:4 + 1 = 5

更新后:

节点最短距离
F5 ✅

队列:[(4, E), (6, E), (5, F)]


🔁 第 5 轮:处理 E,当前距离 4

邻居:

  • B、D:已访问
  • F:4 + 3 = 7 > 当前 F=5 → 跳过

无更新。

队列:[(5, F), (6, E)]


🔁 第 6 轮:处理 F,当前距离 5

邻居:

  • C、E:已访问

无更新。


✅ 最终结果(起点 A 出发的最短路径)

节点最短距离最短路径
A0A
B1A → B
C4A → C
D3A → B → D
E4A → B → D → E
F5A → C → F

三、算法步骤(伪代码)

1. 初始化每个点的距离为 ∞,起点为 0
2. 创建优先队列,加入起点
3. 当队列非空:
    a. 取出距离最小的节点 u
    b. 遍历 u 的所有邻居 v:
        - 如果通过 u 到 v 的距离更短,则更新 v 的距离
        - 将 v 加入队列
4. 最终,所有点的最短路径就被记录

四、C++ 示例代码:Dijkstra 网格图最短路径

cpp复制编辑#include <iostream>
#include <vector>
#include <queue>
#include <unordered_map>
#include <utility>

using namespace std;

// 定义坐标类型
typedef pair<int, int> Point;

// 定义方向(上下左右)
const vector<Point> directions = {
    {-1, 0}, {1, 0}, {0, -1}, {0, 1}
};

// 判断点是否在地图内且为可通行(0)
bool isValid(int x, int y, const vector<vector<int>>& grid) {
    int rows = grid.size(), cols = grid[0].size();
    return x >= 0 && x < rows && y >= 0 && y < cols && grid[x][y] == 0;
}

// 哈希函数,用于 unordered_map<pair<int,int>, int>
struct pair_hash {
    size_t operator()(const Point& p) const {
        return hash<int>()(p.first) ^ (hash<int>()(p.second) << 1);
    }
};

// Dijkstra 主函数:返回从 start 到所有可达点的最短距离
unordered_map<Point, int, pair_hash>
dijkstra(const vector<vector<int>>& grid, Point start) {
    unordered_map<Point, int, pair_hash> dist;
    priority_queue<pair<int, Point>, vector<pair<int, Point>>, greater<>> pq;

    dist[start] = 0;
    pq.push({0, start});

    while (!pq.empty()) {
        auto [cost, point] = pq.top();
        pq.pop();

        for (auto [dx, dy] : directions) {
            int nx = point.first + dx;
            int ny = point.second + dy;
            Point neighbor = {nx, ny};

            if (!isValid(nx, ny, grid)) continue;

            int new_cost = cost + 1;  // 每步代价为 1
            if (!dist.count(neighbor) || new_cost < dist[neighbor]) {
                dist[neighbor] = new_cost;
                pq.push({new_cost, neighbor});
            }
        }
    }

    return dist;
}

int main() {
    // 地图示例:0 表示可通行,1 表示障碍
    vector<vector<int>> grid = {
        {0, 0, 0, 0},
        {1, 1, 0, 1},
        {0, 0, 0, 0},
        {0, 1, 1, 0},
        {0, 0, 0, 0}
    };

    Point start = {0, 0};  // 起点坐标

    // 执行 Dijkstra 算法
    auto result = dijkstra(grid, start);

    // 输出所有可达点及其最短距离
    cout << "从 (" << start.first << "," << start.second << ") 出发的最短距离:" << endl;
    for (const auto& [point, d] : result) {
        cout << "(" << point.first << "," << point.second << ") : " << d << endl;
    }

    return 0;
}

五、Python 简化实现(二维网格图)

python复制编辑import heapq

def dijkstra(grid, start):
    rows, cols = len(grid), len(grid[0])
    dist = {start: 0}
    visited = set()
    pq = [(0, start)]  # (distance, position)

    while pq:
        d, (x, y) = heapq.heappop(pq)
        if (x, y) in visited:
            continue
        visited.add((x, y))

        for dx, dy in [(-1,0), (1,0), (0,-1), (0,1)]:
            nx, ny = x + dx, y + dy
            if 0 <= nx < rows and 0 <= ny < cols and grid[nx][ny] == 0:
                new_dist = d + 1
                if (nx, ny) not in dist or new_dist < dist[(nx, ny)]:
                    dist[(nx, ny)] = new_dist
                    heapq.heappush(pq, (new_dist, (nx, ny)))

    return dist  # 返回从起点到所有可达点的最短距离

六、A* vs Dijkstra 对比

特性DijkstraA*(A-star)
是否启发式是(需设计启发函数)
搜索策略扩展所有路径朝着目标方向智能搜索
保证最优路径✅ 是✅ 是(启发函数可接受)
性能(搜索效率)较慢通常更快(剪枝更多)
应用场景静态全局规划实时决策与动态路径规划

七、优缺点总结

✅ 优点:

  • 简洁、稳定、易于实现;
  • 不依赖启发函数,适用于所有加权图;
  • 可求任意点对最短路径。

❌ 缺点:

  • 搜索空间大(尤其是地图大时),效率低;
  • 不考虑目标方向,盲目扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值