Bài viết được sự cho phép bởi tác giả Sơn Dương
Dijkstra là một trong những thuật toán rất nổi tiếng trong giới lập trình. Nghe tới những bài toán liên quan tới tìm đường đi ngắn nhất là nghĩ ngay tới thuật toán Dijkstra.
Dijkstra là thuật toán được đặt tên theo nhà khoa học máy tính người Phần Lan, người đã phát minh ra nó. Thuật toán này nhằm mục đích tìm đường đi ngắn nhất trong đồ thị có cạnh với trọng số dương.
Tổng quan thuật toán Dijkstra
Trước khi đi vào chi tiết nội dung thuật toán, chúng ta cần phải hiểu những thuật ngữ sau:
- Graph (đồ thị): Đồ thị là một cấu trúc dữ liệu phi tuyến tính được định nghĩa là G = (V, E), trong V là tập hợp hữu hạn các đỉnh (node), E là tập hợp hữu hạn các cạnh, cạnh là một đường nối giữa hai node với nhau.
- Weighted graph (đồ thị có trọng số): Tương tự như đồ thị ở trên, chỉ khác là mỗi cạnh sẽ được gán thêm một trọng số. Kiểu như cùng một khoảng cách đi từ A đến B, nhưng đi đường đẹp thì nhanh hơn, đường làng nhiều ổ gà thì chậm hơn.
- Connected graph (đồ thị liên thông): Một đồ thị được gọi là liên thông (connected) nếu có đường đi giữa mọi cặp đỉnh phân biệt của đồ thị. Ngược lại, đồ thị này được gọi là không liên thông.
- Spanning tree (cây khung): một spanning tree của đồ thị G là cây con của đồ thị G, chứa tất cả các đỉnh của G. Nói cách khác, cây bao trùm của một đồ thị G là một đồ thị con của G, chứa tất cả các đỉnh của G, liên thông và không có chu trình. Cây bao trùm của đồ thị liên thông G cũng có thể định nghĩa như một đồ thị con không chu trình lớn nhất, hay một đồ thị con liên thông nhỏ nhất của G.
Thuật toán Dijkstra giải quyết bài toán gì?
Cho một đồ thị có trọng số (đặt tên là đồ thị G). Mục tiêu là tìm đường đi ngắn nhất từ một đỉnh cho trước đến các đỉnh còn lại của đồ thị G.
Đồ thị G có các đặc điểm sau:
- Gồm tập hợp các đỉnh (V)
- Tập hợp các cạnh (E). Trong đó ký hiệu (q,r) là biểu diễn một cạnh nối giữa hai đỉnh q và r, cost(q,r) thì biểu thị trọng số của cạnh đó.
Ý tưởng thực hiện thuật toán Dijkstra
Thuật toán Dijkstra dựa trên nguyên tắc giảm bớt. Trong đó các giá trị chính xác hơn sẽ dần thay thế một giá trị gần đúng với khoảng cách chính xác cho đến khi đạt được khoảng cách ngắn nhất. Khoảng cách gần đúng tới mỗi định được ước tính lớn hơn nhiều khoảng cách thực và sẽ dần thay thế bằng giá trị nhỏ nhất của giá trị cũ bằng độ dài của một đường mới tìm được.
Thuật toán sử dụng hàng đợi ưu tiên kết hợp với thuật toán tham lam chọn đỉnh gần nhất chưa được xử lý và thực hiện quá trị giảm bớt này trên tất cả các cạnh mà nó duyệt qua.
Giả thuật các bước thực hiện:
Bước 1: Đánh dấu tất các node dự kiến: Đặt khoảng cách từ nút nguồn tới nút 0 là nguồn, và đặt là vô hạn với các nút khác.
Bước 2: Tiến hành chạy lặp (loop):
- Trích xuất nút N là nút có khoảng cách nhỏ nhất
- Thêm liên kết tới nút N vào cây đường đi ngắn nhất
- Sau đó tiến hành tối ưu các đường đi cạnh N bằng cách thử kéo dài cạnh
Tham khảo việc làm C++ hấp dẫn trên TopDev
Mã nguồn c++ minh họa thuật toán tìm đường đi ngắn nhất
Thuật toán có thể được implement bởi bất kỳ ngôn ngữ nào: C++, Java, hay Python…
Dưới đây là code minh họa bằng C++
Kết quả khi chạy chương trình:
Độ phức tạp của thuật toán: O(E.log(V))
Bài viết gốc được đăng tải tại vntalking.com
Xem thêm:
- Thuật toán tham lam (Greedy Algorithm) – Thực hành với C++
- Sử dụng thuật toán quay lui giải bài toán phân tích số bằng JavaScript
- Thuật toán frontend: Tìm node chứa content chính
Tham khảo ngay việc làm IT mọi cấp độ trên TopDev!