Cách tính độ phức tạp của một số giải thuật đơn giản. Show QUY TẮC XÁC ĐỊNH ĐỘ PHỨC TẠP • Độ phức tạp tính toán của giải thuật: O(f(n)) • Việc xác định độ phức tạp tính toán của giải thuật trong thực tế có thể tính bằng một số quy tắc đơn giản sau: – Quy tắc bỏ hằng số: T(n) = O(c.f(n)) = O(f(n)) với c là một hằng số dương – Quy tắc lấy max: T(n) = O(f(n)+ g(n)) = O(max(f(n), g(n))) – Quy tắc cộng: T1(n) = O(f(n)) T2(n) = O(g(n)) T1(n) + T2(n) = O(f(n) + g(n)) – Quy tắc nhân: Đoạn chương trình có thời gian thực hiện T(n)=O(f(n)) Nếu thực hiện k(n) lần đoạn chương trình với k(n) = O(g(n)) thì độ phức tạp sẽ là O(g(n).f(n)) PHÉP TOÁN TÍCH CỰC (BEST PROXY) • Trong một thuật toán, ta chú ý đặc biệt đến một phép toán gọi là phép toán tích cực. Đó là phép toán mà số lần thực hiện không ít hơn các phép toán khác • Ví dụ 1: s = 0; for (i=0; i<=n;i++){ p =1; for (j=1;j<=i;j++) p=p * x / j; s = s+p; } Phép toán tích cực là p = p * x / j Số lần thực hiện phép toán này là 0+1+2+…+n = n(n-1)/2 = n2/2 – n/2 \=> Vậy độ phức tạp là O(n2/2 – n/2) \= O(n2/2) sử dụng quy tắc lấy max \= O(n2) sử dụng quy tắc bỏ hằng số • Ví dụ 2: s = 1; p = 1; for (i=1;i<=n;i++) { p = p * x / i; s = s + p; } Phép toán tích cực là p = p * x / i Số lần thực hiện phép toán là n \=> Vậy độ phức tạp của thuật toán là O(n) • Ví dụ 3: s=n*(n-1) /2; \=> Độ phức tạp của thuật toán là O(1), nghĩa là thời gian tính toán không phụ thuộc vào n • Ví dụ 4: Thuật toán tính tổng các số từ 1 đến n s=0; for (i= 1;i<=n;i++) s=s+i; Vòng lặp lặp n lần phép gán s = s+i, nên thời gian tính toán tỉ lệ thuận với n, tức độ phức tạp là O(n). Đối với một người làm về khoa học máy tính, thuật toán chắc chắn phải là một trong những khái niệm đầu tiên phải học. Vậy thì thuật toán là gi? Một thuật toán là một quá trình để thực hiện một task, thuật toán là ý tưởng bên trong của bất kì chương trình máy tính nghiêm chỉnh nào. Ta có thể nói một thuật toán thì sẽ phải giải quyết một vấn đề nào đó và để giải quyết một vấn đề có thể có nhiều thuật toán khác nhau. Ví dụ: Vấn đề sắp xếp:
Để giải quyết vấn đề sắp xếp ta có các thuật toán sắp xếp: merge sort, quick sort, insertion sort, selection sort, … 2. Phân tích thuật toánCó nhiều thuật toán để giải quyết một vấn đề. Vì vậy sẽ nảy sinh vấn đề làm sao để lựa chọn thuật toán nào cho vấn đề nào. Để giải quyết vấn đề đó chúng ta sẽ phải phân tích thuật toán. Có hai công cụ quan trọng để đánh giá thuật toán: mô hình RAM, Big-O 2.1. Mô hình RAM
Hiển nhiên chúng ta có thể thấy các điều kiện ở trên chỉ có tính tương đối và không đúng với thực tiễn. Nhưng khi áp dụng mô hình RAM nó lại khiến cho việc phân tích thuật toán trở nên đơn giản và hiệu quả. 2.1.1 Độ phức tạp theo thời gianKhi áp dụng mô hình trên người ta thường sẽ để ý đến các trường hợp:
Trường hợp tệ nhất đóng vai trò quan trọng trong thực tiễn và thường ta chỉ quan tâm đến nó mà bỏ qua hai trường hợp còn lại. 2.1.2 Cách xác định độ phức tạp theo thời gianĐộ phức tạp theo thời gian dùng để ước lượng thời gian cần thiết để thực thi giải thuật và được tính toán dựa vào số bước thực hiện các thao tác cơ bản. Ví dụ: Hãy xác định thời gian thiện hiện thuật toán dưới đây
Câu trả lời chính xác tuỳ thuộc vào nhiều yếu tố như là giá trị đầu vào, ngôn ngữ lập trình và môi trường thực thi, trình biên dịch, hệ điều hành và phần cứng, … Vì vậy chúng ta thường chỉ muốn ước lượng thời gian thực thi thuật toán tương đối chỉ dựa vào thuật toán và giá trị đầu vào. Điều này có thể được thực hiện bằng cách chọn một thao tác cơ bản mà thuật toán lặp lại nhiều lần và tính toán độ phức tạp thời gian như là số thao tác cơ bản cần để thực hiện thuật toán với input array có độ dài n Đối với thuật toán ở trên ta có thể chọn thao tác so sánh a[i] > max làm thao tác cơ bản.
2.1.2.1. Độ phức tạp thời gian tệ nhất (worst-case)Xem xét thuật toán dưới này:
Phép toán so sánh x == a[i] có thể được dùng làm phép toán cơ bản trong trường hợp này. Tuy nhiên như chúng ta thấy trong trường hợp này số lượng phép toán so sánh được thực hiện không chỉ phụ thuộc vào số lượng phần tử array n mà còn phụ thộc vào giá trị của x và giá trị của các phần tử trong a.
Vì lý do này mà thông thường ta sẽ chọn xác định trường hợp thời gian tệ nhất của thuật toán:
Vì vậy độ phức thời gian trong trường hợp tệ nhất sẽ là n 2.1.2.2 Độ phức tạp thời gian trung bình (average-case)Độ phức tạp thời gian trung bình thì ít phổ biến hơn, có thể được định nghĩa là số bước trung bình cần thiết để thực hiện thuật toán.
Độ phức tạp thời gian trung bình khó để tính toán và ý nghĩa của nó là chủ đề gây tranh cãi. 2.2. Big-ONhư ở trên ta có nói thời gian thực thi của một thuật toán phụ thuộc vào nhiều yếu tố và khó để xác định chính xác nó. Vì vậy khi nói đến việc tính toán thời gian thực thi của thuật toán đó chính là thời gian ước lượng, việc này thì thực ra không gây ra vấn đề gì. Bởi vì trong khoa học máy tính thứ được quan tâm nhiều hơn đối với một thuật toán là thời gian thực thi của nó sẽ tăng nhanh như thế nào khi số lượng phần tử đầu vào thay đổi. Từ đó khái niệm Big-O được ra đời. Và sau đây là một định nghĩa toán học của Big-O Cho T(n) và f(n) là hai hàm số dương. Ta viết T(n) = O(f(n)) có nghĩa rằng c . f(n) là cận trên của T(n). Vì vậy tồn tại một hằng số c sao cho T(n) luôn luôn <= c . f(n) với một số n đủ lớn (n >= n0) Hay nói một cách dễ hiểu hơn: T(n) = O(f(n)) có nghĩa là T(n) không tăng nhanh hơn f(n). Lưu ý: Ngoài Big-O, còn có hai khái niệm khác Big Omega(Ω) và Big Thelta(Θ):
2.2.1. Giới thiệu về một số hàm số tăng cơ bản2.2.1.1 Hàm số hằngĐây là trường hợp đơn giản và lý tưởng nhất cho mọi thuật toán T(n) = O(1). Theo như định nghĩa có nghĩa là sẽ tồn tại một giá trị n đủ lớn n >= n0 sao cho T(n) luôn luôn nhỏ hơn một giá trị cố định không phụ thuộc vào n. 2.2.1.2. Hàm số tuyến tínhĐây là trường hợp thuật toán có độ phức tạp theo thời gian T(n) = O(n). Áp dụng định nghĩa của Big-O, điều này có nghĩa là tồn tại một số n đủ lớn n0 sao cho thời gian thực thi của thuật toán luôn nhỏ hơn n 2.2.1.3 Hàm số mũĐây là trường hợp thuật toán có độ phức tạp theo thời gian T(n) = O(n2). Một lần nữa áp dụng định nghĩa, điều này có nghĩa là tồn tại một số n đủ lớn sao cho thời gian thực thi của thuật toán luôn nhỏ hơn n2. |