Phân tích một bài toán
Sau bài này bạn sẽ làm được
- Lập bảng phân tích đầy đủ cho một bài toán bất kỳ
- Trả lời năm câu hỏi bắt buộc trước khi viết dòng code đầu tiên
- Suy ra độ phức tạp cho phép từ ràng buộc thời gian
- Chọn cấu trúc dữ liệu phù hợp với bài toán
Bài cuối của Phần 2 gom mọi thứ lại thành một công cụ dùng được ngay: bảng phân tích bài toán. Từ giờ tới hết khóa học, mọi bài tập có thuật toán đều bắt đầu bằng bảng này.
#Mô hình vào xử lý ra
Mô hình này đơn giản tới mức có vẻ tầm thường, nhưng nó ép bạn tách rõ ba việc mà người mới hay trộn lẫn: dữ liệu đến từ đâu, làm gì với nó, và kết quả đi đâu.
#Năm câu hỏi bắt buộc
Đây là danh sách kiểm tra. Nếu chưa trả lời được cả năm thì chưa nên viết dòng mã nào.
| Câu | Câu hỏi | Nếu bỏ qua |
|---|---|---|
| 1 | Dữ liệu vào chính xác là gì? Kiểu, miền giá trị, kích thước tối đa? | Chọn sai kiểu dữ liệu, tràn số, hoặc cấp phát thiếu |
| 2 | Dữ liệu ra chính xác là gì? Định dạng, làm tròn, đơn vị? | Chạy đúng logic nhưng in sai định dạng, vẫn bị coi là sai |
| 3 | Có những trường hợp biên nào? | Chương trình chạy đúng với dữ liệu mẫu rồi hỏng với dữ liệu thật |
| 4 | Ràng buộc thời gian và bộ nhớ là bao nhiêu? | Viết xong mới biết thuật toán quá chậm, phải làm lại từ đầu |
| 5 | Nếu dữ liệu vào sai thì làm gì? | Chương trình dừng đột ngột hoặc cho kết quả vô nghĩa |
#Bảng phân tích mẫu
MSSV,HoTen,Diem. In ra 10 sinh viên có điểm cao nhất, sắp xếp giảm dần theo điểm.| Mục | Nội dung |
|---|---|
| Vào | File văn bản, mỗi dòng ba trường ngăn bằng dấu phẩy. Tối đa 10⁶ dòng. Điểm từ 0,0 tới 10,0 |
| Ra | Bảng 10 dòng gồm hạng, mã số, họ tên, điểm. Điểm hiện hai chữ số thập phân, các cột căn thẳng |
| Ràng buộc | Bộ nhớ tối đa 256 MB. Mỗi bản ghi khoảng 84 byte nên 10⁶ bản ghi chiếm khoảng 84 MB, vẫn chứa vừa |
| Trường hợp biên | File rỗng. Ít hơn 10 sinh viên. Dòng sai định dạng. Dòng thiếu trường. Điểm ngoài khoảng hợp lệ. Mã số trùng nhau. Điểm bằng nhau ở vị trí thứ 10 |
| Thuật toán | Cách A: sắp xếp toàn bộ rồi lấy 10 đầu, O(n log n). Cách B: dùng đống nhỏ nhất kích thước 10, O(n log 10) tức O(n). Chọn cách B |
| Cấu trúc dữ liệu | Một struct cho bản ghi, một đống nhỏ nhất cố định 10 phần tử |
| Xử lý lỗi | Không mở được file thì báo ra luồng lỗi chuẩn rồi thoát với mã khác 0. Dòng sai định dạng thì cảnh báo, bỏ qua, và đếm số dòng đã bỏ |
Mã giả tương ứng
HÀM top_10(ten_file)
NẾU không mở được ten_file THÌ
BÁO LỖI và THOÁT
HẾT NẾU
dong_loi ← 0
dong ← đống nhỏ nhất rỗng, sức chứa 10
VỚI MỖI dong_van_ban TRONG file LÀM
NẾU không tách được thành ba trường THÌ
dong_loi ← dong_loi + 1
BỎ QUA dòng này
HẾT NẾU
NẾU điểm nằm ngoài khoảng 0 đến 10 THÌ
dong_loi ← dong_loi + 1
BỎ QUA dòng này
HẾT NẾU
NẾU đống chưa đủ 10 phần tử THÌ
THÊM bản ghi vào đống
NGƯỢC LẠI NẾU điểm > điểm nhỏ nhất trong đống THÌ
BỎ phần tử nhỏ nhất
THÊM bản ghi vào đống
HẾT NẾU
HẾT VỚI
SẮP XẾP đống giảm dần theo điểm
IN bảng kết quả
NẾU dong_loi > 0 THÌ CẢNH BÁO số dòng đã bỏ qua
HẾT HÀMĐống nhỏ nhất sẽ được học ở Chương 23. Ở đây bạn chỉ cần thấy: khi bảng phân tích chỉ ra rằng chỉ cần 10 kết quả trong một triệu bản ghi, nó dẫn thẳng tới lựa chọn cấu trúc dữ liệu phù hợp.
#Chọn cấu trúc dữ liệu
Bảng phân tích không chỉ chọn thuật toán, nó còn chọn cả cấu trúc dữ liệu. Bảng dưới đây là bản rút gọn để dùng ngay, còn chi tiết đầy đủ nằm ở Phần 10.
| Nhu cầu chính | Nên dùng | Học ở |
|---|---|---|
| Truy cập theo chỉ số, kích thước biết trước | Mảng | Chương 9 |
| Kích thước thay đổi lúc chạy | Mảng động | Chương 14 |
| Thêm và xóa ở đầu rất nhiều | Danh sách liên kết | Chương 21 |
| Vào sau ra trước | Ngăn xếp | Chương 22 |
| Vào trước ra trước | Hàng đợi | Chương 23 |
| Luôn lấy phần tử lớn nhất hoặc nhỏ nhất | Đống | Chương 23 |
| Tra cứu theo khóa rất nhanh | Bảng băm | Chương 25 |
| Tra cứu theo khóa và cần thứ tự | Cây tìm kiếm nhị phân | Chương 24 |
Quy trình rút gọn để dùng hằng ngày
1. Vào là gì? kiểu, miền, kích thước tối đa
2. Ra là gì? định dạng, làm tròn
3. Biên nào? n=0, n=1, trùng nhau, âm, tràn
4. Ràng buộc? thời gian và bộ nhớ -> suy ra độ phức tạp cho phép
5. Dữ liệu sai thì sao? bỏ qua, báo lỗi, hay dừng hẳn
Rồi mới: nghĩ hai hướng giải -> chọn -> viết mã giả -> cài đặt -> kiểm thử#Tổng kết Phần 2
Bạn vừa hoàn thành Phần 2. Đây là những gì đã tích lũy qua hai chương.
- Chương 6: ba loại vòng lặp và khi nào dùng cái nào, ba thành phần bắt buộc, bảy nguyên nhân chạy vô hạn, bốn công cụ điều khiển, và một bài học về bộ nhớ đệm mà nhiều người học C nhiều năm vẫn không biết.
- Chương 7: quy trình sáu bước, năm tính chất của thuật toán, mã giả, lưu đồ, Big-O kèm bảng quy đổi ra thời gian thật, và bảng phân tích bài toán.
Phần 3 sẽ vào hàm: cách chia chương trình thành các khối độc lập, khung ngăn xếp thật sự hoạt động ra sao, và đệ quy. Đó là bước chuẩn bị trực tiếp cho Phần 5 về con trỏ, chặng khó nhất của cả khóa học.
Tự làm thử
- Lập bảng phân tích đầy đủ cho bài toán: tìm số xuất hiện nhiều nhất trong mảng 10⁷ phần tử, biết giá trị nằm trong khoảng 0 tới 1000.
- Lập bảng phân tích cho bài toán kiểm tra chuỗi ngoặc hợp lệ với ba loại ngoặc.
- Lập bảng phân tích cho bài toán tìm đường đi ngắn nhất trong mê cung 1000 nhân 1000.
- Lập bảng phân tích cho bài toán gộp hai file đã sắp xếp thành một file sắp xếp, biết mỗi file 10 GB còn bộ nhớ chỉ 1 GB. Chú ý câu hỏi số 4.
- Cài đặt trọn vẹn bài toán top 10 sinh viên, dùng mảng thay cho đống trước, đo thời gian với file một triệu dòng.
- Lấy một bài tập bất kỳ bạn đã làm ở Phần 1, lập bảng phân tích cho nó, và xem có trường hợp biên nào bạn đã bỏ sót.
Trình chấm điểm tự động sẽ được bổ sung ở giai đoạn sau. Hiện tại bạn tự chạy thử trên máy.
Tóm tắt
- Mô hình vào xử lý ra tách ba nhóm lỗi khác nhau, giúp khoanh vùng nhanh khi chương trình sai.
- Năm câu hỏi bắt buộc: vào là gì, ra là gì, biên nào, ràng buộc gì, dữ liệu sai thì sao.
- Ràng buộc thời gian quyết định độ phức tạp cho phép, và độ phức tạp quyết định thuật toán.
- Bảng phân tích nên ghi ít nhất hai hướng giải rồi mới chọn một.
- Bảng phân tích cũng dẫn tới việc chọn cấu trúc dữ liệu phù hợp.
- Với n nhỏ, mảng đơn giản thường thắng mọi cấu trúc tinh vi nhờ bộ nhớ đệm.