Tải bản đầy đủ (.pdf) (30 trang)

Mô phỏng thuật toán tìm kiếm đồ thị theo DFS và BFS và tìm đường đi ngắn nhất trên đồ thị có trọng số theo Dijkstra

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (1.02 MB, 30 trang )

Đồ án Java: “Mô phỏng thuật toán tìm kiếm đồ thị theo DFS và BFS và tìm đường đi
ngắn nhất trên đồ thị có trọng số theo Dijkstra”

LỜI CẢM ƠN
Ngày nay, việc ứng dụng công nghệ thông tin đã trở nên phổ biến trong hầu hết mọi
cơ quan, doanh nghiệp, trường học đặc biệt là việc áp dụng các giải pháp tin học trong
công tác quản lý.
Trong ít năm trở lại đây, với tốc độ phát triển như vũ bão, CNTT đang dần làm cho
cuộc sống của con người trở nên thú vị và đơn giản hơn. Vì vậy để bắt kịp với nhịp độ
phát triển của xã hội, những kiến thức học được trên giảng đường là vô cùng quan trọng
đối với mỗi Sinh viên chúng em.
Chúng em xin chân thành cảm ơn các thầy, cô bộ môn đã tận tình giảng dạy chúng
em trong suốt thời gian học tập vừa qua. Nhờ có sự chỉ dạy tận tình của các thầy, cô để
giúp chúng em hoàn thành đồ án này. Tuy đã có nhiều cố gắng nhưng trong quá trình làm
đề tài không thể tránh được những sai sót. Chúng em rất mong nhận được các ý kiến đóng
góp từ các thầy cô và bạn bè để chúng em rút kinh nghiệm thực hiện tốt hơn ở các đề tài
sau.
Chúng em xin chân thành cảm ơn thầy cô!

Đồ án Java: “Mô phỏng thuật toán tìm kiếm đồ thị theo DFS và BFS và tìm đường đi
ngắn nhất trên đồ thị có trọng số theo Dijkstra”

MỤC LỤC
CHƢƠNG 1: CƠ SỞ LÝ THUYẾT 1
1.1. Lý thuyết ngăn xếp (Stack) 1
1.2. Lý thuyết hàng đợi (Queue) 1
1.3. Thuật toán tìm kiếm theo chiều sâu ( DFS: Depth First Search ) 2
1.3.1. Ý tưởng thuật toán. 2
1.3.2. Phân tích thuật toán. 3
1.3.3. Ví dụ DFS 3
1.4. Thuật toán tìm kiếm theo chiều rộng (BFS: Breadth First Search) 4


1.4.1. Ý tưởng thuật toán. 4
1.4.2. Phân tích thuật toán. 4
1.4.3. Ví dụ BFS 5
1.5. Thuật toán tìm kiếm đường đi ngắn nhất (chi phí thấp nhất) trên đồ thị có trọng số
theo Dijkstra: 5
1.5.1. Ý tưởng của thuật toán Dijkstra: 5
1.5.2. Phân tích thuật toán: 6
1.5.3. Ví dụ Dijkstra : 6
1.6. Lý thuyết đồ họa trong Java: 8
1.6.1 Tìm tọa độ các đỉnh của đa giác đều n đỉnh 8
1.6.2. Thuật toán vẽ đường thẳng nối 2 điểm 9
CHƢƠNG 2: PHÂN TÍCH - THIẾT KẾ 10
2.1. Phân tích chương trình. 10
2.1.1. Yêu cầu: 10
2.1.2. Quy định: 10
2.1.2. Mục tiêu đặt ra: 10
2.2. Thiết kế 11
Đồ án Java: “Mô phỏng thuật toán tìm kiếm đồ thị theo DFS và BFS và tìm đường đi
ngắn nhất trên đồ thị có trọng số theo Dijkstra”

2.2.1. Kiến trúc chung 11
2.2.1.1. Chức năng khởi tạo: 12
2.2.1.2. Chức năng tìm kiếm đồ thị BFS và DFS: 12
2.2.1.3. Chức năng tìm kiếm đồ thị Dijkstra (đồ thị vô hướng): 12
2.2.1.4. Chức năng mô phỏng tìm kiếm đồ thị: 12
2.2.2. Cấu trúc dữ liệu 13
2.2.3. Thuật toán 13
2.2.3.1. Lưu đồ giải thuật BFS: 13
2.2.3.2. Lưu đồ giải thuật DFS: 15
2.2.3.3. Lưu đồ giải thuật Dijkstra: 16

2.2.3.4. Lưu đồ giải thuật Bresenham 17
2.2.4. Giao diện người dùng 18
2.3. Mục tiêu đã hoàn thành 19
2.4. Các thiếu sót của chương trình 21
2.5. Khả năng ứng dụng 21
2.6. Hướng phát tiển 21
KẾT LUẬN 22
TÀI LIỆU THAM KHẢO 24
NHẬN XÉT CỦA GIÁO VIÊN HƢỚNG DẪN 25


Đồ án Java: “Mô phỏng thuật toán tìm kiếm đồ thị theo DFS và BFS và tìm đường đi
ngắn nhất trên đồ thị có trọng số theo Dijkstra”

DANH MỤC HÌNH ẢNH
Hình 1. 1: Mô tả ngăn xếp 1
Hình 1. 2: Mô tả hàng đợi 2
Hình 1. 3: Đồ thị tìm kiếm DFS 4
Hình 1. 4: Ví dụ BFS 5
Hình 1. 5: Ví dụ thuật toán Dijkstra 7
Hình 1. 6: Minh họa thuật toán Bresenham 9
Hình 2. 1: Mô hình phân rã chức năng 11
Hình 2. 2: Lưu đồ giải thuật BFS 14
Hình 2. 3: Lưu đồ giải thuật DFS 15
Hình 2. 4: Lưu đồ giải thuật Dijkstra 16
Hình 2. 5: Lưu đồ thuật toán Bresenham 17
Hình 2. 6: Giao diện chính 20
Hình 2. 7: Giao diện mô phỏng thuật toán Dijkstra 20



Đồ án Java: “Mô phỏng thuật toán tìm kiếm đồ thị theo DFS và BFS và tìm đường đi
ngắn nhất trên đồ thị có trọng số theo Dijkstra”

LỜI MỞ ĐẦU
 Đề tài: “Mô phỏng thuật toán tìm kiếm đồ thị theo DFS và BFS và tìm đường đi
ngắn nhất trên đồ thị có trọng số theo Dijkstra”
Lý thuyết đồ thị là một lĩnh vực đã có từ lâu và có nhiều ứng dụng hiện đại. Những
tư tưởng cơ bản của lý thuyết đồ thị được đề xuất vào những năm đầu của thế kỷ 18 bởi
nhà toán học lỗi lạc người Thụy Sỹ Lenhard Eurler. Chính ông là người đã sử dụng đồ thị
để giải bài toán nổi tiếng về các cái cầu ở thành phố Konigsberg…
Có rất nhiều thuận toán trên đồ thị được xây dựng trên cơ sở duyệt tất cả các đỉnh
của đồ thị sao cho mỗi đỉnh của nó được viếng thăm đúng một lần. Vì vậy, việc xây dựng
những thuật toán cho phép duyệt một cách hệ thống tất cả các đỉnh của đồ thị là một vấn
đề quan trọng thu hút sự quan tâm nghiên cứu của nhiều người. Những thuật toán như vậy
được gọi chung là thuật toán tìm kiếm trên đồ thị. Trong đề tài này chúng em sẽ giới thiệu
hai thuật toán tìm kiếm cơ bản trên đồ thị không trọng số: Thuật toán tìm kiếm theo chiều
sâu (Depth Firt Search), Thuật toán tìm kiếm theo chiều rộng (Breadth First Search) và
thuật toán tìm đường đi ngắn nhất (chi phí thấp nhất) trên đồ thị có trọng số theo Dijkstra.
Để tiện cho việc học tập, tìm hiểu 3 thuật toán trên, nhóm chúng em đã viết một
chương trình sử dụng ngôn ngữ lập trình Java để mô phỏng lại 3 thuật toán BFS và DFS
và Dijkstra. Người dùng nhập dữ liệu vào chương trình qua giao diện cửa sổ và lựa chọn
chức năng của chương trình là tìm kiếm theo chiều rộng (BFS) hoặc tìm kiếm theo chiều
sâu (DFS) hoặc tìm đường đi ngắn nhất (chi phí thấp nhất) trên đồ thị có trọng số theo
Dijkstra. Sau khi có kết quả tìm kiếm, người dùng có thể lựa chọn mô phỏng lại quá trình
tìm kiếm bằng giao diện đồ họa. Chương trình sẽ vẽ một đồ thị dựa trên những dữ liệu
của người dùng và hiển thị quá trình tìm kiếm bằng hình ảnh động để người dùng có thể
thấy được quá trình tìm kiếm diễn ra theo từng bước như thế nào.
Cấu trúc của báo cáo đề tài gồm 4 chương:
- Chương 1: Cơ sở lý thuyết.
- Chương 2: Phân tích - Thiết kế.

- Kết luận.

Đồ án Java: “Mô phỏng thuật toán tìm kiếm đồ thị theo DFS và BFS và tìm đường đi
ngắn nhất trên đồ thị có trọng số theo Dijkstra”

Giảng viên hướng dẫn: Vũ Đức Minh Trang 1

CHƢƠNG 1: CƠ SỞ LÝ THUYẾT
1.1. Lý thuyết ngăn xếp (Stack)
Một ngăn xếp là một cấu trúc dữ liệu dạng thùng chứa (container) của các phần tử
(thường gọi là các nút (node)) và có hai phép toán cơ bản : push and pop. Push bổ sung
một phần tử vào đỉnh (top) của ngăn xếp, nghĩa là sau các phần tử đã có trong ngăn xếp.
Pop giải phóng và trả về phần tử đang đứng ở đỉnh của ngăn xếp. Trong stack, các đối
tượng có thể được thêm vào stack bất kỳ lúc nào nhưng chỉ có đối tượng thêm vào sau
cùng mới được phép lấy ra khỏi stack.
Ngoài ra, stack cũng hỗ trợ một số thao tác khác:
 isEmpty(): Kiểm tra xem stack có rỗng không.
 Top(): Trả về giá trị của phần tử nằm ở đầu stack mà không hủy nó khỏi stack.
Nếu stack rỗng thì lỗi sẽ xảy ra.


Hình 1. 1: Mô tả ngăn xếp
1.2. Lý thuyết hàng đợi (Queue)
Một hàng đợi là một cấu trúc dữ liệu dạng ống của các phần tử (thường gọi là các
nút (node)) và có hai phép toán cơ bản : enQueue and deQueue. enQueue bổ sung một
phần tử vào cuối của hàng đợi, nghĩa là sau các phần tử đã có trong hàng đợi. deQueue
giải phóng và trả về phần tử đang đứng ở đỉnh của hàng đợi. Trong Queue, các đối tượng
Đồ án Java: “Mô phỏng thuật toán tìm kiếm đồ thị theo DFS và BFS và tìm đường đi
ngắn nhất trên đồ thị có trọng số theo Dijkstra”


Giảng viên hướng dẫn: Vũ Đức Minh Trang 2

có thể được thêm vào Queue bất kỳ lúc nào nhưng chỉ có đối tượng thêm vào đầu tiên
mới được phép lấy ra khỏi stack.
Ngoài ra, stack cũng hỗ trợ một số thao tác khác:
 IsEmpty(): kiểm tra xem hàng đợi có rỗng không.
 Front(): trả về giá trị của phần tử nằm ở đầu hàng đợi mà không hủy nó. Nếu
hàng đợi rỗng thì lỗi sẽ xảy ra.

Hình 1. 2: Mô tả hàng đợi
1.3. Thuật toán tìm kiếm theo chiều sâu ( DFS: Depth First Search )
1.3.1. Ý tƣởng thuật toán.
Tìm kiếm theo chiều sâu (DFS) là một thuật toán duyệt và tìm kiếm trên một cây
hoặc một đồ thị. Thuật toán khởi đầu tạo gốc (hoặc chọn một đỉnh nào đó coi như gốc) và
phát triển xa nhất có thể theo mỗi nhánh.
Thông thường, DFS là một dạng tìm kiếm mù mà quá trình tìm kiếm được phát
triển tới đỉnh con đầu tiên của nút đang tìm kiếm cho tới khi gặp được đỉnh cần tìm hoặc
tới một nút không có con. Khi đó giải thuật quay lui về đỉnh vừa mới tìm kiếm ở bước
trước. Trong dạng không đệ quy, tất cả các đỉnh chờ được phát triển được bổ sung và một
ngăn xếp. Đỉnh nào được đưa vào ngăn xếp sau sẽ được phát triển trước (LIFO).
Đồ án Java: “Mô phỏng thuật toán tìm kiếm đồ thị theo DFS và BFS và tìm đường đi
ngắn nhất trên đồ thị có trọng số theo Dijkstra”

Giảng viên hướng dẫn: Vũ Đức Minh Trang 3

Ý tưởng chính của thuật toán có thể trình bày như sau:
Ta sẽ bắt đầu tìm kiếm từ một đỉnh v0 nào đó của đồ thị. Sau đó chọn u là một đỉnh
tuỳ ý kề với v0 và lặp lại quá trình đối với u. Ở bước tổng quát, giả sử ta đang xét đỉnh v.
Nếu như trong số các đỉnh kề với v tìm được đỉnh w là chưa được xét thì ta sẽ xét đỉnh
này (nó sẽ trở thành đã xét) và bắt đầu từ nó ta sẽ bắt đầu quá trình tìm kiếm còn nếu như

không còn đỉnh nào kề với v là chưa xét thì ta nói rằng đỉnh này đã duyệt xong và quay
trở lại tiếp tục tìm kiếm từ đỉnh mà trước đó ta đến được đỉnh v (nếu v=v0, thì kết thúc
tìm kiếm). Có thể nói nôm na là tìm kiếm theo chiều sâu bắt đầu từ đỉnh v được thực hiện
trên cơ sở tìm kiếm theo chiều sâu từ tất cả các đỉnh chưa xét kề với v.
1.3.2. Phân tích thuật toán.
 Các bước thực hiện thuật giải:
- Bước 1. Xuất phát từ đỉnh bắt đầu, chuyển đỉnh đó vào ngăn xếp.
- Bước 2. Xử lý đỉnh này và đánh dấu để không xử lý lần sau.
- Bước 3. Chuyển tất cả các đỉnh kề nó vào ngăn xếp, chọn một đỉnh để xử lý tiếp
theo.
- Bước 4. Quay lại bước 2 cho đến khi tìm được đường ngắn nhất hoặc không còn
đỉnh trong ngăn xếp.
1.3.3. Ví dụ DFS
 Ví dụ:
1. Bắt đầu từ đỉnh 1. Đưa các đỉnh kề với 1 vào danh sách: 2, 4, 5.
2. Chọn đỉnh 2 để xử lý. Đưa các đỉnh kề với đỉnh 2 vào danh sách: 3, 5.
3. Chọn đỉnh 3 để xử lý. Đưa các đỉnh kề với đỉnh 3 vào danh sách: 5, 6.
4. Chọn định 5 để xử lý. Đưa các đỉnh kề với đỉnh 5 vào danh sách: 4
5. Chọn đỉnh 4 để xử lý. Không có đỉnh nào kề với đỉnh 4.
6. Chọn đỉnh 6 để xử lý. Không có đỉnh nào kề với đỉnh 6.
7. Tất các đỉnh đã được duyệt.
8. Kết quả cuối cùng thứ tự: 1 2 3 5 4 6
 Đồ thị:
Đồ án Java: “Mô phỏng thuật toán tìm kiếm đồ thị theo DFS và BFS và tìm đường đi
ngắn nhất trên đồ thị có trọng số theo Dijkstra”

Giảng viên hướng dẫn: Vũ Đức Minh Trang 4


Hình 1. 3: Đồ thị tìm kiếm DFS

1.4. Thuật toán tìm kiếm theo chiều rộng (BFS: Breadth First Search)
1.4.1. Ý tƣởng thuật toán.
Trong lý thuyết đồ thị, tìm kiếm theo chiều rộng (BFS) là một thuật toán duyệt hoặc
tìm kiếm trên một cây hoặc một đồ thị. Thuật toán khởi đầu tại đỉnh gốc (hoặc chọn một
đỉnh nào đó coi như gốc) và duyệt tất cả các đỉnh lân cận. Sau đó, lần lượt đối với các
đỉnh lân cận, nó kiểm tra các đỉnh con của đỉnh đó mà chưa đi qua. Khi đã kiểm tra một
đỉnh, đỉnh đó sẽ được đánh dấu đã đi qua. Quá trình đó lặp đi lặp lại cho đến khi tìm được
đường đi ngắn nhất.
Để ý rằng trong thuật toán tìm kiếm theo chiều sâu đỉnh được thăm càng muộn sẽ
càng sớm trở thành đã duyệt xong. Điều đó là hệ quả tất yếu của việc các đỉnh được thăm
sẽ được kết nạp vào trong ngăn xếp (STACK). Tìm kiếm theo chiều rộng trên đồ thị, nếu
nói một cách ngắn gọn, được xây dựng trên cơ sở thay thế ngăn xếp (STACK) bởi hàng
đợi (QUEUE). Với sự cải biên như vậy, đỉnh được thăm càng sớm sẽ càng sớm trở thành
đã duyệt xong (tức là càng sớm dời khỏi hàng đợi). Một đỉnh sẽ trở thành đã duyệt xong
ngay sau khi ta xét xong tất cả các đỉnh kề (chưa được thăm) với nó
1.4.2. Phân tích thuật toán.
 Bước 1: Khởi tạo:
- Các đỉnh đều ở trạng thái chưa đánh dấu, ngoại trừ đỉnh xuất phát S là đã đánh dấu
duyệt theo thứ tự ưu tiên chiều rộng
 Bước 2: Lặp các bước sau đến khi hàng đợi rỗng:
- Lấy u khỏi hàng đợi, thông báo thăm u (Bắt đầu việc duyệt đỉnh u) Xét tất cả
những đỉnh v kề với u mà chưa được đánh dấu, với mỗi đỉnh v đó:
- Đánh dấu v.
- Ghi nhận vết đường đi từ u tới v (Có thể làm chung với việc đánh dấu)
- Đẩy v vào hàng đợi (v sẽ chờ được duyệt tại những bước sau)
 Bước 3: Truy vết tìm đường đi.
Đồ án Java: “Mô phỏng thuật toán tìm kiếm đồ thị theo DFS và BFS và tìm đường đi
ngắn nhất trên đồ thị có trọng số theo Dijkstra”

Giảng viên hướng dẫn: Vũ Đức Minh Trang 5


1.4.3. Ví dụ BFS
Ví dụ: Xét đồ thị dưới đây, Đỉnh xuất phát S = 1.

Hình 1. 4: Ví dụ BFS

Hàng
đợi
Đỉnh u ( lấy ra từ
hàng đợi)
Hàng đợi (sau
khi lấy u ra)
Các đỉnh v kề u
mà chưa lên lịch
Hàng đợi sau khi
đẩy những đỉnh v
vào
(1)
1


2,3
(2,3)
(2,3)
2
(3)
4
(3,4)
(3,4)
3

(4)
5
(4,5)
(4,5)
4
(5)
6
(5,6)
(5,6)
5
(6)
Không có
(6)
(6)
6


Không có



Để ý thứ tự các phần tử lấy ra khỏi hàng đợi, ta thấy trước hết là 1; sau đó đến 2, 3;
rồi mới tới 4, 5; cuối cùng là 6. Rõ ràng là đỉnh gần S hơn sẽ được duyệt trước. Và như
vậy, ta có nhận xét: nếu kết Các thuật toán trên đồ thị hợp lưu vết tìm đường đi thì đường
đi từ S tới F sẽ là đường đi ngắn nhất (theo nghĩa qua ít cạnh nhất)
1.5. Thuật toán tìm kiếm đƣờng đi ngắn nhất (chi phí thấp nhất) trên đồ thị có trọng
số theo Dijkstra:
1.5.1. Ý tƣởng của thuật toán Dijkstra:
Có rất nhiều giải thuật đã được phát triển để giải bài toán tìm đường đi ngắn nhất
giữa một cặp đỉnh, trong khuôn khổ bài viết này tôi chỉ xin giới thiệu giải thuật Dijkstra.

Giải thuật Dijkstra là một giải thuật để giải bài toán đường đi ngắn nhất nguồn đơn trên
Đồ án Java: “Mô phỏng thuật toán tìm kiếm đồ thị theo DFS và BFS và tìm đường đi
ngắn nhất trên đồ thị có trọng số theo Dijkstra”

Giảng viên hướng dẫn: Vũ Đức Minh Trang 6

một đồ thị có trọng số cạnh mà tất cả các trọng số đều không âm. Nó xác định đường đi
ngắn nhất giữa hai đỉnh cho trước, từ đỉnh a đến đỉnh b.
Ý tưởng xuất phát từ việc gán nhãn cho các đỉnh. Nhãn được gán theo cách là đường
đi ngắn nhất từ đỉnh a đến đỉnh đó. Đến khi nào đỉnh b là đỉnh được chọn tức là đường đi
từ a tới b là ngắn nhất, ta truy vết để tìm đường đi ngắn nhất (chi phí thấp nhất).
1.5.2. Phân tích thuật toán:
Ở mỗi đỉnh v, giải thuật Dijkstra xác định 3 thông tin: k
v
, d
v
và p
v
.
k
v
: mang giá trị boolean xác định trạng thái được chọn của đỉnh v.
Ban đầu ta khởi tạo tất cả các đỉnh v chưa được chọn, nghĩa là:
k
v
= false,

v

V.

d
v
: là chiều dài đường đi mà ta tìm thấy cho đến thời điểm đang xét từ a đến v.
Khởi tạo, d
v
=

, v  V \{a}, d
a
= 0.
p
v
: là đỉnh trước của đỉnh v trên đường đi ngắn nhất từ a đến b. Đường đi ngắn nhất từ
a đến b có dạng {a, ,p
v
,v, ,b}. Khởi tạo, p
v
= null, v V.
Sau đây là các bước của giải thuật Dijkstra
 Bƣớc 1. Khởi tạo: Đặt k
v
:= false v  V; d
v
:=

,v  V \ {a}, d
a
:=0.
 Bƣớc 2. Chọn v  V sao cho k
v

= false và d
v
= min {d
t
/ t V, k
t
= false}
Nếu d
v
=  thì kết thúc, không tồn tại đường đi từ a đến b.
 Bƣớc 3. Đánh dấu đỉnh v, k
v:
= true.
 Bƣớc 4. Nếu v = b thì kết thúc và d
b
là độ dài đường đi ngắn nhất từ a đến b.
Ngược lại nếu v

b sang Bƣớc 5.
 Bƣớc 5. Với mỗi đỉnh v kề với u mà k
v
= false, kiểm tra
Nếu d
v
> d
u
+ w(u,v) thì d
v
:= d
u

+ w(u,v)
Ghi nhớ đỉnh v: p
u
:= v.Quay lại Bƣớc 2.
1.5.3. Ví dụ Dijkstra :
Ví dụ:
Đồ án Java: “Mô phỏng thuật toán tìm kiếm đồ thị theo DFS và BFS và tìm đường đi
ngắn nhất trên đồ thị có trọng số theo Dijkstra”

Giảng viên hướng dẫn: Vũ Đức Minh Trang 7

Ta có đồ thị nhƣ sau: tìm đường đi ngắn nhất từ a tới f
b 5 d
4 6
a 1 f
8
2 3
c 10 e
Hình 1. 5: Ví dụ thuật toán Dijkstra
- Gán nhãn đỉnh a là 0, đánh dấu a được xét; nhãn của các đỉnh còn lại là vô cùng, đánh
dấu là chưa được xét.
- Gán lại nhãn của các đỉnh kề đỉnh đang xét (đỉnh a) mà chưa được chọn với điều kiện
nhãn mới có giá trị nhỏ hơn nhãn cũ. (nhãn mới = nhãn của đỉnh chọn + trọng số)
- Tìm đỉnh có nhãn nhỏ nhất mà chưa được chọn, đánh dấu là được xét. Thực hiện lại cho
đến khi đỉnh cuồi (đỉnh f) là đỉnh được chọn.
Ta lập được bảng như sau:
Bảng chạy thô
V
T
a

b
c
d
e
f


0










A
a
*
4
2*






C

ac

3*
*
10
12


B
acb

*

8*
12


D
acbd



*
12*
14
E
acbde





*
14
F
acbdef





*
Vậy độ dài từ af là 14.
Đồ án Java: “Mô phỏng thuật toán tìm kiếm đồ thị theo DFS và BFS và tìm đường đi
ngắn nhất trên đồ thị có trọng số theo Dijkstra”

Giảng viên hướng dẫn: Vũ Đức Minh Trang 8

1.6. Lý thuyết đồ họa trong Java:
1.6.1 Tìm tọa độ các đỉnh của đa giác đều n đỉnh
class Point{
public int x,y;
Point(int xx,int yy){
x=xx;
y=yy;
}
}
Point Tips[] = new Point[n];
Point CenterPoint = new Point( 300 , 300);
int Radius = BFSFrame.WIDTH/2-50;
float Angle = 2f * (float)Math.PI / (float)n;

for (int i = 0; i < n; i++)
{
Tips[i] = new Point(0,0);
Tips[i].x = (int)((float)CenterPoint.x + 4*(Radius * (float)Math.sin(i *
Angle)));
Tips[i].y = (int)((float)CenterPoint.y - 4*(Radius * (float)Math.cos(i *
Angle)));
}
Khởi tạo mảng Point[n] gồm n đỉnh.
Xác định điểm trung tâm CenterPoint. Do trong phần mềm, chúng ta cố định kích
thước của frame là 600x600 nên điểm trung tâm là Point(300,300);
Radius : bán kính của đường tròn ngoại tiếp đa giác đều tâm là CenterPoint. Trong
bài này chúng ta chọn là 250.
Angle : là góc quay sau của mỗi đỉnh so với đỉnh đầu tiên (tính theo rad). (với 2f
tương đương 2.0). => góc quay bằng 2pi/n.

Đồ án Java: “Mô phỏng thuật toán tìm kiếm đồ thị theo DFS và BFS và tìm đường đi
ngắn nhất trên đồ thị có trọng số theo Dijkstra”

Giảng viên hướng dẫn: Vũ Đức Minh Trang 9

1.6.2. Thuật toán vẽ đƣờng thẳng nối 2 điểm
Thuật toán Bresenham
Với thuật toán DDA, việc quyết định chọn y
i+1
là y
i
hay y
i
+1, dựa vào phương trình

của đoạn thẳng y = mx + b. Còn với thuật toán Bresenham đưa ra cách chọn y
i+1
là y-
i
hay y
i
+1 theo một hướng khác sao cho có thể tối ưu hóa về mặt tốc độ so với thuật toán
DDA. Vấn đề mấu chốt ở đây là làm thế nào để hạn chế tối đa các phép toán trên số thực
trong thuật toán.

Hình 1. 6: Minh họa thuật toán Bresenham

Đồ án Java: “Mô phỏng thuật toán tìm kiếm đồ thị theo DFS và BFS và tìm đường đi
ngắn nhất trên đồ thị có trọng số theo Dijkstra”

Giảng viên hướng dẫn: Vũ Đức Minh Trang 10

CHƢƠNG 2: PHÂN TÍCH - THIẾT KẾ
2.1. Phân tích chƣơng trình.
2.1.1. Yêu cầu:
Viết một chương trình sử dụng ngôn ngữ lập trình Java để mô phỏng lại 3 thuật toán
BFS và DFS và Dijkstra.
Người dùng có thể nhập dữ liệu vào chương trình qua giao diện cửa sổ bao gồm
thông tin về số đỉnh, các cạnh (đường đi) giữa các đỉnh và trọng số (nếu là Dijkstra),
thông tin về đỉnh đầu, đỉnh cuối để tìm đường đi.
Xây dựng 3 chức năng chính của chương trình là tìm kiếm theo chiều rộng (BFS)
hoặc tìm kiếm theo chiều sâu (DFS) hoặc tìm đường đi ngắn nhất (chi phí thấp nhất) trên
đồ thị có trọng số theo Dijkstra với dữ liệu là ma trận đỉnh và liên kết nhập từ trên.
Sau khi có kết quả tìm kiếm, người dùng có thể lựa chọn mô phỏng lại quá trình tìm
kiếm bằng giao diện đồ họa. Chương trình sẽ vẽ một đồ thị dựa trên những dữ liệu của

người dùng và hiển thị quá trình tìm kiếm bằng hình ảnh động để người dùng có thể thấy
được quá trình tìm kiếm diễn ra theo từng bước như thế nào.
2.1.2. Quy định:
Số lượng đỉnh 2<= n <=20 để tránh tràn bộ nhớ.
Với dijkstra, Yêu cầu dữ liệu nhập vào là trọng số đường đi giữa các đỉnh phải là số
dương, Nếu giá trị = 0 tức là không có đường đi nối giữa 2 đỉnh.
Với BFS và DFS, giá trị của ma trận liên lạc =0 tức là không có đường đi, = 1 tức là
có đường đi nối giữa 2 đỉnh.
Giá trị của đỉnh khởi đầu và đỉnh kết thúc phải là số và < n (tránh xét đỉnh không tồn
tại).
Thời gian hiển thị của mô phỏng không quá nhanh cũng không quá chậm.
2.1.2. Mục tiêu đặt ra:
 Yêu cầu về thời gian:
Tốc độ xử lý của chương trình phụ thuộc vào độ phức tạp của thuật toán được sử
dụng. Cần tối ưu thuật toán về mặt thời gian và không gian lưu trữ.
Đồ án Java: “Mô phỏng thuật toán tìm kiếm đồ thị theo DFS và BFS và tìm đường đi
ngắn nhất trên đồ thị có trọng số theo Dijkstra”

Giảng viên hướng dẫn: Vũ Đức Minh Trang 11

Do mô phỏng có xử lý delay time (thời gian chờ) khoảng mỗi lần là 1s để người
dùng tiện theo dõi quá trình xử lý.
 Yêu cầu về độ ổn định:
Cái thiện được tốc độ xử lý của thuật toán nhưng yêu cầu phải giữ được độ ổn định
của thuật toán.
Đảm bảo tính chính xác của dữ liệu đầu vào (có cơ chế bẫy lỗi).
 Yêu cầu Hệ thống:
Ngoài những lỗi của dữ liệu đầu vào, còn có những lỗi hệ thống, lỗi xử lý hay lặp vô
hạn, …. Yêu cầu bẫy lỗi, xét các khả năng có thể say ra.
 Yêu cầu bảo trì, nâng cấp:

Code có thể kế thừa để phát triển với những thuật toán khác về đồ thị.
Chú thích rõ ràng, có thể dễ dàng check lỗi nêu có lỗi phát sinh.
2.2. Thiết kế
2.2.1. Kiến trúc chung

Hình 2. 1: Mô hình phân rã chức năng

Đồ án Java: “Mô phỏng thuật toán tìm kiếm đồ thị theo DFS và BFS và tìm đường đi
ngắn nhất trên đồ thị có trọng số theo Dijkstra”

Giảng viên hướng dẫn: Vũ Đức Minh Trang 12

2.2.1.1. Chức năng khởi tạo:
Khởi tạo giá trị n – số đỉnh của đồ thị, chọn chức năng muốn xử lý (BFS/DFS : đồ
thị vô hướng không có trọng số; Dijkstra : đồ thị vô hướng có trọng số).
Nếu là BFS và DFS thì Xây dựng ma trận nxn MatrixButton.
Nếu là Dijkstra thì xây dựng ma trận nxn MatrixTextField.
2.2.1.2. Chức năng tìm kiếm đồ thị BFS và DFS:
Xây dựng ma trận MatrixButton nxn là các button, lắng nghe sự kiện Click để thay
đổi value giữa 0 và 1 (0 là không có đường đi, 1 là có đường đi).
Chức năng tìm kiếm đồ thị BFS và DFS sẽ trích rút từ MatrixButton để lấy ma trận
liên lạc (đồ thị đỉnh). Sau đó là gọi hàm xử lý để tìm đường đi từ đỉnh bắt đầu đến đỉnh
kết thúc.
Đường đi tương ứng với bài toán sẽ được hiển thị.
Kích hoạt chức năng Mô phỏng với BFS và DFS.
2.2.1.3. Chức năng tìm kiếm đồ thị Dijkstra (đồ thị vô hƣớng):
Xây dựng ma trận MatrixTextField nxn là các JTextField, lắng nghe sự kiện
TextChange để thay đổi giá trị tương ứng(0 là không có đường đi, >0 là trọng số của
đường đi giữa 2 đỉnh).
Chức năng tìm kiếm đồ thị DIJKSTRA sẽ trích rút từ MatrixTextField để lấy ma

trận liên lạc (đồ thị đỉnh). Sau đó là gọi hàm xử lý để tìm đường đi từ đỉnh bắt đầu đến
đỉnh kết thúc.
Đường đi và chi phí nhỏ nhất tương ứng với bài toán sẽ được hiển thị.
Kích hoạt chức năng Mô phỏng Dijkstra.
2.2.1.4. Chức năng mô phỏng tìm kiếm đồ thị:
Sau khi đã thực hiện xong chức năng tìm kiếm với BFS, DFS hoặc Dijkstra, người
dùng có thể chọn chức năng mô phỏng. Chức năng mô phỏng sẽ vẽ đồ thị dựa trên những
dữ liệu đầu vào, sau đó thực hiện hiển thị các bước xây dựng của thuật toán để mô phỏng
thuật toán.

Đồ án Java: “Mô phỏng thuật toán tìm kiếm đồ thị theo DFS và BFS và tìm đường đi
ngắn nhất trên đồ thị có trọng số theo Dijkstra”

Giảng viên hướng dẫn: Vũ Đức Minh Trang 13

2.2.2. Cấu trúc dữ liệu
 Class MatrixButton extends Button{
Int value;
Int x,y;
}
Dữ liệu có cấu trúc dạng button, lắng nghe sự kiện Click để thay đổi giá trị, xây
dựng ma trận đồ thị liên lạc giữa các đỉnh.
 Class MatrixTextField extends JTextField{
Int value;
Int x,y;
}
Dữ liệu có cấu trúc dạng JtextField lắng nghe sự kiện TextChange của
DocumentListener với mục đích thay đổi giá trị tương ứng, xây dựng ma trận đồ thị liên
lạc giữa các đỉnh.
2.2.3. Thuật toán

2.2.3.1. Lƣu đồ giải thuật BFS:
Đồ án Java: “Mô phỏng thuật toán tìm kiếm đồ thị theo DFS và BFS và tìm đường đi
ngắn nhất trên đồ thị có trọng số theo Dijkstra”

Giảng viên hướng dẫn: Vũ Đức Minh Trang 14


Hình 2. 2: Lưu đồ giải thuật BFS
Đồ án Java: “Mô phỏng thuật toán tìm kiếm đồ thị theo DFS và BFS và tìm đường đi
ngắn nhất trên đồ thị có trọng số theo Dijkstra”

Giảng viên hướng dẫn: Vũ Đức Minh Trang 15

2.2.3.2. Lƣu đồ giải thuật DFS:

Hình 2. 3: Lưu đồ giải thuật DFS
Đồ án Java: “Mô phỏng thuật toán tìm kiếm đồ thị theo DFS và BFS và tìm đường đi
ngắn nhất trên đồ thị có trọng số theo Dijkstra”

Giảng viên hướng dẫn: Vũ Đức Minh Trang 16

2.2.3.3. Lƣu đồ giải thuật Dijkstra:


Hình 2. 4: Lưu đồ giải thuật Dijkstra


Begin
n, C = (c
ij

), a, b
d(a) = 0
d(v) = v a
K(i) = False i n

v K
Chọn v K sao cho d[v] đạt min
K = K \ {v}
V K & kề
d(u) = min(d(u), d(v) + w(v,u))
End
S
Đ
S
Đ
d(b)
Đồ án Java: “Mô phỏng thuật toán tìm kiếm đồ thị theo DFS và BFS và tìm đường đi
ngắn nhất trên đồ thị có trọng số theo Dijkstra”

Giảng viên hướng dẫn: Vũ Đức Minh Trang 17

2.2.3.4. Lƣu đồ giải thuật Bresenham

Hình 2. 5: Lưu đồ thuật toán Bresenham

Đồ án Java: “Mô phỏng thuật toán tìm kiếm đồ thị theo DFS và BFS và tìm đường đi
ngắn nhất trên đồ thị có trọng số theo Dijkstra”

Giảng viên hướng dẫn: Vũ Đức Minh Trang 18


2.2.4. Giao diện ngƣời dùng
 Frame khởi tạo
Gồm 1 JtextField để nhập số đỉnh, 1 button và 1 CheckBox (Dijkstra)
Button lắng nghe sự kiện click. Nếu click button, sẽ kiểm tra giá trị nhập ở
JtextField có đúng không, gửi phản hồi. Nếu đúng, khởi tạo n = số đỉnh.
Sự kiện click thành công, kiểm tra CheckBox.
 CheckBox.isSelect() == true (Xử lý Dijkstra)
Khởi tạo ma trận MatrixTextField[n][n].
Add vào frame bao gồm 2 JtextField khởi đầu và kết thúc (lấy giá trị điểm khởi đầu
và điểm kết thúc).
Add vào frame ma trận MatrixTextField, lắng nghe sự kiện textChange để update lại
giá trị cho mỗi MatrixTextField[i][j];
Add thêm vào frame 2 JTextField Kết quả và Chi phí để hiển thị đường đi có chi
phí ít nhất và chi phí tương ứng.
Cuối cùng là add vào 2 Jbutton Dijkstra và Mô phỏng Dijkstra, lắng nghe sự kiện
click. Dijkstra click => thực hiện thao tác xử lý Dijkstra, hiển thị ở JTextField Kết quả và
Chi phí, Add sự kiện lắng nghe cho JButton Mô phỏng để mô phỏng hoạt động.
 CheckBox.isSelect() == false (Xử lý BFS và DFS)
Khởi tạo ma trận MatrixButton[n][n].
Add vào frame bao gồm 2 JtextField khởi đầu và kết thúc (lấy giá trị điểm khởi đầu
và điểm kết thúc).
Add vào frame ma trận MatrixButton, lắng nghe sự kiện Click để update lại giá trị
cho mỗi MatrixButton[i][j];
Add thêm vào frame 2 JTextField Kết quả BFS và Kết quả DFS để hiển thị đường
đi với các phương pháp tương ứng.
Cuối cùng là add vào 4 Jbutton BFS và Mô phỏng BFS, Jbutton DFS và Mô phỏng
DFS lắng nghe sự kiện click. Khi button xử lý được click => thực hiện thao tác xử lý BFS
Đồ án Java: “Mô phỏng thuật toán tìm kiếm đồ thị theo DFS và BFS và tìm đường đi
ngắn nhất trên đồ thị có trọng số theo Dijkstra”


Giảng viên hướng dẫn: Vũ Đức Minh Trang 19

hoặc DFS, hiển thị ở JTextField Kết quả, Add sự kiện lắng nghe cho JButton Mô phỏng
để mô phỏng hoạt động.
 Frame Mô phỏng:
Sau khi đã thực hiện xong chức năng tìm kiếm với BFS, DFS hoặc Dijkstra, người
dùng có thể chọn chức năng mô phỏng. Chức năng mô phỏng sẽ vẽ đồ thị dựa trên những
dữ liệu đầu vào, sau đó thực hiện hiển thị các bước xây dựng của thuật toán để mô phỏng
thuật toán.
Chức năng mô phỏng bằng đồ họa, đầu tiên sẽ tính tọa độ các đỉnh của n giác đều
(hoặc đặt ở những vị trí hợp lý). Kế tiếp là đọc ma trận liên lạc để vẽ đồ thị liên lạc tương
ứng. Vẽ thêm chú thích các loại đường
o Nét đen : liên kết giữa các đỉnh (con đường có thể đi).
o Nét xanh lá : hướng phát triển của hệ thống.
o Nét đỏ : truy vết đường đi tương ứng.
Tạo hàm delay time để hiển thị để người dùng có thể theo dõi chi tiết các bước xử lý
của hệ thống.
Thay nét vẽ bằng màu xanh để vẽ các đường là các bước phát triển tương ứng (vẽ đè
lên đường cũ).
Delay time để theo dõi.
Thay nét vẽ đỏ, thực hiện thao tác truy vết, vẽ các đường thẳng lên đường truy vết
(vẽ đè lên đường cũ).
Quá trình mô phỏng sẽ được thực hiện 2 lần để người dùng theo dõi tốt hơn. Trong
quá trình xử lý mô phỏng, không thể thực hiện một thao tác nào khác. Cần phải đợi thao
tác mô phỏng trước kết thúc.
2.3. Mục tiêu đã hoàn thành
Chương trình đã hoàn thành được các chức năng với các mục tiêu đề ra như việc
tính toán theo thuật toán và thời gian thực hiện của từng bộ test.
Chương trình có phần vẽ đồ thị giúp cho việc minh họa sinh động và dễ hiểu hơn.
a. Giao diện chính

Đồ án Java: “Mô phỏng thuật toán tìm kiếm đồ thị theo DFS và BFS và tìm đường đi
ngắn nhất trên đồ thị có trọng số theo Dijkstra”

Giảng viên hướng dẫn: Vũ Đức Minh Trang 20


Hình 2. 6: Giao diện chính
b. Giao diện mô phỏng thuật toán Dijkstra

Hình 2. 7: Giao diện mô phỏng thuật toán Dijkstra

×