BÀI GIẢNG: PHÂN TÍCH VÀ THIẾT KẾ GIẢI THUẬT

71 0 0
Tài liệu đã được kiểm tra trùng lặp
BÀI GIẢNG: PHÂN TÍCH VÀ THIẾT KẾ GIẢI THUẬT

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

Công Nghệ Thông Tin, it, phầm mềm, website, web, mobile app, trí tuệ nhân tạo, blockchain, AI, machine learning - Công Nghệ Thông Tin, it, phầm mềm, website, web, mobile app, trí tuệ nhân tạo, blockchain, AI, machine learning - Lập trình Bài giảng: Phân tích và thiết kế giải thuật GV: Hồ Hữu Linh Page 1 UBND TỈNH QUẢNG NAM TRƯỜNG ĐẠI HỌC QUẢNG NAM KHOA: CÔNG NGHỆ THÔNG TIN ---------- BÀI GIẢNG PHÂN TÍCH VÀ THIẾT KẾ THUẬT TOÁN Họ và tên giảng viên: Hồ Hữu Linh Quảng Nam, 122018 Bài giảng: Phân tích và thiết kế giải thuật GV: Hồ Hữu Linh Page 2 LỜI NÓI ĐẦU Lập trình là một trong nhưng bước quan trọng nhất trong quy trình giải quyết một bài toán. Nhiều ngôn ngữ lập trình đã được ra đời nhằm giúp chúng ta giải quyết các bài toán một cách hiệu quả nhất. Mỗi ngôn ngữ lập trình có những thế mạnh và nhược điểm riêng. Các ngôn ngữ lập trình thể chia ra thành hai loại chính là ngôn ngữ lập trình bậc thấp (gần gũi với ngôn ngữ máy), và ngôn ngữ lập trình bậc cao (gần gũi với ngôn ngữ tự nhiên của con người). Trong quá trình học tập, chúng ta gặp rất nhiều các bài tập về Toán-Tin. Các bài tập rất phong phú và đa dạng. Thực tế chưa có thuật toán hoàn chỉnh có thể áp dụng cho mọi bài toán. Tuy nhiên người ta đã tìm ra một số thuật toán chung như chia để trị, tham lam, quay lui,... Các thuật toán này có thể áp dụng để giải một lớp khá rộng các bài toán hay gặp trong thực tế. Trong bài giảng này, tôi muốn đề cập với các bạn một số thuật toán như Đệ quy, Tham lam, Quy hoạch động và một số thuật toán Đồ thị,.. nhằm giúp các bạn giải ó cái nhìn tổng quan cho từng loại bài toán. Bài giảng: Phân tích và thiết kế giải thuật GV: Hồ Hữu Linh Page 3 TỔNG QUAN VỀ THUẬT TOÁN (Đọc thêm) 1. Khái niệm về thuật toán Thuật toán là một bảng liệt kê các chỉ dẫn (hay quy tắc) cần thực hiện theo từng bước xác định nhằm giải bài toán đã cho. Thuật ngữ “Algorithm” (thuật toán) là xuất phát từ tên nhà toán học Ả Rập Al-Khowarizmi. Ban đầu, từ algorism được dùng để chỉ các quy tắc thực hiện các phép tính số học trên các số thập phân. Sau đó, algorism chuyển thành algorithm vào thế kỷ 19. Với sự quan tâm ngày càng tăng đối với các máy tính, khái niệm thuật toán đã được cho một ý nghĩa chung hơn, bao hàm cả các thủ tục xác định để giải các bài toán, chứ không phải chỉ là thủ tục để thực hiện các phép tính số học. Có nhiều cách trình bày thuật toán: dùng ngôn ngữ tự nhiên, ngôn ngữ lưu đồ (sơ đồ khối), ngôn ngữ lập trình. Tuy nhiên, một khi dùng ngôn ngữ lập trình thì chỉ những lệnh được phép trong ngôn ngữ đó mới có thể dùng được và điều này thường làm cho sự mô tả các thuật toán trở nên rối rắm và khó hiểu. Hơn nữa, vì nhiều ngôn ngữ lập trình đều được dùng rộng rãi, nên chọn một ngôn ngữ đặc biệt nào đó là điều người ta không muốn. Vì vậy ở đây các thuật toán ngoài việc được trình bày bằng ngôn ngữ tự nhiên cùng với những ký hiệu toán học quen thuộc còn dùng một dạng giả mã để mô tả thuật toán. Giả mã tạo ra bước trung gian giữa sự mô tả một thuật toán bằng ngôn ngữ thông thường và sự thực hiện thuật toán đó trong ngôn ngữ lập trình. Các bước của thuật toán được chỉ rõ bằng cách dùng các lệnh giống như trong các ngôn ngữ lập trình. 2. Các đặc trưng của thuật toán - Đầu vào (Input): Một thuật toán có các giá trị đầu vào từ một tập đã được chỉ rõ. - Đầu ra (Output): Từ mỗi tập các giá trị đầu vào, thuật toán sẽ tạo ra các giá trị đầu ra. Các giá trị đầu ra chính là nghiệm của bài toán. Bài giảng: Phân tích và thiết kế giải thuật GV: Hồ Hữu Linh Page 4 - Tính dừng: Sau một số hữu hạn bước thuật toán phải dừng. - Tính xác định: Ở mỗi bước, các bước thao tác phải hết sức rõ ràng, không gây nên sự nhập nhằng. Nói rõ hơn, trong cùng một điều kiện hai bộ xử lý cùng thực hiện một bước của thuật toán phải cho những kết quả như nhau. - Tính hiệu quả: Trước hết thuật toán cần đúng đắn, nghĩa là sau khi đưa dữ liệu vào thuật toán hoạt động và đưa ra kết quả như ý muốn. - Tính phổ dụng: Thuật toán có thể giải bất kỳ một bài toán nào trong lớp các bài toán. Cụ thể là thuật toán có thể có các đầu vào là các bộ dữ liệu khác nhau trong một miền xác định. 3. Tầm quan trọng của thuật toán Mục đích của việc nghiên cứu cấu trúc dữ liệu và giải thuật chính là để xây dựng các chương trình hiệu quả. Tiêu chuẩn 2 chính là tính hiệu quả của thuật giải. Một thuật giải được gọi là hiệu quả nếu nó tiết kiệm được không gian và thời gian. Tiết kiệm không gian là chiếm dụng ít bộ nhớ trong thời gian thực hiện. Tiết kiệm thời gian là chạy nhanh. Tiêu chuẩn thời gian thực hiện nhanh là quan trọng hàng đầu. Đánh giá độ phức tạp của thuật giải là đánh giá thời gian thực hiện nó. Bài toán không không phải là bài toán chưa có lời giải mà là bài toán mà việc giải nó mất một khoảng thời gian quá dài, đến mức không chấp nhận được. 4. Phân tích độ phức tạp của thuật toán Thước đo hiệu quả của một thuật toán là thời gian mà máy tính sử dụng để giải bài toán theo thuật toán đang xét, khi các giá trị đầu vào có một kích thước xác định. Một thước đo thứ hai là dung lượng bộ nhớ đòi hỏi để thực hiện thuật toán khi các giá trị đầu vào có kích thước xác định. Các vấn đề như thế liên quan đến độ phức tạp tính toán của một thuật toán. Sự phân tích thời gian cần thiết để giải một bài toán có kích thước đặc biệt nào đó liên quan đến độ phức tạp thời gian của thuật toán. Sự phân tích bộ nhớ cần thiết của máy tính liên quan đến độ phức tạp không gian của thuật toán. Vệc xem xét độ phức tạp thời gian và không gian của một thuật Bài giảng: Phân tích và thiết kế giải thuật GV: Hồ Hữu Linh Page 5 toán là một vấn đề rất thiết yếu khi các thuật toán được thực hiện. Biết một thuật toán sẽ đưa ra đáp số trong một micro giây, trong một phút hoặc trong một tỉ năm, hiển nhiên là hết sức quan trọng. Tương tự như vậy, dung lượng bộ nhớ đòi hỏi phải là khả dụng để giải một bài toán,vì vậy độ phức tạp không gian cũng cần phải tính đến.Vì việc xem xét độ phức tạp không gian gắn liền với các cấu trúc dữ liệu đặc biệt được dùng để thực hiện thuật toán nên ở đây ta sẽ tập trung xem xét độ phức tạp thời gian. Độ phức tạp thời gian của một thuật toán có thể được biểu diễn qua số các phép toán được dùng bởi thuật toán đó khi các giá trị đầu vào có một kích thước xác định. Sở dĩ độ phức tạp thời gian được mô tả thông qua số các phép toán đòi hỏi thay vì thời gian thực của máy tính là bởi vì các máy tính khác nhau thực hiện các phép tính sơ cấp trong những khoảng thời gian khác nhau. Hơn nữa, phân tích tất cả các phép toán thành các phép tính bit sơ cấp mà máy tính sử dụng là điều rất phức tạp. Bài giảng: Phân tích và thiết kế giải thuật GV: Hồ Hữu Linh Page 6 Chương 1. Đệ qui 1. Đệ qui và truy hồi hồi a. đệ qui: bài toán đệ qui là bài toán được chia làm 2 phần: + phần cơ sở(suy biến): cho giá trị xác định + phần đệ qui: gọi lại bài toán ở mức thấp hơn. Ví dụ 1: Giai thừa của n (n): +Nếu n=0 thì n=1; phần cơ sở +nếu n>0 thì n= n.(n-1) phần đệ qui Ví dụ 2: dãy số fibonaci được định nghĩa như sau: F(n)= 1 khi n=1 hoặc n =2; phần cơ sở F(n)= f(n-1) +f(n-2) khi n>2; phần suy biến Tổng quan cách cài đặt: f(n); bài toán có kích thước n { If Return ; Else Return ; } b. truy hồi nghiệm: Như đã nói ở bài trước thì trong kỹ thuật đệ quy, phần khó nhất là tìm ra công thức truy hồi hay tổng quát hoá vấn đề. Muốn dùng kỹ thuật đệ quy, phải tư duy theo kiểu đệ quy. Mong loạt bài luyện tập đệ quy có thể giúp bạn có cái nhìn tổng quát về hướng tiếp cận với một bài toán theo kiểu đệ quy. Khi giải một bài toán bằng đệ quy, thông thường mình sẽ thử viết ra kết quả đối với những trường hợp đơn giản, sau đó cố gắng rút ra công thức tổng quát. Sẽ không có Bài giảng: Phân tích và thiết kế giải thuật GV: Hồ Hữu Linh Page 7 một phương pháp chung để có thể học tốt đệ quy, vì nó còn dựa vào yếu tố kinh nghiệm, làm nhiều bạn sẽ quen với tư duy kiểu đệ quy. Ví dụ 1: Tính S = 1 + 2 + 3 + … + n Dễ dàng tìm được công thức tổng quát cho bài này là: S(0) = 0 S(n) = S(n-1) + n Ví dụ 2: Tính xn Công thức này học sinh lớp 7 nào cũng phải biết  x0 = 1  xn = x xn-1 ví dụ 3: Tìm UCLN(a, b) Ta có thể dùng công thức Euclid như sau:  UCLN(a, b) = b nếu a chia hết cho b.  Ngược lại: UCLN(a, b) = UCLN(b, a mod b) Với công thức này thì điểm dừng của đệ quy là trường hợp a chia hết cho b. 3 bài trên quá dễ vì đã có sẵn công thức truy hồi. Ví dụ 4: Tính (n dấu căn) Ta tính thử một vài trường hợp đơn giản và cố gắng suy ra liên hệ đối với trường hợp trước đó.  n = 1 (1 dấu căn):  n = 2 (2 dấu căn):  n = 3 (3 dấu căn): Đến đây, ta có thể suy đoán rằng: . Sau khi suy đoán được, hãy thử kiểm tra bằng cách tình thử một vài trường hợp nữa bằng công thức vừa tìm được nhé. Bài giảng: Phân tích và thiết kế giải thuật GV: Hồ Hữu Linh Page 8 Và điểm dừng của công thức này S(1) = 1. Ví dụ 5: Đếm số lượng chữ số của một số nguyên n. Trước khi chưa biết đệ quy, ta thường làm cách dùng vòng lặp, dùng một biến đếm lưu kết quả, mỗi lần lặp tăng biến đếm lên và chia n cho 10, lặp cho đến khi n bằng 0. Nếu tư duy theo kiểu đệ quy sẽ đơn giản hơn rất nhiều. Giả sử có số nguyên dương , ta đếm số lượng chữ số bằng cách: đếm số lượng của số nguyên rồi cộng thêm 1 (ứng với chữ số ). Và trường hợp cơ bản là nếu n < 10 thì có 1 chữ số. 1 2 3 4 5 6 7 int DemSoLuongChuSo(int n) { if (n < 10) return 1; else return DemSoLuongChuSo(n 10) + 1; } Vậy số nguyên âm thì sao ? Đơn giản ta chỉ cần đếm số đối của nó, hàm được cài đặt hoàn thiện như sau: 1 2 3 4 5 6 7 8 9 int DemSoLuongChuSo(int n) { if (n < 0) return DemSoLuongChuSo(-n); else if (n < 10) return 1; else return DemSoLuongChuSo(n 10) + 1; } 2. phân tích độ phức tạp giải thuật: Bài giảng: Phân tích và thiết kế giải thuật GV: Hồ Hữu Linh Page 9 Tham khảo ở phần đọc thêm 3. giải thuật lặp ( khử đệ qui): Một cách tổng quát người ta chỉ ra rằng: Mọi giải thuật đệ quy đều có thể thay thế bằng một giải thuật không đệ quy. Vấn đề còn gọi là kỹ thuật xây dựng lại giải thuật không đệ quy tương ứng thay thế giải thuật đệ quy. Công việc xây dựng lại một giải thuật không đệ quy không phải bao giờ cũng đơn giản và cho đến nay vẫn chưa có giải pháp thỏa đáng cho trường hợp tổng quát. Sơ đồ xây dựng chương trình cho một bài toán khó khi ta không tìm được giải thuật không đệ quy thường là: + Dùng quan niệm đệ quy để tìm giải thuật cho bài toán. + Mã hóa giải thuật đệ quy. + Khử đệ quy để có được một chương trình đệ quy. Tuy nhiên, do việc khử đệ quy không phải bao giờ cũng dễ và vì vậy trong nhiều trường hợp ta cũng phải chấp nhận sử dụng chương trình đệ quy. a. Các trường hợp khử đệ quy đơn giản + Sử dụng vòng lặp: Ví dụ 1: Hàm tính giá trị của dữ liệu mô tả bằng hồi quy. Ví dụ: Hàm giai thừa FAC(n) = n = 1 khi n = 0 = nFAC(n – 1) khi n > 0. Cách khử: Hàm tính giai thừa không đệ quy: int FAC ( int n) { int k = 0; int F = 1; while(k < n) F = ++k F; return F; Bài giảng: Phân tích và thiết kế giải thuật GV: Hồ Hữu Linh Page 10 } b. Các ham đệ quy dạng đệ quy đuôi (tail -recusitive). Xét các hàm đệ quy dạng: Tức là: f(X) ≡ if( C(X) ) return ( f (g(X))); else return (a(x)); Đoạn chương trình tính f = f(X0) là: U = X0; While( C(U)) U = g(U); f = a(U); Ví dụ: Với m, n >= 0 ta có hàm đệ quy tính UCLN(m, n) là: UCLN(m ,n ) ≡ if (m = 0 ) return(UCLN ( abs(m – n) , min(m , n) ) ; else return n ; – Dạng hàm đệ quy tương ứng trong C++ int USCLN(int m , int n) { while( n = 0) { int t1 = m ; int t2 = n ; m = abs(t1-t2) ; if(t1 lùi lại bước trước để xác định lại thành phần xi-1. Mô hình quay lui được tổ chức theo đệ quy dưới dạng giả mã như sau: void Duyet(i:Typevar); Typevar j; { For j do Bài giảng: Phân tích và thiết kế giải thuật GV: Hồ Hữu Linh Page 23 If chấp nhận j Then { Ghi nhân trạng thái mới if i=n then thông báo kết quả cho bài toán else Duyet(i+1); Trả lại trạng thái cũ } } Ví dụ1 : hiện thị tất cả những xâu nhị phân có độ dài là n void Duyet(int i); int j; { For (int j=0 j=0 ; j--) { ai=j;{đề cử giá trị j cho xi} s=s+i; {s là tổng nghiệm hiện tại từ 1 đến i} if ((i==n) ( s= =c)) then inkq(); else if ((s

Ngày đăng: 28/05/2024, 17:52