Tài liệu được dùng cho các thành viên trong CLB Lập Trình Học viện Công nghệ Bưu Chính Viễn Thông. Được tổng hợp từ các thành viên ưu tú nhất CLB , được sự góp ý của các thầy cô giáo trong khoa. Tập tài liệu này sẽ có đôi chỗ còn thiếu sót, mong các bạn sẽ cùng đóng góp, nghiên cứu trao đổi để chúng ta có một bộ tài liệu đầy đủ nhất có thể. Chúng tôi cần sự hợp tác của các bạn. Chúc các bạn thành công
CLB Lập trình PTIT - ProPTIT Tài liệu thuật toán MỤC LỤC Contents Bài Sắp xếp Tìm kiếm – tìm kiếm nhị phân I Các phương pháp xếp Sắp xếp bọt Sắp xếp chọn 3.Sắp xếp trộn Sắp xếp nhanh 11 Bài tập áp dụng 14 II Thuật toán tìm kiếm nhị phân 15 Tìm kiếm tìm kiếm nhị phân 15 Tư tưởng thuật toán 15 Minh họa thuật toán 15 Code tham khảo 16 Bài tập áp dụng : 17 Bài 2: Các phương pháp sinh 18 I Giới thiệu 18 II Cấu trúc thuật toán sinh 18 III Giới thiệu bốn phương pháp sinh 19 Sinh nhị phân 19 Sinh hoán vị 20 Sinh tổ hợp 23 Sinh chỉnh hợp 25 Bài tập ứng dụng 26 Bài 3: Đệ quy quay lui kỹ thuật nhánh cận 27 I Đệ quy 27 Khái niệm đệ quy 27 Giải thuật đệ quy 27 Page CLB Lập trình PTIT - ProPTIT Một số ví dụ đệ quy 28 Một số tập áp dụng 30 II Quay lui 30 Giới thiệu quay lui 30 Mô hình thuật toán quay lui 31 Các ví dụ quay lui 32 III Một số toán đặc trưng sử dụng thuật toán Đệ quy – Quay lui 35 Bài toán tìm đường ma trận 35 Bài toán người du lịch 36 Bài toán xếp hậu 38 Bài toán quân mã tuần 41 IV Kỹ thuật nhánh cận 44 Bài toán tối ưu bùng nổ tổ hợp 44 Mô hình kỹ thuật nhánh cận 44 Một số toán sử dụng kỹ thuật nhánh cận 45 Bài 4: Cấu trúc liệu STACK – QUEUE 50 I STACK – Ngăn xếp 50 II QUEUE – Hàng đợi 53 III Priority_Queue_Hàng đợi ưu tiên 54 Khái niệm: 54 Cấu trúc Heap: 55 Cách sử dụng priority queue thư viện STL: 56 Bài : Quy hoạch động 59 I Quy hoạch động gì? 59 Đệ quy quy hoạch động : 59 Quy hoạch động ? 59 Ưu nhươc điểm : 59 II Hai cách tiếp cận quy hoạch động 59 Top-down (Từ xuống): 60 Bottom-up (Từ lên) 61 Page CLB Lập trình PTIT - ProPTIT Phương pháp giải toán quy hoạch động : 62 III Một số toán, ví dụ quy hoạch động 62 Bài toán dãy đơn điệu dài 62 Bài toán xâu chung dài 66 Bài toán túi – quy hoạch động 69 Bài 6: Đồ thị - Các phương pháp duyệt đồ thị 72 I Lý thuyết đồ thị 72 1.Định nghĩa đồ thị: 72 Phân loại 73 Các khái niệm 74 Các cách biểu diễn lưu trữ đồ thị 75 II.Các thuật toán duyệt đồ thị không trọng số 81 1.Thuật toán duyệt đồ thị theo chiều sâu (Depth-First Search - DFS) 81 Thuật toán duyệt đồ thị theo chiều rộng (Breadth-First Search - BFS) 90 III Bài tập áp dụng 95 TÀI LIỆU THAM KHẢO 96 Page CLB Lập trình PTIT - ProPTIT LỜI NÓI ĐẦU Thay mặt cho người biên soạn tập tài liệu này, có đôi lời muốn nói với bạn Trước hết, người soạn tài liệu KHÔNG phải GIÁO SƯ, TIẾN SĨ… Hay có trình độ học vấn uyên bác Nhưng tất kiến thức tích cóp từ nguồn đánh tin cậy từ “bố đẻ google” , phần kiến thức lý thuyết mà THẦY GIÁO/ GIÁO SƯ/ TIẾN SĨ giảng dạy từ trường đại học, biến chuyển, hay chuyển thể sang cách học “ Bình dân” để người bắt đầu không thấy lạ lẫm hay khó khăn để bắt đầu với ngôn ngữ lập trình Những người biên soạn chúng tôi, người chưa biết lập trình, phải học, phải sai để ngồi biên soạn tập tài liệu Là người trước, nên biết bạn sai đâu, vướng mắc đâu, nên tài liệu này, giảm tải cao siêu uyên bác mà nhà lập trình giỏi họ nói, để hạ mức xuống, phổ thông giúp bạn dễ dàng tiếp cận Vì hi vọng tập tài liệu hữu ích với bạn Hơn nữa, Sinh viên bạn, tầm hiểu biết sâu rộng giúp bạn giải đáp thắc mắc Cũng tập tài liệu có đôi chỗ thiếu sót, mong bạn đóng góp, nghiên cứu trao đổi để có tài liệu đầy đủ Chúng cần hợp tác bạn Chúc bạn thành công! Page CLB Lập trình PTIT - ProPTIT Bài Sắp xếp Tìm kiếm – tìm kiếm nhị phân I Các phương pháp xếp Ta có dãy số a1, a2,, …, aN lưu trữ cấu trúc liệu mảng Sắp xếp dãy số a1, a2, …., aN thực việc bố trí lại phần tử cho hình thành dãy ak1, ak2, …., akN có thứ tự (ví dụ thứ tự tăng) nghĩ aki > aki -1 Tùy theo yêu cầu toán tính chất dãy số,ta có phương pháp xếp khác Tuy nhiên, giới thiệu phương pháp phổ thông là: xếp bọt,sắp xếp chọn, xếp trộn xếp nhanh Sắp xếp bọt Ý tưởng : Xuất phát từ đầu dãy, so sánh phần tử cạnh để đưa phần tử nhỏ lên trước, sau lại xét cặp tiến đầu dãy Nhờ vậy, lần xử lý thứ i tìm phần tử vị trí đầu dãy i Giải thuật : Bước 1: i=1 // Lần xử lý Bước 2: j=N // Duyệt từ cuối dãy trở vị trí Trong (j > i) thực hiện: Nếu a[j] < a[j-1]: hoán vị a[j] a[j-1] j=j-1; Bước 3: i=i+1 // Lần xử lý Nếu I > N-1 dừng Ngược lại, lặp lại bước Nhận xét : Lần duyệt ta cần duyệt n phần tử,lần duyệt thứ cần duyệt n-1 phần tử,…cứ duyệt lần duyệt cuối phần tử.Vậy số lần duyệt phương pháp n + (n-1) + (n-2) + +1 = n(n+1)/2 tương đương với độ phức tạp O(n^2) Page CLB Lập trình PTIT - ProPTIT Ví dụ : Cho mảng a[5]={ 5, 1, 12, -5, 16 } Chúng ta cần xếp mảng tăng dần theo giá trị Khi đó, thuật toán Bubble Sort trình bày sau: Code : Page CLB Lập trình PTIT - ProPTIT Sắp xếp chọn Ý tưởng : Chọn phần tử nhỏ n phần tử ban đầu, đưa phần tử vị trí dãy hành Sau không quan tâm đến nữa, xem dãy hành n-1 phần tử dãy ban đầu, vị trí thứ Lặp lại trình cho dãy hành đến dãy hành phần tử Giải thuật : Bước : Đặt i=1,min=1 với biến dùng để tìm vị trí phần tử nhỏ dãy xét Bước : Tìm phần tử a[min] nhỏ dãy xét từ i đến n Bước : Hoán vị a[min] a[i] Bước : Nếu i -> -> Đến hết đỉnh kề thực quay lui tiếp tục duyệt tiếp: -> - > 6, đến dừng thuật toán thăm đủ n đỉnh thực quay lui về, chương trình tự động quay lui không thực sâu qua hết đỉnh Dưới giải thích cách hoạt động : - Giả sử chọn đỉnh 1: Duyệt (1) DFS_Dequy (1) - For (1-> 6) tìm đỉnh chưa đánh dấu đến từ Gặp thỏa mãn: Duyệt (2) DFS_Dequy (2) - For (1-> 6) tìm đỉnh chưa đánh dấu đến từ Gặp thỏa mãn: Duyệt (4) DFS_Dequy (4) - For (1-> 6) tìm đỉnh chưa đánh dấu đến từ Gặp thỏa mãn: Duyệt (3) DFS_Dequy (3) - For (1-> 6) tìm đỉnh chưa đánh dấu đến từ Không tìm thấy -> Dừng DFS_Dequy (3) Tiếp tục DFS_Dequy (4) Gặp thỏa mãn: Duyệt (5) DFS_Dequy (5) For (1-> 6) tìm đỉnh chưa đánh dấu đến từ Gặp thỏa mãn: Duyệt (6) DFS_Dequy (6) For (1-> 6) tìm đỉnh chưa đánh dấu đến từ Không tìm thấy -> Dừng DFS_Dequy (6) Tiếp tục DFS_Dequy (5) Không tìm thấy -> Dừng DFS_Dequy (5) Tiếp tục DFS_Dequy (4) Không tìm thấy -> Dừng DFS_Dequy (4) Tiếp tục DFS_Dequy (2) Không tìm thấy -> Dừng DFS_Dequy (2) Page 84 CLB Lập trình PTIT - ProPTIT - Tiếp tục DFS_Dequy (1) Không tìm thấy -> Dừng DFS_Dequy (1) Hoàn thiện Code : b Cài đặt thuật toán cấu trúc liệu Stack : Như biết ứng dụng Stack khử đệ quy, toán duyệt đồ thị thuật toán DFS, số đỉnh đồ thị lớn ( cỡ 10^6) có số vấn đề tràn nhớ đệ quy để cải thiện điều sử dụng Stack cách tốt Nhập liệu đồ thị : ( Giống phần cài đặt DFS _ Đệ quy ) Page 85 CLB Lập trình PTIT - ProPTIT Cài đặt DFS_Stack : Trên tư tưởng khử đệ quy, pop() đỉnh ra, đỉnh sâu vào ta phải thực push lại đỉnh vào để lần pop phía sau đem đỉnh rẽ nhánh sang nhánh khác – tư tưởng quay lui STT 10 11 Kiểm nghiệm thuật toán cho ví dụ : Trạng thái stack 1, 1, 2, 1, 2, 3, 1, 2, 3, 1, 2, 3, 5, 1, 2, 3, 1, 2, 1, Rỗng kết thúc (pop(4) ) (pop(6) ) (pop(5) ) (pop(3) ) (pop(2) ) (pop(1) ) Các đỉnh duyệt 1, 1, 2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, Hoàn thiện Code : Page 86 CLB Lập trình PTIT - ProPTIT c Ứng dụng cho DFS – Bài toán tìm thành phần liên thông Định nghĩa thành phần liên thông: - Đồ thị vô hướng coi liên thông tìm đường hai đỉnh - Trong trường hợp đồ thị G không liên thông, ta phân G thành số đồ thị liên thông mà chúng đôi đỉnh chung Mỗi đồ thị thành phần liên thông G Như vậy, đồ thị liên thông số thành phần liên thông Page 87 CLB Lập trình PTIT - ProPTIT - Đối với đồ thị vô hướng, đường từ đỉnh u đến đỉnh v giống đỉnh đường từ đỉnh v đến đỉnh u Chính vậy, tồn u V cho u có đường đến tất đỉnh lại đồ thị ta kết luận đồ thị liên thông Ví dụ : Cho đồ thị hình vẽ xác định số thành phần liên thông: 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Dễ thấy ta có thành phần liên thông là: {1, 2, 3, 4, 5, 6}; {7, 8} {9}; Áp dụng DFS tìm thành phần liên thông: Ý tưởng: Một đồ thị liên thông không liên thông Nếu đồ thị liên thông số thành phần liên thông Điều tương đương với phép duyệt theo thứ tự DFS (u) gọi đến lần Page 88 CLB Lập trình PTIT - ProPTIT Mô tả thuật toán: Nếu đồ thị không liên thông (số thành phần liên thông lớn 1) tách chúng thành đồ thị liên thông Điều có nghĩa phép duyệt đồ thị, số thành phần liên thông số lần gọi tới thủ tục DFS ( ) Để xác định số thành phần liên thông đồ thị, sử dụng thêm biến solt để ghi nhận đỉnh thành phần thông Hoàn thiện Code : Page 89 CLB Lập trình PTIT - ProPTIT Thuật toán duyệt đồ thị theo chiều rộng (Breadth-First Search - BFS) Định nghĩa BFS (Breadth-First Search) tên gọi cho thuật toán tìm kiếm đồ thị dựa theo ưu tiên chiều rộng Có nghĩa là, xuất phát từ nút, ta bắt đầu duyệt tất nhánh tầng liền kề nó, từ nhánh duyệt tiếp tầng liền kề tiếp theo, hết vùng liên thông Trên hình ví dụ đồ thị duyệt từ nút theo phương pháp BFS Cách cài đặt BFS Đặc trưng BFS để phân biệt với thuật toán tìm kiếm đồ thị khác việc sử dụng cấu trúc liệu hàng đợi (queue) Nguyên lý hoạt động là: ban đầu, nút đồ thị truyền vào hàng đợi Từ trở đi, tới nút nút xuất khỏi hàng đợi, đồng thời chèn vào hàng đợi nút liền kề với nút mà chưa duyệt qua Do cấu trúc hàng đợi LIFO – đầu vào, đầu ra, nên đỉnh lớp trước lấy đỉnh duyệt tới cho vào phía sau hàng đợi, đảm bảo duyệt đồ thị từ lớp gần với đỉnh xuất phát trước Thuật toán kết thúc hàng đợi rỗng Page 90 CLB Lập trình PTIT - ProPTIT Bài toán cụ thể : Cho đồ thị vô hướng không trọng số hình vẽ Với điểm xuất phát 1, yêu cầu duyệt qua đỉnh cho đỉnh lần thuật toán BFS Áp dụng thuật toán BFS : Thuật toán tìm kiếm theo chiều rộng (BFS) đỉnh u duyệt đến đỉnh v kề tập đỉnh, tiếp tục chọn đỉnh tập đỉnh vừa lấy đem đỉnh tìm đỉnh chưa xét đưa vào hàng đợi Ở chọn đỉnh đầu tiên: Ta có cách duyệt : 2,3 : {2,3} : {3,4} Ø : {4} 5,6 : {5,6} : {5,6,7} Danh sách đỉnh duyệt : , , , 4, , 6, Cài đặt thuật toán BFS : Nhập liệu biểu diễn đồ thị : DFS,ở nhập vào cặp cạnh (u, v) biểu diễn đồ thị danh sách kề Cài đặt thuật toán BFS : - Đầu tiên khởi tạo hàng đợi chứa đỉnh bắt đầu đánh dấu đỉnh xét, đỉnh lại chưa xét - Mỗi bước thực lấy đỉnh khỏi hàng đợi thực duyệt đến đỉnh kề với đỉnh mà chưa xét, thực push đỉnh vào hàng đợi đồng thời đánh dấu xét - Các bước lặp lại hàng đợi rỗng Code C++ : BFS(1) cho phép duyệt đồ thị từ đỉnh Page 91 CLB Lập trình PTIT - ProPTIT Kiểm nghiệm thuật toán : Bước Queue 2,3 3,4 5,6 6,7 Ø Đỉnh chọn Kết thúc Đỉnh duyệt 2,3 Ø 5,6 Ø Ø Ứng dụng BFS vào toán tìm đường ngắn đồ thị không trọng số: Phát biểu toán : Cho đơn đồ thị vô hướng không trọng số gồm n đỉnh, m cạnh, đỉnh s, t thuộc tập đỉnh Cho m cặp cạnh, tìm đường có tổng số cạnh qua nhỏ từ s t Nhận xét: + Khi thực duyệt đồ thị theo chiều rộng, đỉnh duyệt phân thành lớp, đỉnh lớp có khoảng cách tới đỉnh xuất phát + Các đỉnh nằm lớp lớn có cách duyệt để nằm lớp bé từ lớp trước duyệt tất đỉnh nằm lớp sau Khoảng cách đỉnh bắt đầu đỉnh đồ thị sử dụng phương pháp duyệt BFS đường có tổng số cạnh nhỏ Page 92 CLB Lập trình PTIT - ProPTIT + Mỗi đỉnh cập nhật vào hàng đợi theo đỉnh khác lớp trước Ta từ đỉnh đích dần lần vết để in đường ngắn từ st cho trước Ý tưởng: - Thuật toán BFS đỉnh s duyệt cho ta đường nhỏ đến đỉnh t - Sử dụng mảng truoc[1 n] : truoc[v] lưu đỉnh cha v u duyệt đồ thị từ u v để phục vụ cho trình lần vết Truy vết: Code hoàn chỉnh : Page 93 CLB Lập trình PTIT - ProPTIT Page 94 CLB Lập trình PTIT - ProPTIT III Bài tập áp dụng http://www.spoj.com/PTIT/problems/BCACM11D/ http://vn.spoj.com/problems/MTWALK/ http://vn.spoj.com/problems/VMUNCH/ http://vn.spoj.com/problems/QBBISHOP/ http://vn.spoj.com/problems/NKGUARD/ http://vn.spoj.com/problems/PBCWATER/ Page 95 CLB Lập trình PTIT - ProPTIT TÀI LIỆU THAM KHẢO Giải thuật lập trình - thầy Lê Minh Hoàng Tài liệu giáo khoa chuyên tin KC-BOOK (Quy hoạch động) Một số vấn đề đáng ý môn tin học DP-SpeedUp - admin Ngô Minh Đức KC-BOOK3 Page 96 ... CLB Lập trình PTIT - ProPTIT Page 13 CLB Lập trình PTIT - ProPTIT Code : Bài tập áp dụng http://vn.spoj.com/problems/DHEXP/ http://www.spoj.com /PTIT/ problems /PTIT1 23A/ Page 14 CLB Lập trình PTIT. .. Page CLB Lập trình PTIT - ProPTIT Ví dụ : Cho mảng a[5]={ 5, 1, 12, -5, 16 } Chúng ta cần xếp mảng tăng dần theo giá trị Khi đó, thuật toán Bubble Sort trình bày sau: Code : Page CLB Lập trình PTIT. .. 95 TÀI LIỆU THAM KHẢO 96 Page CLB Lập trình PTIT - ProPTIT LỜI NÓI ĐẦU Thay mặt cho người biên soạn tập tài liệu này, có đôi lời muốn nói với bạn Trước hết, người soạn tài liệu