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

Mô phỏng một số thuật toán trên đồ thị

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 (3.77 MB, 84 trang )

ĐẠI HỌC QUỐC GIA HÀ NỘI
TRƯỜNG ĐẠI HỌC CÔNG NGHỆ

NGUYỄN THỊ CHINH

MƠ PHỎNG MỘT SỐ THUẬT TỐN TRÊN ĐỒ THỊ

LUẬN VĂN THẠC SĨ

Hà Nội - 2011


ĐẠI HỌC QUỐC GIA HÀ NỘI
TRƯỜNG ĐẠI HỌC CÔNG NGHỆ

NGUYỄN THỊ CHINH

MƠ PHỎNG MỘT SỐ THUẬT TỐN TRÊN ĐỒ THỊ

Ngành: Công nghệ thông tin
Chuyên ngành: Hệ thống thông tin
Mã số: 60 48 05

LUẬN VĂN THẠC SĨ

NGƯỜI HƯỚNG DẪN KHOA HỌC:

TS. HỒ CẨM HÀ

Hà Nội - 2011



LỜI CAM ĐOAN
Tôi xin cam đoan, kết quả luận văn hồn tồn là kết quả của tự bản thân
tơi tìm hiểu, nghiên cứu dưới sự hướng dẫn của TS. Hồ Cẩm Hà.
Các tài liệu tham khảo được trích dẫn và chú thích đầy đủ.

Học viên

Nguyễn Thị Chinh

Trang 3


LỜI CẢM ƠN
Trước hết, tôi muốn gửi lời cảm đến các Thầy, Cô trong khoa Công nghệ
thông tin- Trường Đại học Công nghệ - Đại học Quốc gia Hà nội đã truyền đạt
các kiến thức quý báu cho tôi trong suốt thời gian học tập tại trường. Đặc biệt,
tôi xin gửi lời cảm ơn sâu sắc tới cô giáo hướng dẫn TS Hồ Cẩm Hà, người đã
tận tình chỉ bảo và hướng dẫn về mặt chuyên môn cho tôi trong suốt q trình
thực hiện luận văn này.
Cũng qua đây, tơi xin gửi lời cảm ơn đến Ban Giám hiệu trường THPT
Chuyên Đại học Sư phạm Hà Nội, nơi tôi đang công tác đã tạo mọi điều kiện
thuận lợi cho tôi trong thời gian học tập cũng như trong suốt quá trình thực
hiện luận văn tốt nghiệp.
Cuối cùng, tơi xin cảm ơn gia đình, bạn bè, đồng nghiệp đã ln ủng hộ,
động viên tôi rất nhiều để tôi yên tâm nghiên cứu và hồn thành luận văn. Trong
suốt q trình làm luận văn, bản thân tôi đã cố gắng tập trung tìm hiểu, nghiên
cứu và tham khảo thêm nhiều tài liệu liên quan. Tuy nhiên, do thời gian hạn chế
và bản thân cịn chưa có nhiều kinh nghiệm trong nghiên cứu khoa học, chắc
chắn bản luận văn vẫn còn nhiều thiếu sót. Tơi rất mong được nhận sự chỉ bảo

của các Thầy Cơ giáo và các góp ý của bạn bè, đồng nghiệp để luận văn được
hoàn thiện hơn.
Hà Nội, ngày 12 tháng 06 năm 2011
Nguyễn Thị Chinh

Trang 4


MỤC LỤC
LỜI CẢM ƠN ...................................................................................................... 4
LỜI NÓI ĐẦU....................................................................................................... 8
Chương 1 MỘT SỐ KIẾN THỨC CƠ BẢN VỀ THUẬT TOÁN ..................... 10
1. Khái niệm bài toán Tin học.......................................................................... 10
2. Khái niệm thuật tốn .................................................................................... 10
3. Các tính chất của thuật tốn ......................................................................... 11
4. Độ phức tạp và xác định độ phức tạp của thuật tốn ................................... 12
5. Chi phí thực hiện thuật tốn ......................................................................... 16
6. Ba bài tốn trên mơ hình đồ thị được đưa vào giảng dạy trong trường Trung
học Phổ thông Chuyên ..................................................................................... 16
6.1. Một số khái niệm cơ bản về đồ thị ........................................................ 16
6.1.1. Khái niệm đồ thị (Graph) ................................................................ 16
6.1.2. Các khái niệm cơ bản ...................................................................... 17
6.2. Bài tốn tìm kiếm trên đồ thị ................................................................. 19
6.2.1. Phát biểu bài tốn ............................................................................ 19
6.2.2. Giới thiệu thuật tốn tìm kiếm DFS và BFS ................................... 20
6.2.3. Độ phức tạp tính toán của thuật toán DFS và BFS ......................... 22
6.3. Bài tốn tìm đường đi ngắn nhất trên đồ thị có trọng số ....................... 22
6.3.1. Phát biểu bài toán ............................................................................ 22
6.3.2. Giới thiệu thuật toán Ford - Bellman .............................................. 23
6.2.3. Giới thiệu thuật toán thuật toán Dijkstra ........................................ 24

6.3.4. Độ phức tạp ..................................................................................... 26
6.4. Các thuật tốn tìm kiếm trên cây khung ................................................ 26
6.4.1. Bài toán cây khung.......................................................................... 26
6.4.2. Giới thiệu thuật toán Prim............................................................... 27
6.4.3. Giới thiệu thuật toán Kruskal .......................................................... 28
6.4.5. Độ phức tạp .................................................................................... 29

Trang 5


6.5. Bài tốn tìm chu trình Hamilton qua tất cả các đỉnh của đồ thị ............ 30
6.5.1. Phát biểu bài tốn ............................................................................ 30
6.5.2. Giới thiệu thuật tốn tìm chu trình Hamilton: ................................ 31
Chương 2 MƠ PHỎNG THUẬT TỐN ............................................................ 32
1. Khái niệm và chức năng của mô phỏng....................................................... 32
2. Lịch sử của mơ phỏng thuật tốn ................................................................. 33
3. Hiệu quả của mơ phỏng thuật tốn trong giảng dạy .................................... 35
4. Một số u cầu đối với mơ phỏng thuật tốn .............................................. 39
4.1. Mơ phỏng đúng theo thuật tốn............................................................. 39
4.2. Cho phép thực hiện theo từng bước ...................................................... 39
4.3. Mô phỏng thuật tốn phải có tính động................................................. 39
4.4. Có thể thực thi với mọi bộ dữ liệu đầu vào ........................................... 41
4.5. Có sự phân cấp người học ..................................................................... 41
5. Quy trình mơ phỏng thuật tốn .................................................................... 41
5.1. Nghiên cứu và phân tích giải thuật ........................................................ 41
5.2. Mơ phỏng dữ liệu vào và kết quả đầu ra ............................................... 42
5.3. Chia thuật toán thành nhiều bước nhỏ rồi mô phỏng theo từng bước .. 43
5.4. Tổng hợp mô phỏng theo các bước ....................................................... 45
5.5. Sơ đồ cấu trúc chung của hệ thống mô phỏng ...................................... 45
6. Đề xuất lựa chọn công cụ để phát triển chương trình mơ phỏng thuật tốn 46

6.1. Một số hệ thống mơ phỏng thuật tốn chung ........................................ 47
6.2. Sử dụng cơng cụ mơ phỏng thuật tốn riêng biệt.................................. 50
6.3. Xây dựng hệ thống từ đầu ..................................................................... 51
Chương 3 PHÂN TÍCH THIẾT KẾ HỆ THỐNG MƠ PHỎNG MỘT SỐ
THUẬT TỐN TRÊN ĐỒ THỊ ......................................................................... 52
1. Mục đích ...................................................................................................... 52
2. Những yêu cầu thực tế ................................................................................. 52
3. Đề xuất cho hệ thống mới ............................................................................ 53
4. Thiết kế hệ thống mô phỏng một số thuật toán trên đồ thị .......................... 54
Trang 6


4.1. Lựa chọn cơng cụ lập trình .................................................................... 55
4.2. Chức năng mơ phỏng của các thuật tốn được cài đặt .......................... 57
4.2.1 Mơ phỏng thuật tốn tìm kiếm ......................................................... 57
4.2.2. Mơ phỏng thuật tốn Dijkstra ......................................................... 59
4.2.3. Mơ phỏng thuật tốn Ford – Bellman ............................................. 61
4.2.4. Mơ phỏng thuật tốn Prim .............................................................. 61
4.2.5. Mơ phỏng thuật tốn Kruskal ......................................................... 63
4.2.6. Thuật tốn tìm chu trình Hamilton ................................................. 64
5. Giới thiệu chương trình ................................................................................ 64
5.1. Tổng quan về hệ thống .......................................................................... 64
5.1.1. Các đối tượng xây dựng cấu trúc đồ thị .......................................... 65
5.1.2. Cơng cụ vẽ hình ảnh để mơ phỏng ................................................. 68
5.1.3.Chức năng chi tiết của các công cụ hỗ trợ cho q trình mơ phỏng 68
5.2. Giới thiệu các công cụ hỗ trợ mô phỏng do người dùng cài đặt ........... 69
Chương 4 KẾT LUẬN ........................................................................................ 78
1. Những kết quả đạt được ............................................................................... 78
2. Hướng phát triển .......................................................................................... 79
DANH MỤC TÀI LIỆU THAM KHẢO ............................................................ 80

PHỤ LỤC ............................................................................................................ 82

Trang 7


LỜI NÓI ĐẦU
Cách đây gần ba thập kỉ (khoảng những năm 80 của thế kỉ XX), ở nhiều
nước trên thế giới mơ phỏng thuật tốn đã được sử dụng trong việc giảng dạy
các mơn Khoa học máy tính như một cơng cụ hữu hiệu để mơ tả thuật tốn một
cách trực quan, khoa học. Khơng những vậy nó cịn cho người học biết chi tiết
từng bước hoạt động của thuật tốn cùng với cấu trúc dữ liệu đi kèm thơng qua
việc mô tả bằng đồ họa.
Những năm gần đây, ở Việt Nam mơn Tin học đã được đưa vào chương
trình của học sinh trung học phổ thông như là mô ̣t môn ho ̣c chiń h thức . Tuy
nhiên trên thực tế , mô ̣t số trường chuyên trên cả nước đã tuyể n sinh ho ̣c sinh
chuyên Tin từ cuối những năm 80 của thế kỉ XX . Những ho ̣c sinh này cần nắm
chắc kiế n thức cơ bản về Tin học như: các cấu trúc dữ liệu trừu tượng : stack,
queue, cây, cây nhi ̣phân , cây nhi ̣phân tìm kiế m , các chiến lược thiết kế thuật
tốn: tham lam, quay lui, quy hoa ̣ch đơ ̣ng… Trong đó, lý thuyết về đờ thi ̣và
th ̣t toán trên đồ thị là một lĩnh vực rộng và phức tạp . Viê ̣c hiể u và cài đă ̣t tớ t
các thuật tốn đó đòi hỏi thời gian và công sức rấ t lớn . Hiện nay, việc truyền đạt
các thuật toán trên đồ thị cho học sinh chuyên Tin gặp rất nhiều khó khăn. Có
nhiều rất nhiều lý do: Các thuật tốn đó khó hình dung, việc tổ chức dữ liệu cho
nó cũng phức tạp, thời gian giảng dạy trên lớp có hạn, tài liệu tham khảo có thể
tự đọc, tự học vẫn cịn ít….
Trong khn khổ đề tài này, chúng tơi xây dựng một chương trình nhằm
mơ phỏng hoạt động của ba thuật tốn giải ba bài toán cơ bản trên đồ thị theo
phân phối chương trình của Bộ Giáo dục với hai mục đích: để học sinh có thể dễ
dàng nắm bắt tư tưởng cũng như từng bước hoạt động cụ thể của các thuật tốn,
để giáo viên có thể làm cho bài giảng về các thuật toán này trở nên dễ hiểu, dễ

tiếp thu hơn.
Nội dung luận văn đươ ̣c chia thành 3 chương:

Trang 8


Chương I. Những kiến thức cơ bản về thuật toán.
Ở chương này, chúng tơi trích nêu khái niệm về bài tốn và thuật tốn.
Các tính chất của thuật tốn, xác định độ phức tạp của thuật tốn…Cuối cùng,
chúng tơi giới thiệu ba thuật toán quan trọng trên đồ thị mà học sinh THPT sẽ
được học.
Chương II. Mơ phỏng thuật tốn.
Chương này chúng tơi trình bày khái niệm mơ phỏng, các chức năng của
mô phỏng và các vấn đề liên quan như: lịch sử mô phỏng, nghiên cứu về hiệu
quả của nó trong giảng dạy và một số yêu cầu đối với việc mơ phỏng thuật tốn
nói chung.
Chương III. Phân tích thiết kế hệ thống mơ phỏng một số thuật tốn trên
đồ thị.
Ở chương 3, chúng tơi trình bày về q trình phân tích, thiết kế và xây
dựng hệ thống mơ phỏng trên ba thuật tốn: thuật tốn tìm kiếm (tìm kiếm theo
chiều sâu và tìm kiếm theo chiều rộng), thuật tốn tìm đường đi ngắn nhất (thuật
tốn Dijsktra) và thuật tốn tìm cây khung cực tiểu trên đồ thị vơ hướng có trọng
số (thuật tốn Prim)…

Trang 9


Chương 1 MỘT SỐ KIẾN THỨC CƠ BẢN VỀ THUẬT TỐN
1. Khái niệm bài tốn Tin học
Trong phạm vi tin học, người ta quan niệm bài tốn là một cơng việc nào

đó mà con người muốn máy tính thực hiện. [xem 1]
Khi dùng máy tính để giải bài tốn, ta cần quan tâm tới 2 vấn đề: Dữ liệu
cần được đưa vào máy tính (Input) là gì và cần lấy ra (Output) thơng tin gì? Nói
một cách khác, cho một bài tốn là việc mơ tả rõ Input và Output của bài tốn.
Vấn đề cịn lại là: Làm thế nào để từ Input ta có được Output?
2. Khái niệm thuật toán
Khác với Toán học (các yêu cầu của bài toán thường là chứng minh sự tồn
tại đáp án chứ không yêu cầu tìm một cách chi tiết để tìm ra đáp án đó), giải một
bài tốn Tin học là việc đi tìm một lời giải cụ thể, tường minh để đưa ra Output
của bài toán dựa trên Input đã cho. Việc chỉ ra một cách tìm Output của bài tốn
được gọi là một thuật tốn. Có nhiều cách phát biểu khái niệm về thuật toán.
Dưới đây là cách phát biểu được chọn để đưa vào sách giáo khoa Tin học phổ
thơng:
Khái niệm về thuật tốn: thuật tốn là một dãy hữu hạn các thao tác
được sắp xếp theo một trình tự nhất định để sau khi thực hiện dãy các thao
tác đó, từ input ta có output cần tìm [xem 1].
Trong lĩnh vực máy tính, cụm từ “thuật tốn” đơi khi người ta dùng bằng
một từ khác: “giải thuật”.
Ví dụ về một thuật toán: Nhập vào một số nguyên dương N, kiểm tra số
đó có là số nguyên tố hay khơng?
Lời giải:
Input: Số ngun dương N.
Output: Có/khơng tương ứng với N có là ngun tố hay khơng?
Trang 10


Ý tƣởng: Một số nguyên gọi là nguyên tố khi nó chỉ có ước là 1 và chính
nó. Từ định nghĩa suy ra:
- Nếu N = 1 thì thơng báo là N không nguyên tố rồi kết thúc;
- Nếu 1< N < 4 thì thơng báo N là số ngun tố rồi kết thúc;

- Nếu N  4 và không có ước trong khoảng từ 2 đến [ N ] thì N là ngun
tố.
Thuật tốn: Có nhiều cách mơ phỏng khác nhau. Dƣới đây là cách
mơ phỏng thuật tốn dạng liệt kê các bƣớc:
Bước 1. Nhập số nguyên dương N;
Bước 2. Nếu N = 1 thì thơng báo là N không nguyên tố rồi kết thúc;
Bước 3. Nếu N < 4 thì thơng báo N là số ngun tố rồi kết thúc;
Bước 4. i  2;
Bước 5. Nếu i  [ N ](*) thì thơng báo N là ngun tố rồi kết thúc;
Bước 6. Nếu N chia hết cho i thì thơng báo N khơng ngun tố rồi kết
thúc;
Bước 7. i  i + 1 rồi quay lại bước 5;
3. Các tính chất của thuật tốn
Dựa trên khái niệm về thuật tốn và ví dụ ở trên ta thấy các thao tác trong
thuật tốn phải được mơ tả đủ chi tiết để một đối tượng cứ tiến hành thực hiện
theo đúng thứ tự các thao tác đó là có thể cho ra output dựa trên input tương
ứng. Một thuật toán phải đảm bảo được các tính chất sau:
Tính xác định: Sau khi thực hiện một thao tác thì hoặc là thuật tốn kết
thúc hoặc là có đúng một thao tác xác định để thực hiện tiếp theo.

Trang 11


Tính đúng đắn: Sau khi thực hiện thuật tốn ta phải nhận được đúng
Output cần tìm.
Tính dừng: Thuật tốn phải kết thúc sau một số hữu hạn lần thực hiện.
Tính tổng quát: Thuật toán là đúng đắn với mọi bộ dữ liệu đầu vào của
bài tốn.
Tính hiệu quả:
- Hiệu quả về thời gian: Ta quan tâm tới thời gian cần thiết để thực

hiện xong thuật tốn đó. Thời gian đó phải nằm trong giới hạn cho phép.
- Hiệu quả về không gian: Dung lượng bộ nhớ cần thiết để lưu trữ
các đối tượng như bộ Input, bộ Output, kết quả trung gian và chương trình
được dùng để thực hiện thuật tốn.
- Dễ cài đặt: thuật tốn đó liệu có chuyển được thành chương trình
bằng một ngơn ngữ lập trình nào đó hay khơng.
Trước khi xây dựng thuật tốn cho một bài tốn nào đó, trước tiên phải
xác định được Input và Output là gì, thử trên một số ví dụ cụ thể để định hướng
cho việc xây dựng thuật toán. [xem 1]
4. Độ phức tạp và xác định độ phức tạp của thuật tốn
Một thuật tốn chỉ có thể giải một bài tốn, nhưng một bài tốn có thể giải
bằng nhiều thuật toán khác nhau. Làm thế nào để lựa chọn một thuật toán tốt để
giải một bài toán đã cho? Tất nhiên, người lập trình thường chọn thuật tốn dễ
hiểu, dễ cài đặt. Theo đó, chương trình viết ra ít có khả năng có lỗi, việc nâng
cấp chương trình dễ dàng và nhiều người có thể thực hiện được. Nhưng nếu hiệu
quả của thuật toán (về mặt thời gian và khơng gian nhớ) là u cầu quan trọng
thì cần chọn một thuật toán chạy nhanh và sử dụng tài nguyên có sẵn một cách
hiệu quả. Như vậy dựa vào đâu để có thể kết luận thuật tốn này “nhanh” hơn
thuật toán kia?

Trang 12


Có một cách để biết được thuật tốn nào nhanh hơn bằng cách viết các
chương trình bằng cùng một ngơn ngữ lập trình cho các thuật tốn rồi so sánh
trên các bộ Input giống nhau trên cùng một hệ thống để kết luận thuật toán nào
nhanh, thuật toán nào chậm. Tuy nhiên cách này khơng chính xác và tốn nhiều
thời gian.
Một cách khác để đánh giá thuật toán là dựa vào tiêu chí mỗi câu lệnh của
chương trình nguồn sẽ thực hiện bao nhiêu lần trên một tập dữ liệu vào. Việc

đánh giá đó khơng chỉ đánh giá, so sánh trong việc lựa chọn thuật tốn mà cịn
có thể hiệu chỉnh, cải tiến thuật tốn đã có tốt hơn. Khi đánh giá thời gian thực
hiện thuật toán ta chú ý đặc biệt đến các phép toán mà số lần thực hiện khơng ít
hơn các phép tốn khác – ta gọi là phép tốn tích cực của thuật tốn.
Cách đánh giá thời gian thực hiện thuật toán độc lập với hệ thống máy
tính dẫn đến khái niệm về Độ phức tạp của thuật toán. Thời gian thực hiện một
thuật toán bằng chương trình máy tính phụ thuộc vào rất nhiều yếu tố. Một yếu
tố cần chú ý nhất đó là kích thước của dữ liệu đầu vào. Dữ liệu càng lớn thì thời
gian xử lý càng chậm. Nếu gọi n là kích thước dữ liệu đưa vào thì thời gian thực
hiện của một thuật tốn có thể biểu diễn một cách tương đối như một hàm của n:
T(n). Thực tế, T(n) khơng những chỉ phụ thuộc vào kích thước n mà cịn phụ
thuộc vào đặc tính, tình trạng thực tế của bộ dữ liệu đầu vào.
Ví dụ, với thuật tốn sắp xếp dãy số đã cho thành dãy tăng dần thì thời
gian sắp xếp còn phụ thuộc vào dãy đầu vào đã là dãy tăng dần, dãy được sinh
ngẫu nhiên hay được sắp xếp theo thứ tự ngược lại. Vì thế cần phải xem xét các
trường hợp tốt nhất, trung bình và xấu nhất. [Xem 2]
Việc xác định độ phức tạp của một thuật tốn bất kỳ có thể rất phức tạp.
Tuy nhiên, trong thực tế, đối với một số thuật tốn ta có thể phân tích bằng một
số quy tắc đơn giản:
4.1. Quy tắc max

Trang 13


Nếu thuật tốn T có thời gian thực hiện T(n) =O(f(n)+g(n)) thì có thể coi
T có độ phức tạp là O(max(f(n), g(n)))
4.2. Quy tắc tổng
Nếu thuật toán T gồm hai đoạn thuật toán liên tiếp T1 và T2 và nếu T1 có
thời gian thực hiện T1(n) = O(f(n)), T2 có thời gian thực hiện là T2(n) = O(g(n))
thì thời gian thực hiện T sẽ là:

T(n) = T1(n) + T2(n) = O(f(n)+ g(n))
4.3. Quy tắc nhân
Nếu đoạn chương trình T có thời gian thực hiện là T(n) = O(f(n)). Khi đó,
nếu thực hiện k(n) lần đoạn chương trình T với k(n) = O(g(n)) thì độ phức tạp sẽ
là O(g(n).f(n))
4.4. Một số tính chất
Theo định nghĩa về độ phức tạp tính tốn ta có một số tính chất:
a) Nếu một thuật tốn có độ phức tạp là hằng số, tức là thời gian thực hiện
khơng phụ thuộc vào kích thước dữ liệu vào thì ta ký hiệu độ phức tạp tính tốn
của thuật tốn đó là O(1).
b) Với một thuật tốn có độ phức tạp cấp logarit của f(n), người ta ký hiệu
là O(logf(n)) mà không cần ghi cơ số của logarit.
c) Với P(n) là một đa thức bậc k thì O(P(n)) = O(nk). Vì thế, một thuật
tốn có độ phức tạp cấp đa thức, người ta thường ký hiệu là O(nk)
d) Một thuật tốn có cấp là các hàm như 2n, n!, nn được gọi là một thuật
tốn có độ phức tạp hàm mũ. Những thuật toán như vậy trên thực tế thường có
tốc độ rất chậm. Các thuật tốn có cấp là các hàm đa thức hoặc nhỏ hơn hàm đa
thức thì thường nhanh hơn các thuật tốn hàm mũ. Tuy nhiên, khi chọn một
thuật toán để giải một bài tốn thực tế phải có một sự mềm dẻo nhất định dựa
vào những điều kiện thực tế cho phép.
Trang 14


Dưới đây là một số hàm số hay dùng để ký hiệu độ phức tạp tính tốn và
bảng giá trị của chúng để tiện theo dõi sự tăng của hàm theo đối số n.
logN

NlogN

N2


N3

2n

1

0

0

1

1

2

2

1

2

4

8

4

4


2

8

16

64

16

8

3

24

64

512

256

16

4

64

256


409

65536

32

5

160

1024

32768

4292967296

Hàm
N

Ví dụ: Tính giá trị của đa thức P(x)=anxn+an-1xn-1+ ... +a1x+a0 với a0, a1, ..., an,
x nhập từ bàn phím.
Thuật tốn 1:
1.Input n, a0, a1,a2,…an, x;
2. S:=a0;
3.for i := 1 to n do begin
3.1 p:=1;
3.2 for j := 1 to i do p:= p*x;
3.3 S:= S+ai*p;
End;

4. Output s;

Với mỗi giá trị i của vòng lặp 3, vòng lặp 3.2 thực hiện i vòng lặp nên khi
n = i nó thực hiện đủ n vịng lặp. Vậy vịng lặp 3 thực hiện

n(n  1)
lần câu lệnh
2

sau do nên thời gian tính tốn tỉ lệ thuận với n2.
Vậy độ phức tạp tính tốn của thuật tốn trên là O(n2).
Thuật tốn 2: Vì xn =x * xn-1 nên có thể tận dụng kết quả của lần tính trước cho
lần tính sau:

Trang 15


1. Input n, a0, a1,a2,…an, x;
2. S := a0;P:=1;
3. for i := 1 to n do begin
3.1 P:=p*x;
3.1 S:= S+p;
End;
4. Output S;

Hai lệnh 2 và 4 đều có độ phức tạp tính tốn là O(1). Vịng lặp 3 cần thực
hiện n lần hai thao tác tính S và p.Vậy số lần thực hiện lệnh 3 là 2n. Do vậy, độ
phức tạp tính tốn của thuật tốn trên là O(n).
5. Chi phí thực hiện thuật tốn
Khái niệm độ phức tạp tính tốn đặt ra là để đánh giá chi phí thực hiện

một thuật tốn về mặt thời gian. Nhưng chi phí thực hiện thuật tốn cịn có rất
nhiều yếu tố khác nữa: không gian bộ nhớ phải sử dụng là một ví dụ. Tuy nhiên,
trên phương diện phân tích lý thuyết, ta chỉ có thể xét tới vấn đề thời gian bởi
việc xác định các chi phí khác nhiều khi rất mơ hồ và phức tạp. Đối với người
lập trình thì khác, một thuật toán với độ phức tạp dù rất thấp cũng sẽ là vô dụng
nếu như không thể cài đặt được trên máy tính, chính vì vậy khi bắt tay cài đặt
một thuật toán, ta phải biết cách tổ chức dữ liệu một cách khoa học, tránh lãng
phí bộ nhớ khơng cần thiết. Có một quy luật tương đối khi tổ chức dữ liệu: Tiết
kiệm được bộ nhớ thì thời gian thực hiện thường sẽ chậm hơn và ngược lại. Biết
cân đối, dung hồ hai yếu tố đó là một kỹ năng cần thiết của người lập trình.
[Xem 2]
6. Ba bài tốn trên mơ hình đồ thị được đưa vào giảng dạy trong trường
Trung học Phổ thông Chuyên
6.1. Một số khái niệm cơ bản về đồ thị

6.1.1. Khái niệm đồ thị (Graph)
Là một cấu trúc rời rạc gồm các đỉnh và các cạnh nối các đỉnh đó. Được
mơ tả hình thức: G = (V, E). Trong đó:
Trang 16


V gọi là tập các đỉnh (Vertices) và E gọi là tập các cạnh (Edges). Có thể
coi E là tập các cặp (u, v) với u và v là hai đỉnh của V.
Một số hình ảnh của đồ thị:

Đồ thị vơ hướng

Đồ thị có hướng

6.1.2. Các khái niệm cơ bản

Có thể phân loại đồ thị theo đặc tính và số lượng của tập các cạnh E: Cho
đồ thị G = (V, E). Ta có một số khái niệm sau [xem 3- tập 1]:
Đơn đồ thị: G được gọi là đơn đồ thị nếu giữa hai đỉnh u, v của V có nhiều nhất
là 1 cạnh trong E nối từ u tới v.
Đa đồ thị: G được gọi là đa đồ thị nếu giữa hai đỉnh u, v của V có thể có nhiều
hơn 1 cạnh trong E nối từ u tới v.
Đồ thị vô hƣớng: G được gọi là đồ thị vô hướng nếu các cạnh trong E là không
định hướng, tức là cạnh nối hai đỉnh u, v bất kỳ cũng là cạnh nối hai đỉnh v, u.
Hay nói cách khác, tập E gồm các cặp (u, v) không tính thứ tự (u, v)  (v, u)
Đồ thị có hƣớng: G được gọi là đồ thị có hướng nếu các cạnh trong E là có định
hướng, có thể có cạnh nối từ đỉnh u tới đỉnh v nhưng chưa chắc đã có cạnh nối
từ đỉnh v tới đỉnh u. Hay nói cách khác, tập E gồm các cặp (u, v) có tính thứ tự:
(u, v)  (v, u). Trong đồ thị có hướng, các cạnh được gọi là các cung. Đồ thị vô

Trang 17


hướng cũng có thể coi là đồ thị có hướng nếu như ta coi cạnh nối hai đỉnh u, v
bất kỳ tương đương với hai cung (u, v) và (v, u).
Ví dụ:
3

1

2

5

B
4


Vơ hướng

Có hướng

Đơn đồ thị

Vơ hướng

Có hướng

Đa đồ thị

Cạnh liên thuộc, đỉnh kề, bậc
Đối với đồ thị vô hướng G = (V, E). Xét một cạnh e  E, nếu e = (u, v) thì
ta nói hai đỉnh u và v là kề nhau (adjacent) và cạnh e này liên thuộc (incident)
với đỉnh u và đỉnh v.
Với một đỉnh v trong đồ thị, ta định nghĩa bậc (degree) của v, ký hiệu
deg(v) là số cạnh liên thuộc với v. Dễ thấy rằng trên đơn đồ thị thì số cạnh liên
thuộc với v cũng là số đỉnh kề với v.
Đối với đồ thị có hướng G = (V, E). Xét một cung e  E, nếu e = (u, v) thì
ta nói u nối tới v và v nối từ u, cung e là đi ra khỏi đỉnh u và đi vào đỉnh v.
Đỉnh u khi đó được gọi là đỉnh đầu, đỉnh v được gọi là đỉnh cuối của cung e.
Với mỗi đỉnh v trong đồ thị có hướng, ta định nghĩa: Bán bậc ra của v ký
hiệu deg+(v) là số cung đi ra khỏi nó; bán bậc vào ký hiệu deg-(v) là số cung đi
vào đỉnh đó

Trang 18



Đƣờng đi: Một đường đi độ dài k từ đỉnh u đến đỉnh v là dãy (u = x0, x1,
..., xk = v) thoả mãn (xi, xi+1)  E (là 1 cạnh của đồ thị) với i: (0  i  k). Đỉnh
u gọi là đỉnh xuất phát, v gọi là đỉnh kết thúc của đường đi. Đường đi không có
cạnh nào đi qua hơn 1 lần gọi là đƣờng đi đơn.
Chu trình: Đường đi có đỉnh xuất phát trùng với đỉnh kết thúc gọi là chu
trình. tương tự ta có khái niệm chu trình đơn.
6.2. Bài tốn tìm kiếm trên đồ thị

6.2.1. Phát biểu bài toán
Cho đồ thị G = (V, E) và s và t là hai đỉnh của đồ thị.
Yêu cầu: Hãy chỉ ra một đường đi từ s đến t (nếu có).
Ví dụ: Xét một đồ thị vơ hướng và một đồ thị có hướng dưới đây:

Trên cả hai đồ thị, (1, 2, 3, 4) là đường đi đơn độ dài 3 từ đỉnh 1 tới đỉnh
4. Bởi (1, 2) (2, 3) và (3, 4) đều là các cạnh (hay cung.
Làm sao để duyệt tất cả các đỉnh có thể đến được từ một đỉnh xuất phát
nào đó? Vấn đề này đưa về một bài tốn liệt kê mà u cầu của nó là khơng
được bỏ sót hay lặp lại bất kỳ đỉnh nào. Vì vậy, cần phải xây dựng những thuật
toán cho phép duyệt một cách hệ thống các đỉnh, những thuật toán như vậy gọi
là những thuật tốn tìm kiếm trên đồ thị. Trong lý thuyết đồ thị, người ta quan

Trang 19


tâm đến hai thuật toán cơ bản nhất: thuật toán tìm kiếm theo chiều sâu và thuật
tốn tìm kiếm theo chiều rộng.
6.2.2. Giới thiệu thuật tốn tìm kiếm DFS và BFS
a. Thuật tốn tìm kiếm theo chiều sâu DFS (Depth – First – Search)
Tư tưởng của thuật tốn có thể trình bày như sau: Bắt đầu từ s, mọi đỉnh u
kề với s tất nhiên sẽ đến được từ s. Với mỗi đỉnh u đó, những đỉnh v kề với u

cũng đến được từ s... Ý tưởng đó gợi ý cho ta viết một thủ tục đệ quy DFS(u)
mô tả việc duyệt từ đỉnh u bằng cách thông báo thăm đỉnh u và tiếp tục quá trình
duyệt DFS(v) với v là một đỉnh chưa thăm kề với u. Để quá trình duyệt khơng
lặp lại bất kì đỉnh nào, ta dùng kỹ thuật đánh dấu, khi thăm một đỉnh, ta sẽ đánh
dấu đỉnh đó lại để các bước duyệt đệ quy kế tiếp khơng thăm lại đỉnh đó nữa.
Vấn đề cịn lại: Để in ra được đường đi từ đỉnh xuất phát s, trong quá trình
duyệt DFS(u), trước khi gọi đệ quy DFS(v) với v là một đỉnh kề với u mà chưa
đánh dấu, ta lưu lại “vết” đường đi từ u tới v bằng cách đặt trace[v] := u, tức là
trace[v] là đỉnh liền trước v trong đường đi từ s tới v. Khi quá trình tìm kiếm
theo chiều sâu kết thúc, đường đi từ S tới F sẽ là:
t  Trace[t]  …. Trace[u1] ... Trace[s]  s.
Truy ngược đường đi này sẽ cho ta hành trình đi từ s đến t. Có thể mơ tả
thủ tục DFS dạng giả mã như sau:
Procedure DFS(uV);
Begin
< 1. Thông báo tới được u >;
< 2. Đánh dấu u là đã thăm>;
< 3. Xét mọi đỉnh v kề với u mà chưa thăm, với mỗi đỉnh v đó >;
Begin
Trace[v] := u;

{Truy vết đường đi}

DFS(v);

{Gọi đệ quy duyệt bắt đầu với v}

Trang 20



End;
End;
Begin
<Input: đồ thị G, s, t >;
<Khởi tạo: Tất cả các đỉnh đều chưa bị đánh dấu >;
DFS(s);
- Nếu t chưa bị đánh dấu thì kết luận: Khơng có đường từ s->t>;
- Nếu t đã bị đánh dấu thì dựa vào Trace tìm đường đi từ s->t>;
>;
End.

b. Thuật tốn tìm kiếm theo chiều rộng BFS (Breadth – First – Search)
Ý tưởng của phương pháp cài đặt này là "lập lịch" duyệt các đỉnh. Khi
thăm một đỉnh ta sẽ lên lịch thăm tất cả các đỉnh kề nó sao cho thứ tự duyệt là
ưu tiên chiều rộng (đỉnh nào gần s hơn sẽ được duyệt trước). Ví dụ: Bắt đầu, ta
thăm đỉnh s. Quá trình thăm S sẽ lên lịch duyệt những đỉnh (u1, u2, ..., up) kề với
s (những đỉnh gần s nhất). Tiếp theo sẽ thăm đỉnh u1, khi thăm u1 sẽ lại lên lịch
duyệt những đỉnh (v1, v2 ..., vq) kề với u1. Nhưng rõ ràng các đỉnh này "xa" s hơn
những đỉnh u nên chúng chỉ được duyệt đến khi tất cả những đỉnh u đã duyệt
xong. Tức là thứ tự duyệt đỉnh sau khi đã thăm u1 sẽ là: (u2, u3..., up, v1, v2, ...,
vq). Do việc lập lịch như mô tả ở trên nên cần phải xếp hàng cho các đỉnh đã lên
lịch theo đúng thứ tự. Khi thêm đỉnh nào đó ta sẽ thêm vào cuối hàng (vì đỉnh
lên lịch sau chắc chắn xa hơn các đỉnh đã lên lịch (vào hàng) rồi. Chính vì
ngun tắc đó nên danh sách chứa những đỉnh đang chờ sẽ được tổ chức dưới
dạng hàng đợi (Queue).
Ta sẽ dựng giải thuật như sau:
Bước 1: Khởi tạo: free[s] = true; free[v] = false v V\{s}
First:=1; Last:=1; Queue[Last]:=s;//Queue chỉ chứa s


Trang 21


Bước 2: Lặp cho tới khi Queue rỗng:
u := pop;//lấy u khỏi hàng đợi
free[u]:= false;
Xét v V: nếu v chưa được thăm:
Free[v] = false;//đánh dấu đã thăm
Trace[v] = u;
Push(v);//đẩy v vào hàng đợi, chờ được thăm
Bước 3: Truy vết tìm đường đi hoặc thông báo không thấy đường.

6.2.3. Độ phức tạp tính tốn của thuật tốn DFS và BFS
Q trình tìm kiếm trên đồ thị bắt đầu từ một đỉnh có thể thăm tất cả các
đỉnh cịn lại, khi đó cách biểu diễn đồ thị [xem 3 – tập 1] có ảnh hưởng lớn tới
chi phí về thời gian thực hiện giải thuật:
Trong trường hợp ta biểu diễn đồ thị bằng danh sách kề, cả hai thuật toán
BFS và DFS đều có độ phức tạp tính tốn là O(n + m) = O(max(n, m)). Đây là
cách cài đặt tốt nhất. Nếu ta biểu diễn đồ thị bằng ma trận kề thì độ phức tạp tính
tốn trong trường hợp này là O(n + n2) = O(n2). Nếu ta biểu diễn đồ thị bằng
danh sách cạnh, thao tác duyệt những đỉnh kề với đỉnh u sẽ dẫn tới việc phải
duyệt qua toàn bộ danh sách cạnh, đây là cài đặt tồi nhất, nó có độ phức tạp tính
tốn là O(n.m).
6.3. Bài tốn tìm đƣờng đi ngắn nhất trên đồ thị có trọng số

6.3.1. Phát biểu bài tốn
Khái niệm đồ thị có trọng số: Đồ thị có trọng số là một bộ ba G = (V, E,
w) trong đó, G = (V, E) là đồ thị, w là hàm được định nghĩa:
w: E  R
e  w(e)


Bài tốn đó phát biểu dưới dạng tổng quát như sau: Cho đồ thị có trọng số
G = (V, E,w) là đồ thị khơng có chu trình âm.

Trang 22


Yêu cầu: Hãy tìm một đường đi ngắn nhất (tổng trọng số qua các đỉnh
trên đường đi) từ đỉnh xuất phát s  V đến đỉnh đích t  V.
Nếu như đồ thị có chu trình âm (chu trình với độ dài âm) thì khoảng cách
giữa một số cặp đỉnh nào đó có thể khơng xác định, bởi vì bằng cách đi vịng
theo chu trình này một số lần đủ lớn, ta có thể chỉ ra đường đi giữa hai đỉnh nào
đó trong chu trình này nhỏ hơn bất kỳ một số cho trước nào. Trong trường hợp
như vậy, có thể đặt vấn đề tìm đường đi cơ bản (đường đi khơng có đỉnh lặp lại)
ngắn nhất. Vấn đề đó là một vấn đề hết sức phức tạp mà ta sẽ không bàn tới ở
đây.
Dưới đây, chúng tôi giới thiệu hai thuật toán giải bài toán này là thuật
toán Ford – Bellman và thuật toán Dijkstra.
6.3.2. Giới thiệu thuật toán Ford - Bellman
Thuật tốn Ford-Bellman có thể phát biểu rất đơn giản:
Với đỉnh xuất phát S. Gọi d(v) là khoảng cách từ S tới v.
Ban đầu d(S) được khởi gán bằng 0 còn các d(v) với v  S được khởi gán
bằng +.
Sau đó ta tối ưu hố dần các d(v) như sau: Xét mọi cặp đỉnh u, v của đồ
thị, nếu có một cặp đỉnh u, v mà d(v) > d(u) + c(u, v) thì ta đặt lại d(v) := d(u) +
c(u, v). Tức là nếu độ dài đường đi từ S tới v lại lớn hơn tổng độ dài đường đi từ
S tới u cộng với chi phí đi từ u tới v thì ta sẽ huỷ bỏ đường đi từ S tới v đang có
và coi đường đi từ S tới v chính là đường đi từ S tới u sau đó đi tiếp từ u tới v.
Chú ý rằng ta đặt c[u, v] = + nếu (u, v) khơng là cung. Thuật tốn sẽ kết thúc
khi không thể tối ưu thêm bất kỳ một nhãn d[v] nào nữa.

Tính dừng của thuật tốn:
Tại bước lặp 0: Bước khởi tạo d(S) = 0; d(v) := + với v  S: thì dãy d(v)
chính là độ dài đường đi ngắn nhất từ S tới v đi qua không quá 0 cạnh
Trang 23


Giả sử tại bước lặp thứ i, d(v) bằng độ dài đường đi ngắn nhất từ S tới v
qua không q i cạnh, thì do tính chất: đường đi từ S tới v qua không quá i + 1
cạnh sẽ phải thành lập bằng cách: lấy một đường đi từ S tới một đỉnh u nào đó
qua khơng q i cạnh, rồi đi tiếp tới v bằng cung (u, v). Nên độ dài đường đi
ngắn nhất từ S tới v qua khơng q i + 1 cạnh sẽ được tính bằng giá trị nhỏ nhất
trong các giá trị: (Nguyên lý tối ưu Bellman)
Độ dài đường đi ngắn nhất từ S tới v qua không quá i cạnh
Độ dài đường đi ngắn nhất từ S tới u qua không quá i cạnh cộng với trọng
số cạnh (u, v) (u)
Nên sau bước lặp tối ưu các d(v) bằng công thức d(v) bước i+1 = min(d(v)bước
i,

d(u)bước i+ c(u, v)) thì các d(v) sẽ bằng độ dài đường đi ngắn nhất từ S tới v qua

không quá i + 1 cạnh.
Sau bước lặp tối ưu thứ n - 1, ta có d(v) = độ dài đường đi ngắn nhất từ S
tới v qua không q n - 1 cạnh. Vì đồ thị khơng có chu trình âm nên sẽ có một
đường đi ngắn nhất từ S tới v là đường đi cơ bản (qua không quá n - 1 cạnh).
Tức là d(v) sẽ là độ dài đường đi ngắn nhất từ S tới v.
Vậy thì số bƣớc lặp tối ƣu hố sẽ khơng q n - 1 bƣớc. Nếu mỗi bước
ta mô tả dưới dạng:
for u := 1 to n do
for v := 1 to n do
d(v) := min(d(v), d(u) + c(u, v));


Thì do sự tối ưu bắc cầu (dùng d(u) tối ưu d(v) rồi lại có thể dùng d(v) tối
ưu d(w) nữa...) nên chỉ làm tốc độ tối ưu nhãn d(v) tăng nhanh lên chứ khơng
thể giảm đi được.
6.2.3. Giới thiệu thuật tốn thuật tốn Dijkstra
Thuật tốn Dijkstra (E.Dijkstra - 1959) có thể mô tả như sau:

Trang 24


Bước 1: Khởi tạo
Với đỉnh v  V, gọi nhãn d[v] là độ dài đường đi ngắn nhất từ s tới v. Ta
sẽ tính các d[v]. Ban đầu d[v] được khởi gán bằng w[s, v]. Nhãn của mỗi đỉnh
có hai trạng thái tự do hay cố định, nhãn tự do có nghĩa là có thể cịn tối ưu hơn
được nữa và nhãn cố định tức là d[v] đã bằng độ dài đường đi ngắn nhất từ s tới
v nên không thể tối ưu thêm. Để làm điều này ta có thể sử dụng kỹ thuật đánh
dấu: Free[v] = TRUE hay FALSE tuỳ theo d[v] tự do hay cố định. Ban đầu các
nhãn đều tự do.
Bước 2: Lặp
Cố định nhãn: Chọn trong các đỉnh có nhãn tự do, lấy ra đỉnh u là đỉnh có
d[u] nhỏ nhất, và cố định nhãn đỉnh u.
Sửa nhãn: Dùng đỉnh u, xét tất cả những đỉnh v và sửa lại các d[v] theo
công thức:
d[v] := min(d[v], d[u] + c[u, v])
Bước lặp sẽ kết thúc khi mà đỉnh đích t được cố định nhãn (tìm được
đường đi ngắn nhất từ s đến t); hoặc tại thao tác cố định nhãn, tất cả các đỉnh tự
do đều có nhãn là + (khơng tồn tại đường đi).
Có thể đặt câu hỏi, ở thao tác 1, tại sao đỉnh u như vậy được cố định nhãn,
giả sử d[u] còn có thể tối ưu thêm được nữa thì tất phải có một đỉnh t mang nhãn
tự do sao cho d[u] > d[t] + c[t, u]. Do trọng số c[t, u] không âm nên d[u] > d[t],

trái với cách chọn d[u] là nhỏ nhất. Tất nhiên trong lần lặp đầu tiên thì S là đỉnh
được cố định nhãn do d[s] = 0.
Bước 3: Kết hợp với việc lưu vết đường đi trên từng bước sửa nhãn, thông
báo đường đi ngắn nhất tìm được hoặc cho biết khơng tồn tại đường đi (d[t] =
+). Có thể mơ tả ngắn gọn thuật tốn bằng giả mã như sau:
Bước 1: d[s] = 0 ; d[v] = + (v  V\{s}); u = s;

Trang 25


×