1. Trang chủ
  2. » Giáo Dục - Đào Tạo

Giáo trình Toán rời rạc Chương 2.1

8 759 0
Tài liệu đã được kiểm tra trùng lặp

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

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 8
Dung lượng 83,5 KB

Nội dung

Giáo trình Toán rời rạc

Chương IICÁC KIẾN THỨC CƠ BẢN.I. Thuật toán:1. Khái niệm thuật toán và đặc trưng của nó:Giả sử nhằm đảm bảo vệ sinh an toàn thực phẩm chúng ta muốn đóng gói kẹo dừa trên một dây chuyền tự động thay cho gói kẹo bằng tay như hiện nay. Để giải quyết bài toán này, chúng ta phải thiết kế và chế tạo ra một thiết bò cơ - điện tử thực hiện các công đoạn từ khâu chiết khối kẹo còn nóng sang thiết bò đóng gói cho đến khâu đưa hộp kẹo ra khỏi băng chuyền. Thiết bò này được điều khiển tự động bằng máy tính và gồm các thao tác:Bước 0: Khởi động việc đếm số viên kẹo (sovienkeo:=0). Qua bước 1.Bước 1: Nhận khối kẹo còn nóng từ chảo nấu. Nếu khối kẹo vừa nhận có trọng lượng khác 0 thì qua bước 2, bằng không qua bước 11.Bước 2: Trọng lượng của khối kẹo khác 0? Đúng: Qua bước 3 – Sai: Qua bước 1.Bước 3: Đùn ép và chia cắt khối kẹo thành viên thích hợp. Qua bước 4Bước 4: Đưa viên kẹo lên khuôn ép đònh hình. Qua bước 5Bước 5: Lấy viên kẹo ra khỏi khuôn ép và đặt lên băng giấy đúng vò trí qui đònh. Qua bước 6.Bước 6: Cắt băng giấy vừa viên kẹo và ép gói theo dạng qui đònh. Qua bước 7.Bước 7: Đẩy ép viên kẹo vào hộp. Qua bước 8.Bước 8: Đếm số viên kẹo đã đặt vào hộp (sovienkeo:=sovienkeo+1). Nếu số viên kẹo còn nhỏ hơn 100 thì trở về bước 2, ngược lại qua bước 9.Bước 9: Đưa hộp kẹo ra khỏi băng chuyền. Qua bước 10:Bước 10: Đặt hộp kẹo rổng vào vò trí cũ. Khởi động lại việc đếm số viên kẹo đã đặt vào hộp. Trở về bước 2.Bước 11: Dừng máy.Qui trình trên cho phép ta/máy thực hiện chính xác, đúng từng bước một công việc đã giao – từ lúc bắt đầu (nhận khối kẹo nóng/khởi tạo biến đếm) đến lúc kết thúc công việc (dừng máy). Một số công đoạn có thể sẽ phải lập đi lập lại nhiều lần. Với mỗi khối kẹo đã nhận qui trình cho ra kết quả rõ ràng là các hộp kẹo. Qui trình trên có qui đònh thứ tự bắt buộc đối với các thao tác. Thứ tự đó không thể thay đổi được. Mỗi công đoạn trong qui trình trên đều có thể thực hiện một cách tương ứng bởi con người (dó nhiên là mất thời gian hơn, nguy hiểm hơn, .).Không phải bài toán nào cũng có thể đưa ra một qui trình giải quyết như vậy. Tuy nhiên ví dụ trên cũng đủ dẫn chúng ta đến với khái niệm:24  Thuật toán: Một giải thuật (hay thuật toán) là một dãy hữu hạn, có thứ tự các chỉ thò nhằm giải quyết một bài toán đảm bảo được 6 tính chất đặc trưng cơ bản sau đây:o Một giải thuật bắt đầu bằng những chỉ thò nhập dữ liệu đầu vào (inputs). Các dữ liệu nhập này sẽ được xử lí bởi những chỉ thò tiếp theo sau của giải thuật.o Các qui tắc xử lí (processing rules) nêu ra trong giải thuật phải chính xác và không mơ hồ sao cho có thể thực hiện được đúng các qui tắc đó.o Mỗi chỉ thò phải đủ căn bản sao cho, về nguyên tắc, có thể hoàn thành bởi con người – và bằng tay – trong hữu hạn thời gian.o Giải thuật phải đủ tổng quát để giải được tất cả các bài toán có dạng như yêu cầu chứ không chỉ cho một tập đặc biêït các giá trò đầu vào.o Tổng thời gian dùng để thực hiện mọi bước của giải thuật phải hữu hạn . Có thể có một số chỉ thò trong các bước giải sẽ được lập đi lập lại nhiều lần nhưng số lần lập phải hữu hạn.o Giải thuật phải cho ra kết quả (outputs). Nói cách khác giải thuật phải có tính dừng.o Các thao tác và cấu trúc điều khiển cơ sở.Để hiện thực được các thuật toán ta cần thiết kế một số thao tác cơ bản cần thiết cho việc thực thi từng bước của thuật toán trên một máy tính giả đònh. Các thao thác căn bản: Tên thao tác Kí hiệu Ý nghóaThao tác nhậpinput(x)Thao tác này cho phép xem x như một biến chờ được nhập dữ liệu từ một thiết bò nhập chuẩn nào đó.Thao tác xuấtoutput(x)Thao tác này cho phép xuất giá trò hiện tại của x ra một thiết bò xuất chuẩn nào đó.Thao tác gán tròx:=yThao tác này được thực hiện từ vế phải qua vế trái nhằm gán giá trò hiện tại của y cho x.Thao tác trả về một giá tròReturn xThao tác này cho phép trả về giá trò hiện tại của x cho một thiết bò nào đó.Các thao tác số học cơ bản hoặc các tác vụ căn bản+ - * div. .Các cấu trúc điều khiển:Để biểu diễn quá trình thực hiện một thuật toán, người ta có thể chỉ mô tả tuần tự các tác vụ của thuật toán kèm theo các chỉ thò so sánh và các lệnh nhảy (jump hoặc goto) là đủ. Chẳng hạn như trong ví dụ trên, ở bước 8 ta có một chỉ thò so sánh 25 (sovienkeo<100 ?) và một lệnh nhảy (Trở về bước 2 | Qua bước 9). Đó là cách mà các ngôn ngữ lập trình cấp thấp như ASSEMBLY (hoặc thậm chí 1985 ANS BASIC –American National Basic) vẫn dùng. Tuy nhiên mô tả thuật toán trong một cấu trúc như vậy làm cho thuật toán trở nên khó đọc, khó hiểu và rất dễ trở nên rối rắm, nhiều nhầm lẫn một khi có quá nhiều lệnh nhảy tới lui trong các bước thực hiện. Để làm cho việc mô tả thuật toán trở nên trong sáng hơn người ta thấy rằng trong mọi trường hợp hoàn toàn có thể thay lệnh nhảy (jmp hoặc goto) bằng (và chỉ cần như vậy là đủ) ba cấu trúc điều khiển sau đây:Cấu trúc tuần tự:Trong cấu trúc điều khiển này các chỉ thò được mô tả thành một dãy tuần tự và được thực thi đúng như theo thứ tự mà chúng được mô tả. Nói cách khác lệnh nhảy đến bước kế tiếp liền kề sau bước đóù là không cần thiết phải nêu ra một cách tường minh. Nếu một dãy tuần tự các chỉ thò được xem như một khối thống nhất phải thực hiện đầy đủ, hoàn tất thì chúng phải được đánh đấu ở đầu khối và ở cuối khối, chẳng hạn bằng một cặp từ khoá begin / end.Cấu trúc lựa chọn: Cấu trúc này có cú pháp như sau: IF <biểu thức lôgic=1> THEN TacVu1 ELSE TacVu2Cấu trúc này buộc trước tiên phải kiểm tra một điều kiện <biểu thức lôgic>. Nếu giá trò của biểu thức này là đúng thì TacVu1 được thực hiện, bằng không TacVu2 sẽ được thực hiện. Cú pháp này cho phép “rẽ nhánh” chương trình, cho phép chỉ TacVu1 hoặc (XOR) TacVu2 được thực hiện tuỳ theo giá trò của <biểu thức lôgic> tại thời điểm chương trình đang được thực thi (in run time).Ví dụ: IF (Sốlượng >0) THEN LàmTiếp ELSE DừngCấu trúc lặp: Cấu trúc này có cú pháp như sau: WHILE <biểu thức lôgic=1> DO TacVuCấu trúc này buộc trước tiên phải kiểm tra một điều kiện <biểu thức lôgic>. Nếu giá trò của biểu thức này là đúng thì TacVu được thực hiện. Sau khi TacVu thực hiện xong thì <biểu thức lôgic> lại được kiểm tra, nếu <biểu thức logic> còn đúng thì TacVu lại được thực hiện, và .v.v. cho đến khi việc kiểm tra <biểu thức logic> cho thấy <biểu thức lôgic> không còn đúng thì chấm dứt lập lại TacVu. Cấu trúc này cho phép “lập lại” TacVu nhiều lần tuỳ theo giá trò của <biểu thức lôgic>. Rõ ràng để đảm bảo tính hữu hạn và tính dừng của chương trình thì trong khi thực hiện TacVu phải có cách làm thay đổi giá trò của <biểu thức lôgic> để chương trình có thể thoát ra khỏi vòng lặp sau một số lần lặp nào đó.26 Ví dụ:I:=2WHILE (I ≤ 5) DOBeginOutput (i2)i:=i+1EndVòng lặp WHILE trong ví dụ này thực hiện khối chỉ thò được bao trong cặp Begin . End bốn lần (đưa ra thiết bò xuất chuẩn các số chính phương 4, 9, 16, 25).o Các hình thức biểu diễn thuật toán.o Lưu đồ thuật toán (flow chart) : Dùng các sơ đồ dòng chảy trong đó kết hợp các đầu nối, các kí hiệu khối tác vụ và các mũi tên để biểu diễn quá trình thực hiện của thuật toán. Các kí hiệu khối tác vụ được qui đònh trong bảng sau:Hình dạng Dùng để Ví dụBiểu diễn tác vụ xử lí của máy tính.Một xử lí được đònh nghóa trướcGọi thường trình xử lí màn hìnhInput; Outputinput (N)Quyết đònh rẽ nhánh So <7Bắt đầu hoặc kết thúc thủ tụcBEGINĐầu nối12Kí hiệu hướng dòng chảy27Tính giai thừa của N Ví dụ về lưu đồ giải phương trình bậc nhất dạng ax+b=0BEGINinput(a,b) a≠0 False b=0 vô nghiệm True x=-b/a vô số nghiệmENDo Mã giả (pseudo code) : Mã giả dùng một số từ khoá, tương tự như các từ khoá dùng trong một ngôn ngữ lập trình nào đó – chẳng hạn ngôn ngữ Pascal – để mô tả quá trình thực hiện giải thuật. Ngoài các từ khoá ứng với các cấu trúc vừa nêu trên các từ khoá tựa–Pascal sẽ dùng trong giáo trình này là:1Procedure Chỉ đònh tên của thủ tục/ giải thuật.FOR i:=giá trò đầu TO giá trò cuối DO Công ViệcLập lại Công Việc mỗi lần i thay đổi giá trò (từ giá trò đầu đến Giá Trò cuối), mỗi lần thực hiện xong Công Việc giá trò i tự động tăng lên một đơn vò.Ví dụ 1: Sau đây là đoạn mã giả tương ứng với lưu đồ giải phương trình dạng ax+b=0 nói trên.Procedure GiaiPhuongTrinhBacNhatinput(a)input(b)IF (a≠0) THEN Output (x= -b/a)ELSE IF (b=0) THEN Output(Phuong trinh co vo so nghiem)ELSE Output(Phuong trinh vo nghiem)Ví dụ 2: Thuật toán tìm phần tử lớn nhất trong một dãy hữu hạn.1 Chú ý rằng mã giả độc lập đối với mọi ngôn ngữ lập trình, do đó không cần tuân thủ cú pháp nghiêm ngặt như của một ngôn ngữ lập trình nào. Mọi chỉ thò nếu cần thiết đều có thể dùng được trong mã giả miễn là mô tả được bản chất thuật toán của bài toán cần giải.28 Procedure TimMax(a1,a2,a3, .,an: các số nguyên){Thuật toán dùng lính canh}Max:=a1{Dùng Max để canh chừng giá trò lớn nhất đang được xem xét}i:=1While (i<=n) doBeginIF (Max<ai) THEN Max:=aii:=i+1EndReturn(Max) Cũng có thể mô tả như sau:Procedure TimMax(a1,a2,a3, .,an: các số nguyên)Max:=a1FOR i:=1 TO n DO IF (Max<ai) THEN Max:=aiReturn(Max) o Bảng quyết đònh (Decision table) : Bảng quyết đònh thường được các nhà phân tích (analyst) và lập trình viên sử dụng như một sơ đồ để mô tả điều gì xảy ra cho hệ thống hoặc cho chương trình khi gặp một dãy trường hợp ứng với nhiều tình huống/chi tiết cần thực hiện khác nhau. Bảng quyết đònh dựa trên logic “IF . THEN”. Bảng quyết đònh chia làm nhiều cột và nhiều dòng. Cột đầu tiên để ghi các trường hợp khác nhau có thể xảy ra, các cột còn lại để ghi các xử lý đối với mỗi tình huống/chi tiết. Ví dụ sau đây sẽ làm rõ ý tưởng đó:Bảng quyết đònh dùng để tính lươngcho các dạng công nhân viên khác nhau:Kiểu nhân viênQui tắc tính lươngLương căn bảnPhụ cấp 50%Phụ cấp 35%Thừa giờThưởngGV biên chế Yes Y No Y YNV biên chế Y N Y N YNV hợp đồng Y N Y N NThanh toán theo bảng lương thángY Y Y N NThanh toán cuối mỗi năm tài khoá N N N Y YMột bảng quyết đònh như vậy ứng với một loạt các cấu trúc IF THEN lồng nhau. Bảng quyết đònh ít cho ta một ý niệm đầy đủ về cấu trúc của giải thuật, tuy nhiên lại cho ta một cái nhìn bao quát, không sót các trường hợp có thể xảy ra.29 o Độ phức tạp của thuật toán:Trong chương I chúng ta đã có nghiên cứu khái niệm thời gian chạy chương trình (hay tốc độ tăng của hàm). Trong nghiên cứu đó chúng ta đã chú ý đến tốc độ thực hiện một chương trình. Một chương trình máy tính là một hiện thực cụ thể của một thuật toán nào đó. Vấn đề đặt ra khi hiện thực thuật toán thành chương trình là thuật toán đó có hiệu quả không? Và hiệu quả được phân tích như thế nào? Nói chung người ta đánh giá tính hiệu quả của thuật toán dựa trên hai tài nguyên quan trọng nhất của máy tính mà thuật toán yêu cầu được cung cấp để thực hiện bài toán:a) Thời gian cần thiết để giải một bài toán có một kích thước input cụ thể: vấn đề này liên quan đến độ phức tạp thời gian của thuật toán.b) Dung lượng bộ nhớ cần thiết để chương trình (thuật toán) có thể “chạy” được: vấn đề này liên quan đến độ phức tạp không gian của thuật toán.Độ phức tạp không gian thường liên quan đến cấu trúc dữ liệu cụ thể dùng để thực hiện thuật toán sẽ được nghiên cứu trong môn Cấu Trúc Dữ Liệu nên không bàn ở đây. Chúng ta chỉ tập trung bàn về vấn đề độ phức tạp thời gian.Độ phức tạp thời gian của một thuật toán có thể đo bằng số lượng phép toán mà thuật toán sử dụng ứng với một qui mô xác đònh của các giá trò đầu vào. Các phép toán này có thể là các phép gán, phép so sánh các số nguyên, các phép cộng, trừ, nhân, chia hoặc bất kì phép tính sơ cấp nào khác. Sở dó ta dùng “số lượng các phép toán” thay thế cho “thời gian thực dùng để chạy chương trình” để đo độ phức tạp thời gian là vì với các máy tính khác nhau có thể có tốc độ xử lí đối với cùng một phép toán là khác nhau.Để làm rõ hơn vấn đề này ta thử xét bài toán tìm kiếm trên một danh sách (hữu hạn) các số nguyên đã được xếp thứ tự:Thuật toán tìm kiếm tuyến tính (vét cạn):Procedure TimKiemTuyenTinh(x: số nguyên ; a1,a2, ., an: các số nguyên)i:=1While (i≤n) and (x≠ai) do i:=i+1If (i≤n) then VitriTimThay := i else VitriTimThay := 0return(VitriTimThay)Thuật toán tìm kiếm nhò phân:Procedure TimKiemNhiPhan(x: số nguyên; a1,a2, ., an: các số nguyên)i:=1j:=nWhile (i<j) dobeginm:=(i+j) div 2if (x>am) then i:=m+1 else j:=mendIf (x=ai) then VitriTimThay := i else VitriTimThay := 0return(VitriTimThay)Trong thuật toán vét cạn ở mỗi bước của vòng lặp ta có hai phép so sánh phải thực hiện – một để xem hết danh sách chưa (i≤n) và một để xem coi tìm gặp chưa (x≠ai). Cuối cùng phải thực hiện thêm một phép so sánh nữa sau khi thực hiện xong vòng 30 lặp. Do đó, nếu tồn tại x=ai thì phải dùng đến 2i+1 phép so sánh. Trong trường hợp xấu nhất là x=an hoặc không tìm thấy sau khi đã duyệt hết danh sách thì số phép so sánh phải thực hiện là 2n+1. Nếu mỗi phép gán tốn một đơn vò thời gian thuật toán thì thời gian chạy2 của chương trình là F(n)=2n+1. Như vậy F(n) là O(n).Để xem xét trường hợp thuật toán nhò phân, ta giả sử n=2k với k là số nguyên không âm3 (ie: k=log2 n). ƠÛ mỗi giai đoạn của thuật toán thì i và j là các vò trí đầu và vò trí cuối của danh sách ở giai đoạn đó. ƠÛ mỗi giai đoạn, trừ lần đầu tiên, chiều dài của danh sách chỉ bằng phân nửa chiều dài danh sách của giai đoạn ngay trước đó. ƠÛ mỗi giai đoạn có hai phép so sánh được thực hiện. Trong tình huống xấu nhất ViTriTimThay chỉ được xác nhận khi chiều dài danh sách bằng 1 (khi i=j). Sau đó một phép so sánh nữa được thực hiện để cho biết có tìm thấy phần tử x trong danh sách tại vò trí i hoặc không tìm thấy x (ViTriTimThay=0). Trong tình huống xấu nhất việc chia đôi danh sách phải thực hiện tất cả k lần (ứng với các chiều dài danh sách 2k, 2k-1, 2k-2, …,22, 21) và phải thực hiện tất cả 2k phép so sánh. Lần cuối cùng (ứng với chiều dài danh sách 20) phải thực hiện phép so sánh (i<j) để thoát khỏi vòng lặp và phép so sánh (x=ai) để kết xuất ViTriTimThay. Tổng cộng có 2k+2 =2 log n + 2 phép so sánh. Thời gian chạy như vậy là F(n)=2 log n + 2. Hay F(n) là O(log n)Đồ thò so sánh như sau:Suy từ đồ thò rõ ràng thuật toán nhò phân, ngay cả trong trường hợp xấu nhất, cũng cho một hiệu quả tìm kiếm tốt hơn nhiều so với tìm kiếm kiểu vét cạn.Thuật toán nhò phân có vẻ như được mô tả phức tạp hơn, rắc rối hơn nhưng điều đó không có nghóa là ít hiệu quả hơn, mà là ngược lại. Trong công việc lập trình điều này thường rất hay xảy ra. Do đó điều quan trọng khi đánh giá hiệu quả một thuật toán không phải là dựa vào số lượng dòng văn bản đã được dùng để mô tả nó mà là có một sự phân tích toán học thấu đáo.2 Là thời gian thực hiện chương trình trong tình huống xấu nhất (thời gian thuật toán).3 Nếu n không phải là luỹ thừa của 2, ta có thể xem danh sách đó là danh sách con của danh sách có 2(k+1) phần tử với k là số nguyên nhỏ nhất sao cho: 2k < n < 2(k+1)31 . chiều dài danh sách 2k, 2k -1, 2k -2, … ,22 , 21 ) và phải thực hiện tất cả 2k phép so sánh. Lần cuối cùng (ứng với chiều dài danh sách 20 ) phải thực hiện phép. gian thuật toán thì thời gian chạy2 của chương trình là F(n)=2n +1. Như vậy F(n) là O(n).Để xem xét trường hợp thuật toán nhò phân, ta giả sử n=2k với k

Ngày đăng: 13/11/2012, 16:17

TỪ KHÓA LIÊN QUAN

w