Duyệt đồ thị theo chiều sâu DFS-Depth First Search:DFS là thuật toán được sử dụng để tìm kiếm hay duyệt qua tất cả các đỉnh thuộc các thành phần liên thông của đồ thị một cách có hệ thốn
lOMoARcPSD|39108650 BỘ CÔNG THƯƠNG TRƯỜNG ĐẠI HỌC CÔNG THƯƠNG TP.HỒ CHÍ MINH Đồ án học phần: CẤU TRÚC RỜI RẠC Tên đề tài: Mô phỏng chức năng đón trả khách của ứng dụng xe ôm công nghệ dựa trên thuật toán Dijkstra Lớp: 13DHTH03 - Nhóm 17 Danh sách thành viên: STT Họ và Tên MSSV TLĐG 2001221771 100% 1 Trần Nguyễn Như Huỳnh 2001221741 100% 2001222369 100% 2 Ngô Thị Thanh Huyền 2001225381 100% 3 Nguyễn Mai Linh 4 Nguyễn Xuân Trang GV hướng dẫn: Đinh Thị Hồng Loan Thành phố Hồ Chí Minh, tháng 12 năm 2023 Downloaded by ANH LE (bachvan14@gmail.com) lOMoARcPSD|39108650 MỤC LỤC 1 Lý thuyết đồ thị và ứng dụng: .1 1.1 Khái niệm đồ thị: 1 1.2 Phân loại: .1 1.2.1 Đơn đồ thị vô hướng: .1 1.2.2 Đa đồ thị vô hướng: .2 1.2.3 Giả đồ thị: .2 1.2.4 Đơn đồ thị có hướng: .3 1.2.5 Đa đồ thị có hướng: .3 1.3 Các bài toán về đồ thị và ứng dụng: 4 1.3.1 Duyệt đồ thị: 4 1.3.2 Đường đi Euler – Chu trình Euler: 5 1.3.3 Đường đi Hamilton – Chu trình Hamilton: 6 1.3.4 Bài toán tìm cây khung ngắn nhất: 7 1.3.5 Bài toán tìm đường đi ngắn nhất: 9 1.4 Ứng dụng: 11 2 Bài toán thực tế: 11 2.1 Mô tả bài toán và giải pháp: 11 2.2 Cấu trúc dữ liệu và giải thuật: 12 2.2.1 Cấu trúc dữ liệu: 12 2.2.2 Giải thuật: .14 3 Kết quả cài đặt và thử nghiệm: 20 3.1 Nền tảng, ngôn ngữ cài đăt: .20 3.2 Các giao diện của chương trình: 20 3.3 Thử nghiệm: 21 3.3.1 Test case : 21 3.3.2 Input: 22 3.3.3 Output: 23 4 Kết luận: 26 Downloaded by ANH LE (bachvan14@gmail.com) lOMoARcPSD|39108650 1 Lý thuyết đồ thị và ứng dụng: 1.1 Khái niệm đồ thị: • Đồ thị là một cấu trúc rời rạc bao gồm các đỉnh và các cạnh nối các đỉnh này • Phân biệt các loại đồ thị khác nhau bởi kiểu và số lượng cạnh nối hai đỉnh nào đó của đồ thị 1.2 Phân loại: 1.2.1 Đơn đồ thị vô hướng: Đơn đồ thị vô hướng G = (V,E) bao gồm: • V: là tập các đỉnh của G; V ≠∅ • E: là tập các cặp không có thứ tự gồm hai phần tử khác nhau của V gọi là các cạnh Hình 1 Sơ đồ mạng máy tính đơn kênh thoại 1 Downloaded by ANH LE (bachvan14@gmail.com) lOMoARcPSD|39108650 1.2.2 Đa đồ thị vô hướng: Đa đồ thị vô hướng G= (V, E) bao gồm: • V: là tập các đỉnh; V ≠∅ • E: là tập các cặp không có thứ tự gồm hai phần tử khác nhau của V gọi là các cạnh Hai cạnh e1 và e2 được gọi là cạnh lặp (bội hay song song) nếu chúng cùng tương ứng với một cặp đỉnh Hình 2 Sơ đồ mạng máy tính đa kênh thoại Mỗi đơn đồ thị là đa đồ thị, nhưng không phải đa đồ thị nào cũng là đơn đồ thị, vì trong đa đồ thị có thể có hai (hoặc nhiều hơn) cạnh nối một cặp đỉnh nào đó 1.2.3 Giả đồ thị: Giả đồ thị vô hướng G = (V, E) bao gồm: • V: là tập các đỉnh; V ≠∅ • E: là tập các cặp không có thứ tự gồm hai phần tử (không nhất thiết phải khác nhau) của V gọi là cạnh Với v ∈ V, nếu (v,v) ∈ E thì ta nói có một khuyên tại đỉnh v 2 Downloaded by ANH LE (bachvan14@gmail.com) lOMoARcPSD|39108650 1.2.4 Đơn đồ thị có hướng: Đơn đồ thị có hướng G = (V, E) bao gồm: • V: là tập các đỉnh; V ≠ ∅ • E: là tập các cặp có thứ tự gồm hai phần tử khác nhau của V gọi là các cung 1.2.5 Đa đồ thị có hướng: Đa đồ thị có hướng G = (V, E) bao gồm: • V: là tập các đỉnh; V ≠ ∅ • E: là tập các cặp có thứ tự gồm hai phần tử khác nhau của V gọi là các cung Hai cung e1, e2 tương ứng với cùng một cặp đỉnh được gọi là cung lặp 3 Downloaded by ANH LE (bachvan14@gmail.com) lOMoARcPSD|39108650 Nhận xét: ‐ Giả đồ thị là loại đồ thị vô hướng tổng quát nhất vì nó có thể chứa các khuyên và các cạnh lặp ‐ Đa đồ thị là loại đồ thị vô hướng có thể chứa cạnh bội nhưng không thể có các khuyên ‐ Đơn đồ thị là loạiđồ thị vô hướng không chứa cạnh bội hoặc các khuyên 1.3 Các bài toán về đồ thị và ứng dụng: 1.3.1 Duyệt đồ thị: 1.3.1.1 Duyệt đồ thị theo chiều sâu (DFS-Depth First Search): DFS là thuật toán được sử dụng để tìm kiếm hay duyệt qua tất cả các đỉnh thuộc các thành phần liên thông của đồ thị một cách có hệ thống với kỹ thuật gọi là độ ưu tiên sâu Ứng dụng giải các bài toán về liên thông, cây khung, đường đi… * Ý tưởng: ‐ Xuất phát từ một đỉnh v cho trước chưa thăm ‐ Thăm đỉnh v và tìm đỉnh u nào đó chưa thăm kề với v, thăm u và lặp lại quá trình này cho đến khi tất cả các đỉnh đều được thăm ‐ Nếu tại một đỉnh u nào đó mà không còn đỉnh kề chưa thăm thì quay trở lại đỉnh trước của u (có đỉnh kề là u 4 Downloaded by ANH LE (bachvan14@gmail.com) lOMoARcPSD|39108650 trong đường đi đến u) và tìm các đỉnh kề chưa thăm của đỉnh này 1.3.1.2 Duyệt đồ thị theo chiều rộng (BFS-Breadth First Search): Thuật toán BFS dùng để duyệt và tìm kiếm trên đồ thi cũng tương tự như thuật toán DFS nhưng thay vì dùng cấu trúc stack thì BFS dùng cấu trúc hàng đợi để thực hiện, kỹ thuật này gọi là tìm kiếm ưu tiên chiều rộng * Ý tưởng: ‐ Xuất phát từ đỉnh v cho trước chưa thăm, bỏ v vào hàng đợi ‐ Lấy từ hàng đợi đỉnh u, thăm u và bỏ các đỉnh kề chưa thăm của u vào hàng đợi ‐ Lặp lại cho đến khi hàng đợi rỗng 1.3.2 Đường đi Euler – Chu trình Euler: 1.3.2.1 Bài toán Euler: ‐ 1736 Euler (1707-1783) công bố lời giải “bài toán về các cầu ở Konigsberg” ‐ Bài toán: Thị trấn Konigsberg chia thành 4 phần bởi các nhánh của dòng sông Pregel Bốn phần này được kết nối bởi 7 cây câu 5 Downloaded by ANH LE (bachvan14@gmail.com) lOMoARcPSD|39108650 Bài toán tìm đường đi qua tất cả các cầu, mỗi cầu chỉ qua một lần có thể được phát biểu lại bằng mô hình như sau: 1.3.2.2 Đường đi Euler: ‐ Đường đi qua mỗi cạnh của đồ thị đúng một lần được gọi là đường đi Euler ‐ Chu trình qua mỗi cạnh của đồ thị đúng một lần được gọi là chu trình Euler ‐ Đồ thị được gọi là đồ thị Euler nếu nó có chu trình Euler, và gọi là đồ thị nửa Euler nếu nó có đường đi Euler Nhận xét: Mọi đồ thị Euler luôn là nửa Euler,nhưng điều ngược lại không luôn đúng 1.3.2.3 Thuật toán Fleury tìm chu trình Euler: Xuất phát từ một đỉnh u nào đó của G ta đi theo các cạnh của nó một cách tuỳ ý chỉ cần tuân thủ 2 qui tắc sau: (1) Xoá bỏ cạnh đã đi qua đồng thời xoá bỏ đỉnh cô lập tạo thành (2) Ở mỗi bước ta chỉ đi qua cầu khi không còn cách lựa chọn nào khác 1.3.3 Đường đi Hamilton – Chu trình Hamilton: 6 Downloaded by ANH LE (bachvan14@gmail.com) lOMoARcPSD|39108650 1.3.3.1 Định nghĩa: Xét G liên thông có hơn 1 đỉnh • Đường đi Hamilton: (nếu có) là đường đi mà đi qua tất cả các đỉnh của G mỗi đỉnh đúng 1 lần • Chu trình Hamilton: là một chu trình xuất phát từ 1 đỉnh, đi qua tất cả các đỉnh của đồ thị G mỗi đỉnh đúng một lần, cuối cùng quay lại đỉnh xuất phát • Đồ thị được gọi là đồ thị Hamilton nếu nó có chu trình Hamilton Đồ thị được gọi là đồ thị nửa Hamilton nếu nó có đường đi Hamilton → Nếu G có chu trình Hamilton thì G cũng có đường đi Hamilton Điều ngược lại không đúng 1.3.3.2 Qui tắc tìm chu trình Hamilton: (1) Nếu tồn tại 1 đỉnh của G có bậc 2 đỉnh, mỗi đỉnh có bậc không nhỏ hơn n/2 là đồ thị Hamilton • Định lý 2: Nếu G là đồ thị phân đôi với hai tập đỉnh là V1, V2 có số đỉnh cùng bằng n (n ≥ 2) và bậc của mỗi đỉnh lớn hơn n/2 thì G là một đồ thị Hamilton • Định lý 3: Giả sử G là đồ có hướng liên thông với n đỉnh Nếu deg+(v) ≥ n/2, deg–(v) ≥ n/2, ∀v thì G là Hamilton 1.3.4 Bài toán tìm cây khung ngắn nhất: 7 Downloaded by ANH LE (bachvan14@gmail.com) lOMoARcPSD|39108650 * Định nghĩa cây khung ngắn nhất: Cho một đồ thị vô hướng G, trên mỗi cạnh của G được gán một trọng số c(i,j) Cây khung T của G được gọi là cây khung ngắn nhất nếu tổng trọng số các cạnh của T là nhỏ nhất * Bài toán tìm cây khung ngắn nhất: Bài toán đặt ra là trong số tất cả các cây khung của đồ thị G, tìm cây khung có độ dài nhỏ nhất Hai mô hình thực tế tiêu biểu: ‐ Bài toán xây dựng hệ thống đường sắt ‐ Bài toán nối mạng máy tính 1.3.4.1 Thuật toán Kruskal: 1.3.4.2 *Ý tưởng: Bước 1: Sắp xếp các cạnh theo thứ tự tăng dần của trọng số, T = ∅ Bước 2: Lần lượt duyệt trong danh sách cạnh đã sắp xếp theo thứ tự trọng số từ nhỏ đến lớn, chọn cạnh bổ sung vào tập T với điều kiện việc bổ sung này không tạo thành chu trình Bước 3: Tiếp tục thực hiện bước 2 cho đến khi T có n-1 cạnh thì dừng Thuật toán Prim: 8 Downloaded by ANH LE (bachvan14@gmail.com) lOMoARcPSD|39108650 Cước phí của chuyến đi 2.2.1.2 Lưu trữ và truy xuất dữ liệu: - Sử dụng mảng một chiều để lưu danh sách các điểm, danh sách các kết quả đường đi ngắn nhất và danh sách các khách hàng book chuyến - Mỗi hàng của ma trận khoảng cách trong đồ thị được lưu vào trong mảng distance của mỗi phần tử dot - Kết quả đường đi ngắn nhất từ điểm nguồn đến các điểm còn lại được lưu lần lượt vào mảng dijkstra Điểm nguồn được mặc định là phần tử đầu tiên của mảng dot, các điểm còn lại là điểm đích Vì vậy phần tử đầu tiên của mảng dijkstra luôn bằng 0 do khoảng cách từ đỉnh nguồn đến đỉnh nguồn là 0 Các kết quả trong mảng dijkstra được lưu theo chỉ số tương ứng của đỉnh đích trong mảng Dot Vd: Thông tin của điểm B được lưu trong mảng Dot ở phần tử thứ 2 thì kết quả đường đi ngắn nhất từ đỉnh 13 Downloaded by ANH LE (bachvan14@gmail.com) lOMoARcPSD|39108650 nguồn đến đỉnh B cũng được lưu ở phần tử thứ 2 trong mảng dijkstra - Thông tin của mỗi khách hàng book chuyến cũng được lưu trong mảng p theo thứ tự dữ liệu nhập vào 2.2.2 Giải thuật: 2.2.2.1 Thuật toán Dijkstra: - Bước 1: Khởi tạo (1) Tổng độ dài đường đi của phần tử đầu tiên trong mảng dijkstra là 0 và điểm kề trước nó là chính nó (2) Tất cả các phần tử của mảng 1 chiều visiteddot (mảng dùng để đánh dấu các điểm đã đi qua trên đồ thị, có 2 giá trị là 0 và -1, nếu phần tử ở vị trí thứ i có giá trị là -1 tức điểm ở vị trí đó đã được đi qua và ngược lại) (3) Bộ đếm k = n (n là số lượng điểm trong đồ thị) - Bước 2: Tìm khoảng cách từ điểm nguồn đến các điểm liền kề nó (1) Duyệt các phần tử trong mảng distance của điểm đầu tiên: + Nếu khoảng cách từ điểm đầu tiên đến điểm thứ i là khác 0, thì : Cập nhật kết quả đường đi ngắn nhất từ điểm đầu tiên đến phần tử thứ i trong mảng dijkstra là khoảng cách thứ i trong mảng distance Cập nhật điểm kề trước phần tử thứ i đó là điểm đầu tiên + Ngược lại, cập nhật kết quả đường đi ngắn nhất ở các vị trí đó là vô hạn 14 Downloaded by ANH LE (bachvan14@gmail.com) lOMoARcPSD|39108650 (2) Cập nhật giá trị phần tử đầu tiên của mảng visiteddot là -1 (3) Giảm giá trị k - Bước 3: Tìm min (1) Khởi tạo min bằng vô hạn, giá trị minindex=0 (2) Duyệt lần lượt các giá trị trong mảng dijkstra: So sánh các giá trị đường đi ngắn nhất tại các đỉnh chưa được đi qua và tìm ra giá trị nhỏ nhất gán cho min Gán minindex bằng vị trí của phần tử có giá trị min (3) Cập nhật lại giá trị của phần tử thứ minindex trong mảng visiteddot thành -1 (đánh dấu đã đi qua, hiện là đỉnh nguồn tạm thời) (4) Duyệt lại lần lượt các giá trị trong mảng dijkstra, cập nhật lại giá trị tổng đường đi ngắn nhất ở các đỉnh chưa được đi qua: Nếu nếu min cộng với khoảng cách từ đỉnh nguồn tạm thời đến đích thứ i nhỏ hơn kết quả đường đi ngắn nhất thứ i trong mảng dijkstra, thì : Cập nhật lại giá trị của phần tử thứ i trong mảng dijkstra thành giá trị min cộng với khoảng cách từ điểm nguồn tạm thời đến điểm đích thứ i Cập nhật điểm kề trước phần tử thứ i trong mảng dijkstra là điểm thứ minindex Ngược lại, không cập nhật (5) Giảm k (6) Lặp lại từ (1) cho đến khi k=0 15 Downloaded by ANH LE (bachvan14@gmail.com) lOMoARcPSD|39108650 2.2.2.2 Đổi đỉnh nguồn: ‐ Thuật toán Dijkstra như ở trên được mặc định đỉnh nguồn là điểm đầu tiên trong mảng dot Do vậy nếu muốn lặp đi lặp lại việc tìm đường từ điểm này đến điểm khác ta cần phải đổi đỉnh nguồn để có thể tiếp tục tìm đường ‐ Thực tế, mỗi hàng trong ma trận khoảng cách của đồ thị được lưu vào các mảng distance trong mỗi dot Vậy nên, việc đổi đỉnh nguồn không thể chỉ là di chuyển phần tử 16 Downloaded by ANH LE (bachvan14@gmail.com) lOMoARcPSD|39108650 thứ i trong mảng dot lên đầu mà còn là việc thay đổi giá trị của các hàng và cột trong trận khoảng cách của đồ thị ‐ Giải pháp để giải quyết vấn đề này là ghi ra một ma trận mới vào file txt và đọc lại nó để cập nhật ma trận mới Các bước của giải thuật như sau: Bước 1: Ghi file (1) Dòng đầu tiên là số lượng điểm trong đồ thị (2) N dòng tiếp theo là tên của các điểm, tên của điểm nguồn mới sẽ được ghi trên cùng (3) N dòng tiếp theo là ma trận khoảng cách của đồ thị, ưu tiên ghi các dòng và cột có index của điểm nguồn mới đầu tiên, sau đó đến các hàng và cột theo thứ tự từ bé đến lớn 17 Downloaded by ANH LE (bachvan14@gmail.com) lOMoARcPSD|39108650 Bước 2: Đọc file txt vứa ghi để cập nhật lại dữ liệu cho ma trận 18 Downloaded by ANH LE (bachvan14@gmail.com)