2 Đặc trưng trong chương trình cần tối ưu
Tối ưu hóa thời gian thực hiện chương trình
Tối ưu hóa không gian lưu trữ dữ liệu
2 Loại tối ưu
Tối ưu chương trình không làm thay đổi thuật toán (Chỉnh sửa mã chương trình)
Tối ưu chương trình làm thay đổi thuật toán
47 trang |
Chia sẻ: lylyngoc | Lượt xem: 1661 | Lượt tải: 0
Bạn đang xem trước 20 trang tài liệu Chương 10 Tối ưu hóa chương trình, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
Click to edit Master text styles Second level Third level Fourth level Fifth level Click to editMaster title style ‹#› TỐI ƯU HÓA CHƯƠNG TRÌNH Chương 10 Tối ưu hóa chương trình 2 Đặc trưng trong chương trình cần tối ưu Tối ưu hóa thời gian thực hiện chương trình Tối ưu hóa không gian lưu trữ dữ liệu 2 Loại tối ưu Tối ưu chương trình không làm thay đổi thuật toán (Chỉnh sửa mã chương trình) Tối ưu chương trình làm thay đổi thuật toán TỐI ƯU HÓA THỜI GIANCHỈNH SỬA MÃ CHƯƠNG TRÌNH Chỉnh sửa mã chương trình Các cách chỉnh sửa mã chương trình Quy tắc Vòng lặp Quy tắc Logic Quy tắc Hàm Quy tắc Biểu thức QUY TẮC VÒNG LẶP Tốu ưu câu lệnh lặp Quy tắc vòng lặp 1: Đưa code ra ngoài vòng lặp Đưa các tính toán không phụ thuộc vào chỉ số lặp ra khỏi vòng lặp Các biểu thức tính toán nếu đều được tính toán giống nhau qua các lần lặp thì nên được để ngoài vòng lặp Chú ý những biểu thức chứa những phép toán tốn nhiều thời gian: *, /, hàm mũ, lấy căn, ... Tốu ưu câu lệnh lặp for (i=0; i value) { found = 0; break; }} Tốu ưu câu lệnh lặp Cải tiến Tốu ưu câu lệnh lặp Quy tắc vòng lặp 3: Tháo bỏ vòng lặp – Do chi phí thay đổi chỉ số lớn: Trong vòng lặp ngắn hay thân vòng lặp ít code thì chi phí lớn thường nằm trong các lệnh thay đổi chỉ số. Chi phí thay đổi chỉ số vòng lặp thường được giảm bằng cách Bỏ vòng lặp Giảm số lần lặp, tăng số lệnh trong thân vòng lặp Tốu ưu câu lệnh lặp sum=0;for (i=0; iMAXFIBO) return 0; if (n a[i]) min = a[i]; for (i=1; i0 trong vòng lặp chúng ta sẽ kiểm tra X!=0 Thay vì kiểm tra sqrt(X)>sqrt(Y) trong vòng lặp chúng ta sẽ kiểm tra X>Y Quy tắc logic Quy tắc logic 2: Dùng hàm có chu kỳ ngắn Nếu chúng ta muốn kiểm tra một hàm không giảm với một ngưỡng nào đó thì chúng ta không cần phải tính toán hàm tiếp nếu ngưỡng đã đạt đến Ví dụ: sum=0; for (i=0; i threshold) Quy tắc logic Cải tiến sum=0;i=0; while (i threshold) Quy tắc logic Cải tiến sum=0;i=0;if (n%2==1){ i=1; sum=x[0];} while (i threshold) Tối ưu biểu thức logic Quy tắc logic 3: sắp xếp lại các biểu thức kiểm tra Phép toán logic AND: Biểu thức có khả năng sai nhiều nhất được sắp trước: if (A1 && A2 && … && An){ …} Tối ưu biểu thức logic Quy tắc logic 3: sắp xếp lại các biểu thức kiểm tra Phép toán logic OR: Biểu thức có khả năng đúng nhiều nhất được sắp trước: if (A1 || A2 || … || An){ …} TỐI ƯU HÓA THỜI GIANTHAY ĐỔI THUẬT TOÁN THAY ĐỔI THUẬT TOÁN Dùng phương pháp Chia để trị Dùng phương pháp Quy hoạch động – Bảng tra (lookup table) Tận dụng các công thức Dùng phương pháp Chia để trị Dùng phương pháp Chia để trị Khi chia được bài toán thành các bài toán con giống nhau Chúng ta chỉ cần giải 1 bài toán con Dùng kết quả này cho các bài toán con giống nhau mà không cần giải lại Dùng phương pháp Chia để trị Ví dụ: Tính an Tìm max/min của dãy số nguyên Tìm số nhỏ thức k trong mảng nguyên Tìm kiếm nhị phân Quicksort Dùng phương pháp Quy hoạch động – Bảng tra (lookup table) Dùng phương pháp Quy hoạch động – Bảng tra (lookup table) Những giá trị được dùng nhiều lần, chúng ta chỉ cần tính 1 lần rồi lưu lại trong 1 bảng (gọi là bảng lookup) Khi cần giải lại bài toán đã giải chúng ta chỉ tra trong bảng lookup Dùng phương pháp Quy hoạch động – Bảng tra (lookup table) Ví dụ: Tính Cách 1: Cách thông thường Tính k! Tính tổ hợp: Gọi tính giai thừa Tính các Dùng phương pháp Quy hoạch động – Bảng tra (lookup table) Cách 2: Dùng bảng lookup Dùng bảng (n+1) phần tử a[0], a[1], ..., a[n] để tính và lưu a[i]=i! Cải tiến Tận dụng các công thức Sử dụng các công thức thay cho vòng lặp Tính toán trên giấy trước khi lập trình Tìm mối quan hệ giữa bước tính trước và bước tính sau Tận dụng các công thức Ví dụ: Tính tổng S sau: int TinhTong(int n) { int s; s=0; int i; for (i=1; i<=n; i++) s = s + i; return s; } int TinhTong(int n) { int s; s = n*(n+1)/2; return s; } Tận dụng các công thức Ví dụ: Viết chương trình tính các biểu thức sau: Tận dụng các công thức Ví dụ: Viết chương trình tính tổng Cách 1: Cách thông thường Chia nhỏ vấn đề, cài đặt các hàm cho từng vấn đề Tính xk Tính k! Tận dụng các công thức Cách 2: Tìm mối quan hệ giữa bước tính trước và bước tính sau Cải tiến Tận dụng các công thức Ví dụ: Tính Cách 1: Cách thông thường Tính k! Tính tổ hợp: Gọi tính giai thừa Tính các Tận dụng các công thức Cách 2: Dùng bảng lookup Dùng bảng (n+1) phần tử a[0], a[1], ..., a[n] để tính và lưu a[i]=i! Cải tiến Tận dụng các công thức Cách 3: Dùng quy nạp Cải tiến Tận dụng các công thức Cách 4: Tìm mối quan hệ giữa bước tính trước và bước tính sau Cải tiến Tận dụng các công thức Cách 5: Hạ xuống phân nửa cho mỗi cách (2), (3), (4) do tính đối xứng Cải tiến Chỉ cần tính với k=1, 2,..., [n/2] Tận dụng các công thức Ví dụ: Kiểm tra n có là số nguyên tố không Cách 1: Dựa vào định nghĩa số nguyên tố Kiểm n có chia hết cho các số từ 2n-1 không Cách 2: Nhận xét các ước số của n chỉ nằm trong [2...n/2] Kiểm tra n có chia hết cho các số từ 2n/2 không Tận dụng các công thức Cách 3: Nhận xét nếu n không nguyên tố thì sẽ tồn tại ước số nguyên tố thuộc [2...sqrt(n)] Nếu n<2 thì n không là số nguyên tố Nếu n=2 thì n là số nguyên tố Kiểm tra n có là số chẵn không Kiểm tra n có chia hết cho các số từ 3sqrt(n) không: 3,5,7, ..., sqrt(n)