1. Trang chủ
  2. » Giáo án - Bài giảng

CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT

783 98 0

Đ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

Thông tin cơ bản

Định dạng
Số trang 783
Dung lượng 3,52 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Quá trình giải quyết một bài toán trên máy tính bao gồm nhiều công đoạn . Bước thứ nhất là xác lập mô hình của bài toán,tức là xác định cấu trúc toán học của bài toán đặt ra. Thực tế cho thấy ,đối với các cơ sở thực tiễn người ta chỉ phác hoạ ra các yêu cầu cần giải quyết một cách hình thức dưới dạng các yêu cầu, mong muốn. Nhiệm vụ của phân tích viên hệ thống là phải chuyển các yêu cầu rất hình thức đó thành các cấu trúc chặt chẽ dưới dạng một mô hình toán học . Mô hình này là cơ sở để thiết kế các bước tiếp theo giải quyết bài toán bắt đầu từ việc thiết kế cấu trúc dữ liệu, thiết kế giải thuật, lựa chọn ngôn ngữ diễn đạt giải thuật, đến việc thử nghiệm chương trình và phân tích kết quả của chương trình nhằm đánh giá chất lượng của chương trình.

Trang 1

CHƯƠNG 1 MỘT SỐ KHÁI NIỆM CƠ BẢN VỀ CẤU TRÚC DỮ LIỆU VÀ GIẢI THUẬT

Trong các bước giải quyết một bài toán trên máy tính, côngđoạn lập trình có vai trò quan trọng nhất.Việc ứng dụng tin họcngày càng phát triển,các yêu cầu của thực tiễn ngày càng đadạng Điều đó đòi hỏi phải thiết kế các giải thuật giải quyết mộtcách hiệu quả nhất vấn đề đặt ra

Trong chương này chúng ta xem xét một số khái niệm cơ bản

về cấu trúc dữ liệu và giải thuật,các phương pháp thiết kế giảithuật thông dụng

1 1 MỘT SỐ KHÁI NIỆM VỀ CẤU TRÚC DỮ LIỆU VÀ GIẢI

THUẬT

Quá trình giải quyết một bài toán trên máy tính bao gồmnhiều công đoạn Bước thứ nhất là xác lập mô hình của bàitoán,tức là xác định cấu trúc toán học của bài toán đặt ra Thực tếcho thấy ,đối với các cơ sở thực tiễn người ta chỉ phác hoạ ra cácyêu cầu cần giải quyết một cách hình thức dưới dạng các yêu cầu,mong muốn Nhiệm vụ của phân tích viên hệ thống là phảichuyển các yêu cầu rất hình thức đó thành các cấu trúc chặt chẽdưới dạng một mô hình toán học Mô hình này là cơ sở để thiết

kế các bước tiếp theo giải quyết bài toán bắt đầu từ việc thiết kếcấu trúc dữ liệu, thiết kế giải thuật, lựa chọn ngôn ngữ diễn đạtgiải thuật, đến việc thử nghiệm chương trình và phân tích kết quảcủa chương trình nhằm đánh giá chất lượng của chương trình Qui trình giải một bài toán trên máy tính gồm 7 bước đượcbiểu diễn trong hình vẽ sau đây:

Trang 2

Programs = Data structure + Algorithm

Chương trình = Cấu trúc dữ liệu + Giải thuật

Định nghĩa này đã nêu lên thực chất của kỹ thuật lập trình:

Kỹ thuật lập trình là công việc lao động trí tuệ và sáng tạo trong

đó các nhà lập trình phải thực hiện hai công đoạn quan trọng:

 Công đoạn thiết kế cấu trúc dữ liệu

 Công đoạn thiết kế giải thuật

Trang 3

Việc xây dựng phần mềm là một quá trình phức tạp, nó làmột nghệ thuật đồng thời cũng là một khoa học.Nó là một nghệthuật bởi vì nó đòi hỏi trí tưởng tượng tốt,óc sáng tạo cộng thêm

sự khéo léo.Là một khoa học bởi vì ở đó các kỹ thuật và phươngpháp tiêu chuẩn được sử dụng.Thuật ngữ công nghệ phần mềm(Software Engineering) đã được dùng để chỉ việc nghiên cứu và

sử dụng những kỹ thuật này.Cả hai công đoạn đều đòi hỏi tínhsáng tạo rất cao,vì đứng trước mỗi bài toán đặt ra ,người lập trìnhphải biết lựa chọn một cấu trúc dữ liệu phù hợp nhất,và trên cơ sở

đó tiến hành thiết kế một giải thuật hiệu quả nhất

Định nghĩa

Giải thuật (Algorithm) là một dãy các qui tắc chặt chẽ xác định một trình tự các thao tác trên một đối tượng cụ thể để giải quyết một vấn đề hoặc để hoàn thành một mục đích cuối cùng nào đó

Trong tin học , thuật ngữ giải thuật dùng để chỉ một thủtục có thể thực hiện được bằng máy tính , và điều này dẫn đếnmột số hạn chế đối với các lệnh tạo nên thủ tục:

1 - Chúng phải được xác định và không nhập nhằng để có thể biết

rõ lệnh đó làm gì?

2 - Chúng phải đủ đơn giản để máy tính hiểu được

3 - Chúng phải kết thúc sau một số hữu hạn các phép toán

Các giải thuật luôn luôn được thiết kế bởi ba cấu trúc điều khiểnsau đây:

 Cấu trúc tuần tự ( Sequential) các bước được thực hiện theotrình tự một cách chính xác, mỗi bước được thực hiện đúng mộtlần

Trang 4

 Cấu trúc chọn lọc ( Selection ) một trong nhiều thao tác đượcchọn và thực hiện.

 Cấu trúc chu trình( Repetition) một hay nhiều bước được thựchiện lặp lại

Ba cơ chế điều khiển chương trình này tuy đơn giản nhưngtrong thực tế đủ mạnh để xây dựng bất cứ giải thuật nào

Nguyên tắc quan trọng để tạo ra một chương trình có chất lượngcao là đảm bảo rằng chương trình phải có cấu trúc tốt Muốn vậychúng ta nên thực hiện các vấn đề sau đây:

 Sử dụng phương hướng tiếp cận từ đỉnh xuống ( Top DownDesign ) để viết các chương trình phức tạp

 Sử dụng các cấu trúc diều khiển cơ bản để thiết kế cho từngđơn thể của chương trình( Program Module)

 Sử dụng các biến cục bộ( Local variables) trong các chươngtrình con

 Sử dụng các tham số để truyền tham số Tránh dùng các biếntoàn cục( Global variables) để truyền tham số giữa các chươngtrình con , bởi vì điều đó làm phá vỡ tính độc lập của các chươngtrình con

Để chứng minh tính đúng đắn của một giải thuật, chúng taphải chứng minh một cách suy diễn rằng những bước trong giảithuật xử lý đầu vào đúng đắn và tạo ra đầu ra theo yêu cầu Nhưvậy, một chứng minh tính đúng đắn của giải thuật bắt đầu bằngmột khẳng định( Giả thiết ) về dữ liệu vào ( Data Input) và dùngcác lý luận lôgic để chỉ ra rằng việc thực hiện giải thuật sẽ cho tamột khẳng định( Kết luận) đúng về dữ liệu ra ( Data Output)

Định nghĩa

Trang 5

Một tập hợp các phần tử dữ liệu ban đầu trong một bài toán được gọi là dữ liệu cơ sở

Ví dụ : Chúng ta xem xét bài toán kinh tế sau đây:

Trong hệ thống quản lý Ngân hàng, giả sử ta cần tính số

dư tiết kiệm của khách hàng, khi biết họ tên khách hàng, số tiềngửi ban đầu, số tháng gửi và lãi suất hàng tháng Trong trườnghợp này các dữ liệu cơ sở là :

- Họ tên người gửi

- Số tiền gửi ban đầu

Việc lựa chọn các cấu trúc dữ liệu, việc thiết lập các giảithuật đúng đắn có cấu trúc tốt và hiệu quả , là những vấn đề mấuchốt của việc thiết lập phần mềm.Hai khía cạnh này của việc pháttriển phần mềm có tầm quan trọng như nhau, và trong thực tếchúng không thể tách rời Không thể nói tới cấu trúc dữ liệu màkhông đề cập đến các giải thuật tác động lên các cấu trúc dữ liệu Ngược lại, mỗi giải thuật đều liên quan đến một cấu trúc dữ liệu

cụ thể , không thể có giải thuật chung chung cho mọi cấu trúc dữliệu Khi cấu trúc dữ liệu thay đổi thì giải thuật cũng phải thayđổi cho phù hợp để có thể xử lý một cách hiệu quả cấu trúc dữliệu ấy

Trang 6

Để minh hoạ cho ý tưởng này ,chúng ta xét bài toán tạolập hồ sơ ban đầu trong phân hệ tin học quản lý nhân sự của một

cơ quan Giả sử mỗi hồ sơ bao gồm các trường: Họ tên , tuổi, địachỉ, số năm công tác, mức lương

Trước hết là việc chọn cấu trúc dữ liệu để giải quyết bài toán Ta

có thể chọn 3 cấu trúc dữ liệu sau đây:

Cấu trúc dữ liệu tệp File

Cấu trúc dữ liệu động kiểu con trỏ Pointer

Cấu trúc dữ liệu mảng Array

Giải thuật tạo lập hồ sơ ban đầu trong 3 trường hợp sẽ như sau :

Trường hợp 1: Sử dụng cấu trúc dữ liệu tệp File

Program CreateFile;

Type

nhansu = record

Stt : integer; (* Số thứ tự *)

Hoten : String [30]; ( * Họ và tên * )

Tuoi : integer; ( * Tuổi * )

namct : integer; ( * Số năm công tác *)

diachi : String [30]; ( * Địa chỉ *)

Luong : real; ( * Lương * )

Trang 7

GotoXY ( X,Y ) ; Write ( ' Sott : ' );

GotoXY ( X, Y+1 ); Write ( ' Hoten : ' );

GotoXY (X, Y+2 ); Write ( ' Tuoi : ' );

GotoXY ( X,Y+3); Write ( ' Nam cong tac');

GotoXY ( X, Y+4); Write (' Dia chi ');

Goto XY ( X, Y+5 ); Write ( ' Luong :' );

X : = X+14 ;

With Nguoi do

Begin

GotoXY ( X,Y ); Write ( SoTT );

GotoXY ( X, Y+1 ); Readln (Hoten ) ;

GotoXY ( X, Y+2 ); Readln ( Tuoi );

GotoXY ( X, Y+3); Readln( Namct);

GotoXY( X, Y+4); Readln (Diachi);

GotoXY ( X, Y+5 ); Readln ( Luong );

Trang 9

Write (' Năm ctac'); Readln( Ptr ^ namct);

Write (' Địa chỉ: ' ); Readln( Ptr ^ diachi);

Write( ' luong ' ); Readln( Ptr ^ luong);

Writeln(' Ho ten:', Ptr ^ hoten)

Writeln(' Tuoi:', Ptr ^ Tuoi);

Writeln(' Nam ctac' , Ptr^ namct);

Writeln(' Dia chi' , Ptr^ diachi);

Writeln ('luong' , Ptr ^.luong);

Trang 10

Write (' Hoten [',i ,' ] = '); Readln ( Hoten [i]);

Write (' Tuoi[',i,'] = ' ); Readln( Tuoi[i]);

Write (' Namct[',i,'] = '); Readln( Namct[i]);

Write (' Diachi[',i,'] =' ); Readln(Diachi[i]);

Write ( ' Luong[',i,'] ='); Readln(Luong[i]);

end;

end;

Qua ba trường hợp trình bày trên đây chúng ta thấy, tuycùng giải quyết một bài toán nhưng căn cứ vào cấu trúc dữ liệuđược lựa chọn mà các giải thuật có thể sẽ rất khác nhau Điều nàykhẳng định một lần nữa mối liên hệ không thể tách rời của haikhái niệm cấu trúc dữ liệu ( Data structure ) và giải thuật( Algorithm ) Bây giờ chúng ta xem xét một vài khái niệm cơbản khác

Trang 11

hai cấu trúc lưu trữ rất thông dụng là cấu trúc lưu trữ ưu tiêndòng(Row major order) và cấu trúc lưu trữ ưu tiên cột ( Colunmmajor order) Mặt khác , nhiều cấu trúc dữ liệu lại có thể đượcbiểu diễn bằng một cấu trúc lưu trữ duy nhất Chẳng hạn, cấu trúc

dữ liệu danh sách kiểu LIFO, cấu trúc danh sách kiểu FIFO, cấutrúc dữ liệu cây Tree) đều có thể được thể hiện trong một cấu trúclưu trữ duy nhất là lưu trữ kế tiếp(Sequential storage allocation) Trong môn học Cấu trúc dữ liệu , người ta thường nghiêncứu các loại cấu trúc cơ bản sau đây :

 Mảng ( Array )

 Danh sách kiểu LIFO (Stack)

 Danh sách kiểu FIFO ( Queue)

 Danh sách liên kết đơn ( Singly linked list )

 Danh sách liên kết vòng ( Circularity linked list)

 Danh sách liên kết kép ( Double Linked list)

 Cấu trúc dữ liệu phi tuyến cây ( Tree)

 Cấu trúc dữ liệu phi tuyến kiểu đồ thị ( Graph )

1 2 HIỆU SUẤT CỦA GIẢI THUẬT ( ALGORITH EFFICIENCY)

Mỗi cấu trúc dữ liệu đều có thể được cài đặt bằng nhiềucách khác nhau , do đó giải thuật xử lý các dữ liệu ấy cũng khácnhau Việc đánh giá những cách cài đặt khác nhau của cấu trúc dữliệu dựa trên hai điều kiện chính:

Một là , khối lượng bộ nhớ để lưu trữ cấu trúc dữ liệu ấy Hai là , thời gian cần thiết để thực hiện giải thuật xử lý

dữ liệu

Trong hai chỉ tiêu trên đây thì chỉ tiêu thứ hai ,tức là thờigian thực hiện một giải thuật thường được xem là quan trọng

Trang 12

hơn Chúng ta sẽ xem xét xem chỉ tiêu này được đánh giá như thếnào?

Thời gian thực hiện một giải thuật chịu ảnh hưởng củanhiều yếu tố Một yếu tố quan trọng là kích thước đầu vào,bởi vì

số các mục đầu vào thường ảnh hưởng đến thời gian xử lýchúng.Ví dụ , thời gian cần thiết để sắp xếp thứ tự danh sách cácmục phụ thuộc vào số lượng các mục trong danh sách.Như vậy,thời gian thực hiện T của một giải thuật như một hàm T(n) của

độ lớn của dữ liệu đầu vào n Các kiểu lệnh ( Instruction) và vậntốc của máy tính thực hiện những lệnh đó cũng ảnh hưởng đếnthời gian thực hiện một giải thuật.Tuy nhiên những yếu tố nàyphụ thuộc vào máy tính đang sử dụng vì vậy chúng không thểbiểu diễn giá trị của T(n) bằng các đơn vị thời gian đầy đủ chẳnghạn như bằng giây [1] Thay vào đó, T(n) sẽ được tính gần đúngnhư là số lượng các lệnh (Instruction) thực hiện Một yếu tố khác

có ảnh hưởng đến thời gian thực hiện giải thuật là chất lượng củachương trình do chương trình dịch tạo ra Không phải mọichương trình dịch đều cho ta các chương trình có hiệu suất nhưnhau Như vậy, T(n) không thể tính như số lượng các lệnh máy( Machine instruction) Hàm T(n) sẽ được tính như là số lần thựchiện các lệnh trong giải thuật Sau đây là bảng giá trị của một sốhàm thường dùng để đánh giá độ phức tạp của giải thuật :

n

n2 n3 2n

Trang 13

Các hàm như 2N , n! được gọi là các hàm mũ Các giải thuật cóthời gian thực hiện là một hàm mũ thường có tốc độ tính toán rấtchậm Còn các hàm đa thức như n , n2 , n3 , Log2 n , nLog2 n

có tốc độ thực hiện tốt hơn

Giả sử rằng mỗi lệnh trong giải thuật được thực hiện trong

1 micrô giây Thời gian cần thiết để thực hiện f(n) lệnh đối vớicác hàm thông dụng với n= 256 cho trong bảng sau đây :

Giả sử T1( n ) và T2( n) là thời gian thực hiện hai giải thuật A1

và A2 với T1(n) = O(f(n)) và T2 = O(f(n)) Khi đó thời gian thực

Trang 14

hiện A1 rồi đến A2 sẽ là T = T1(n) + T2 (n) và được đánh giábằng đại lượng O ( max( f(n),g(n))

QUI TẮC NHÂN

Giả sử T1( n ) và T2( n) là thời gian thực hiện hai giải thuật A1

và A2 với T1(n) = O(f(n)) và T2 = O(f(n)) Khi đó thời gian thựchiện A1 và A2 lồng nhau sẽ là T1(n)T2 (n) = O ( f(n),g(n))

Ví dụ 1

Trong chương trình chúng ta phải thực hiện 3 giải thuật liên tiếpnhau với các độ phức tạp là O(n2) , O ( n3 ) và O (nLog2 n ) Khi đó thời gian thực hiện chương trình sẽ là O(n3 )

Trang 15

Để minh hoạ ,chúng ta xem xét giải thuật tìm giá trị trung bìnhcủa n số.

GIẢI THUẬT TÍNH GIÁ TRỊ TRUNG BÌNH

Cho năng suất lao động trung bình của n doanh nghiệp Tínhnăng suất lao động trung bình ?

1 Đọc n

2 Cho giá trị ban đầu Sum =0

3 Cho chỉ số ban đầu i =1

Lệnh Số lần thực hiện

1 1

2 1

3 1

Trang 16

4 n

5 n

6 n

7 1Tổng cộng 3n+4

chúng ta thấy rằng thời gian thực hiện của giải thuật này là T(n)=3n+4 Khi giá trị n tăng lên , giá trị của T(n) cũng tăng lên theomột cách tuyến tính Chúng ta nói rằng, T(n) có "bậc" là n vàđược ký hiệu theo " ký pháp chữ O lớn" của toán học như sau: T(n)= O(n)

Một cách tổng quát , thời gian tính toán T(n) của một giải thuậtđược gọi là có bậc f(n) ,ký hiệu bởi T(n)= O(f(n)) nếu tồn tại các

số dương C và No sao cho :

T(n)<=C f(n) với mọi n>=N0

nghĩa là T(n) bị chặn trên bởi một hằng số nhân với f(n) với mọigiá trị của n từ một điểm nào đó Độ phức tạp của giải thuật nàyđược gọi là O(F(n))

Ví dụ, độ phức tạp của giải thuật trên đây là O(n) bởi vìthời gian tính được là T(n)=4n+5 và vì 4n+5<= 4n+n với mọin>5 Ta có T(n) <=5n với mọi n>5

Như vậy, ta chỉ cần chọn F(n)=n, No=5 và C=5 chúng ta

có thể viết: T(n)= O(n) Đương nhiên là bất đẳng thức cũngđúng khi ta viết T(n)=O(5280n) hay T(n)=O(4n+5) hay T(n)=(3.1416 n+ 2.71828) nhưng chúng ta chọn các hàm đơn giản hơnnhư n,Log để biểu diễn độ phức tạp của giải thuật

Trang 17

Chúng ta xét thêm giải thuật tìm kiếm tuyến tính sau đây : Tìmphần tử có giá trị Item cho trước trong mảng A[1], A[2] A[n]vànếu có thì xác định vị trí của nó.

GIẢI THUẬT TÌM KIẾM TUYẾN TÍNH

( Tìm Item trong danh sách A[i] Found sẽ có giá trị đúng vàLoc có giá trị là vị trí của Item Nếu không Found sẽ có giá trịsai)

1 Gán giá trị sai cho Found

2 Gán giá trị 1 cho Loc

3 While Loc<= n and not Found , thực hiện các bước sau đây:

4 If Item =A[Loc] then

5 Gán giá trị đúng cho Found

6 Else

Tăng Loc thêm

Trường hợp xấu nhất là không tìm thấy Item trong danh sách vàtrong trường hợp này thời gian tính TL(n) cho giải thuật tìmkiếm tuyến tính như sau:

Trang 18

Như vậy, TL (n)= 3n+3 hay TL(n)= O(n) bởi vì 3n+3<=4n vớimọi n>=3 Nếu danh sách đã dược sắp xếp thì quá trình tìm kiếm

sẽ nhanh hơn rất nhiều Giải thuật tìm kiếm nhị phân sau đây tiếnhành như sau:

Nếu Item < A[Mid] : tìm trong nửa đầu của danh sách

Nếu Item > A[Mid] : tìm trong nửa cuối của danh sách

Nếu Item =A[Mid] : tìm ra Item

Trong đó Mid là phần tử ở giữa của danh sách

GIẢI THUẬT TÌM KIẾM NHỊ PHÂN

( Tìm kiếm nhị phân phần tử Item trong danh sách Found sẽ cógiá trị đúng và Mid có giá trị là vị trí của Item nếu tìm được Nếukhông Found sẽ có giá trị là sai)

1 Gán giá trị sai cho Found

2 Gán 1 cho First

3 Gán n cho Last

4 While First <= Last and not Found thực hiện các bước sau dây:

5 Tính Mid=(First+Last)/2

6 If Item <A[ Mid] then

7 Gán giá trị Mid=1 cho Last

8 Else If Item >A[Mid] then

9 Gán giá trị Mid+1 cho First

10 Else gán giá trị đúng cho Found

Trong giải thuật này các lệnh 1,2 và 3 được thực hiệnđúng một lần và để tính độ phức tạp cho trường hợp xấu nhấtTX(n) chúng ta phải tính số lần thực hiện của vòng lặp chứa cáclệnh từ 4 đến 10 Mỗi lần đi qua vòng lặp này độ lớn của danhsách giảm đi một nửa Lần cuối cùng đi qua danh sách có độ lớn

là 1 Như vậy số lần lặp lại tổng cộng của vòng lặp này là 1 cộng

Trang 19

với k lần đi qua vòng lặp để cuối cùng tạo ra danh sách con có độdài 1.

Vì độ lớn của danh sách con sau k lần đi qua nhiều nhất là N/ 2N

ta có:

2K < 2

nghĩa là N< 2K 1 hay Log2 n < k+1

Số lần đi qua vòng lập là số nguyên bé nhất thoả mãn bấtđẳng thức trên đây nghĩa là phần nguyên của Log2 n Như vậytrong trường hợp xấu nhất , khi Item lớn hơn các phần tửA[1],A[2] A[n] ,lệnh 4 được thực hiện không nhiều hơn 2+

Log2 n lần, lệnh 5,6 và 8 không nhiều hơn 1+ Log2 n lần vàcác lệnh 7,9 và 10 không lần Thời gian tính tổng cộng như vậykhông quá 8+4 Log2 n lần, tức là TX(n)= O(Log2 n ) Bởi vìLôgarit cơ số hai xuất hiện rất thường xuyên trong phân tích giảithuật chúng ta qui ước ký hiệu Log n là Log2 n

Như vậy , chúng ta thấy độ phức tạp của giải thuật tìmkiếm tuyến tính là O(n) còn của giải thuật tìm kiếm nhị phân làO(Logn) rõ ràng là giải thuật tìm kiếm nhị phân có hiệu quả hơnđối với các danh sách có qui mô lớn Nhưng đối với các danhsách có qui mô nhỏ giải thuật tìm kiếm tuyến tính vẫn có ưu thế.Các nghiên cứu cho thấy, đối với các danh sách có không quá 20phần tử, giải thuật tìm kiếm tuyến tính có hiệu quả hơn giải thuậttìm kiếm nhị phân

1 3 PHƯƠNG PHÁP DIỄN ĐẠT GIẢI THUẬT

Trang 20

Để diễn đạt một giải thuật , thông thường người ta có thể dùng baphương pháp chủ yếu sau đây :

Phương pháp 1 Diễn đạt giải thuật bằng lời

Phương pháp 2 Diễn đạt giải thuật bằng sơ đồ khối

Phương pháp 3 Diễn đạt giải thuật bằng một ngôn ngữ lập trình

Trang 22

Chúng ta xét thêm một ví dụ khác Trong phân hệ quản

lý của một doanh nghiệp, người ta yêu cầu tính giá trị tổng sảnlượng trong một năm Giả sử rằng doanh nghiệp có n phânxưởng cùng sản xuất ra m loại sản phẩm Biết số lượng sảnphẩm của mỗi phân xưởng và đơn giá của mỗi sản phẩm

Phương pháp 1 : Diễn đạt giải thuật bằng lời.

 Bước 1 : Nạp số liệu

 Bước 2 : Tính toán giá trị tổng sảnlượng của một phân xưởngbằng cách lấy số lượng từng loại sản phẩm nhân với đơn giá

 Bước 3 : Kiểm tra xem đã tính giá trị tổng sản lượng cho tất

cả các phân xưởng hay chưa?

 Bước 4 : Tinh giá trị tổng sản lượng của cả doanh nghiệp

 Bước 5 : In kết quả

Phương pháp diễn đạt giải thuật bằng lời có ưu điểm là làm chongười đọc dễ dàng nắm bắt được tư tưởng chủ đạo của giải thuật,nhưng nó còn rất "thô" ,khi chuyển giải thuật sang một ngôn ngữlập trình cụ thể nào đó (C++ , Pascal, )ta phải thiết kế làm "mịn"dần trong rất nhiều công đoạn

Phương pháp 2 : Diễn đạt giải thuật bằng sơ đồ khối

Tư tưởng của phương pháp này là trên cơ sở ý đồ chủ đạocủa giải thuật, người ta tiến hành xây dựng các khối biểu diễn cácqui trình tính toán và mối liên hệ giữa các khối với nhau

Phương pháp biểu diễn thuật toán bằng sơ đồ khối cho ta một cáinhìn tổng thể về phương pháp giải quyết bài toán đặt ra Trên cơ

sở của sơ đồ khối người ta đễ dàng chuyển thành chương trình

Trang 23

trong một ngôn ngữ lập trình cụ thể.Chẳng hạn ta xem xét sơ đồkhối biểu diễn giải thuật tính giá trị tổng sản lượng của doanhnghiệp sau đây:

GTSP i = 0 ; i=1,2 n

I = 1

J = 1 GTSP i = GTSP i +SLi j*GIAj

J =J +1

J <= M

I =I +1 I<= N Tinh tong

In

T T

F F

Phương pháp 3 : Diễn đạt giải thuật bằng một ngôn ngữ lập trình cụ thể

Theo phương pháp này người ta sử dụng một ngôn ngữ lập trình

có cấu trúc(như Pascal chẳng hạn) để biểu diễn thuật toán.Chẳng hạn trong PASCAL giải thuật của bài toán tính giá trị tổngsản lượng của doanh nghiệp được biểu diễn như sau:

Type

Trang 24

For I : =1 to n do Tong:= Tong + gtsp [i] ;

Write ('Gia tri tong san luong:');

WriteLn (tong:12:2);

end;

Như vậy , qua việc trình bày 3 phương pháp khác nhau

để diễn đạt một giải thuật chúng ta có một số nhận xét sau đây:

 Phương pháp diễn đạt giải thuật bằng lời giúp ta dễ nắm bắt tưtưởng chủ đạo của giải thuật nhưng còn ở mức độ trừu tượng cao,

Trang 25

từ giải thuật đến chương trình cụ thể còn cần nhiều công đoạnlàm “mịn” ( Chi tiết dần đến mức từng lệnh cụ thể)

 Phương pháp sơ đồ khối cho ta một cái nhìn tổng quát về cấutrúc của một giải thuật nhưng đối với các giải thuật phức tạp vềtính logic thì phương pháp này kém hiệu quả

 Phương pháp diễn đạt bằng một ngôn ngữ thuật toán cụ thể tuyphải tuân theo các qui định của ngôn ngữ đó nhưng việc lựa chọnmột ngôn ngữ có cấu trúc tiền định đủ mạnh ( như Pascal chẳnghạn) sẽ cho phép chúng ta biểu diễn các giải thuật một cách ngắngọn, dễ dàng hình dung ra các công đoạn thiết kế giải thuật.PASCAL có các cấu trúc dữ liệu đầyđủ, có thể biểu diễn các loạicấu trúc dữ liệu từ đơn giản đến phức tạp , từ cấu trúc tuyến tínhđến cấu trúc phi tuyến

Trong giáo trình này chúng tôi sử dụng Pascal để biểudiễn các giải thuật Trong một vài trường hợp sẽ sử dụng thêm cả

sơ đồ khối để minh hoạ

1.4 GIẢI THUẬT ĐỆ QUI ( RECURSIVE ALGORITHM )

Giải thuật đệ qui có vai trò rất đặc biệt Nhờ giải thuật đệqui mà chúng ta có thể thiết kế lời giải của một bài toán phức tạpmột cách rất ngắn gọn , cô đọng Có một số vấn đề mà các giảithuật đệ qui là thích hợp hơn cả để giải quyết chúng

Trong phần này chúng ta sẽ xem xét giải thuật đệ qui ,chứng minh tính đúng đắn của giải thuật đệ qui và hiệu suất củagiải thuật đệ qui so với giải thuật không đệ qui

Trước hết , chúng ta làm quen với khái niệm đệ qui.Chúng ta nói một đối tượng nào đó là đệ qui nếu nó bao hàmchính nó như một bộ phận cấu thành Hoặc nói một cách khác làđối tượng đó được định nghĩa thông qua chính bản thân nó Định nghĩa đệ qui luôn luôn bao gồm hai phần :

Trang 26

 Phần neo ( anchor ) , trong đó tác động của hàm hay thủ tục

được đặc tả cho một tham số

 Phần đệ qui ( recursive ) , trong đó tác động cần được thực

hiện cho giá trị hiện thời của các tham số được định nghĩa bằngcác tác động hay giá trị được định nghĩa trước đây

Dùng định nghĩa này để tính 3! , trước hết chúng ta cần tính 2!

và sau đó 3! được tính như là tích của 2! và 3 Tương tự nhưvậy , muốn tính 2! , trước hết chúng ta cần tính 1! và sau đó 2!được coi là tích của 1! và số 2 Sử dụng một lần nữa ta có 1! = 0!x1 và chúng ta đạt đến trường hợp của phần neo theo sơ đồ sauđây :

Trang 27

Dùng giá trị 1 của 0! , ta có thể tính được 1! Giá trị này đượcdùng để tính 2! sau đó 2! được dùng để tính 3! và ta được giá trịcuối cùng là 6

Giải thuật này được cài đặt như sau :

Function FACTORIAL ( n : integer ) : integer ;

Factorial ( 1) = 1x0! = 1 Factorial ( 0) =1

trong giải thuật đệ qui trên đây chúng ta chỉ cần đến một tham trỏđến chính nó Bây giờ chúng ta xem xét một giải thuật đệ quikhác đòi hỏi nhiều tham trỏ hơn Xét dãy số Fibonacci sau đây :

1,1 ,2,3,5,8,13,21,

Trang 28

trong đó mỗi số sau là là tổng của hai số đứng trước nó Giảithuật Fibonacci Fib được định nghĩa như sau :

Fib (1) = 1  phần neo

Fib (2) = 1

với n > 2 ta có Fib(n) = Fib(n-1) + Fib(n-2)

Ta cài đặt như sau :

Function Fib( n : integer ) : integer ;

Bây giờ chúng ta xem xét tính đúng đắn và hiệu suấtcủa các giải thuật đệ qui

Như đã biết , để chứng minh tính đúng đắn của giảithuật chúng ta phải chứng minh rằng giải thuật sẽ kết thúc và cho

ta kết quả đúng Để chứng minh tính đúng đắn của các giải thuật

đệ qui chúng ta dùng công cụ qui nạp của toán học

Xét hàm đệ qui tính giai thừa sau đây :

Function FACTORIAL ( n : Integer ) : integer ;

Trang 29

Trong trường hợp này các khẳng định đầu vào và đầu ra là :

 Đầu vào : Một số nguyên dương

 Đầu ra : Hàm sẽ kết thúc và cho ta giá trị của N!

Bây giờ , bằng phép qui nạp toán học , chúng ta sẽ chỉ rarằng khẳng định đầu ra được kéo theo từ khẳng định đầu vào

 Bước 1 của qui nạp

Nếu n = 0 , lệnh ở phần neo Factorial : = 1 lập tức được thựchiện giải thuật kết thúc và giá trị đúng của hàm là 0 !

 Bước thứ hai của qui nạp

Giả sử rằng với số nguyên k không âm , hàm kết thúc với n= k vàgiá trị trả đúng k!

 Bước thứ ba của qui nạp

Bây giờ chúng ta phải chứng minh rằng với n = k+1 giá trị trả lạicho hàm Factorial sẽ là ( k+1) !

Thật vậy , với n = k+1 ta có Factorial : = n* Factorial ( n-1 ) màn-1 = k Vậy theo giả thuyết qui nạp tham trỏ Factorial (n-1) kếtthúc và cho ta giá trị của hàm là k! Từ đây suy ra rằng tham trỏvới tham số n = k +1 cũng kết thúc với tham số là

Trang 30

n >0 , biểu thức lôgic n=0 được tính Và vì nó có giá trị sai , nênlệnh qui nạp

Thời gian T(0) để tính 0! là 2 ( vì biểu thức lôgic n=0 được tính

và sau đó thực hiện lệnh ở phần neo Factorial : = 1 )

Như vậy ta có : T(n) = 2(n+1) tức là T(n) = O(n)

Bây giờ chúng ta so sánh thời gian thực hiện của giải thuật

đệ qui và giải thuật không đệ qui

Trước hết , chúng ta viết giải thuật tính giai thừa không đệ quidưới dạng sau đây:

Function NRFactorial ( n: Integer ) : Integer;

Trang 31

tính giai thừa và giải thuật không đệ qui là như nhau Trong một

số trường hợp khác , thời gian tính toán của giải thuật đệ qui cóthể lớn hơn rất nhiều so với giải thuật không đệ qui tương ứng Chẳng hạn với giải thuật đệ qui tính dãy số Fibonacci Tuynhiên , có rất nhiều vấn đề mà việc giải quyết nó bằng cách dùng

đệ qui sẽ tự nhiên hơn và ít phức tạp hơn Ví dụ bài toán Tháp

Hà nội và bài toán Phân giải Khi sử dụng các cấu trúc dữ liệunhư danh sách, cây, đồ thị người ta cũng thường dùng giải thuật

đệ qui Khi duyệt một cấu trúc cây nhị phân theo một thứ tự nào

đó , các giải thuật đệ qui làm cho phép biểu diễn các quá trìnhthực hiện một cách sáng sủa , rõ ràng Trong các trường hợp nhưvậy , sự đơn giản và đẹp mắt của các giải thuật đệ qui thừa sức

để bù vào sự không hiệu quả nếu có thể có

Để kết thúc phần trình bày về giải thuật đệ qui , chúng ta xét một bài toán kinh điển cho thấy giải thuật đệ qui là đặc biệt hiệu quả trong trường hợp này Đó là bài toán Tháp Hà nội

A B C

Bài toán đặt ra như sau : Có một chồng đĩa ở cọc A Yêu cầuchuyển các đĩa từ cọc bên trái sang bên phải theo các luật sauđây:

Trang 32

 Khi di chuyển một đĩa , nó phải được đặt vào một trong ba cọc

 Mỗi lần chỉ được chuyển một đĩa và phải là đĩa ở trên cùng

 Đĩa lớn hơn không bao giờ được nằm trên đĩa nhỏ hơn

Có thể giải quyết bài toán bằng giải thuật đệ qui một cách

dễ dàng , nhưng cách giải không dùng đệ qui là rất khó khăn Giải thuật đệ qui như sau :

Nếu chỉ có 1 đĩa : Chuyển nó từ cọc A sang cọc C là xong

Giả sử rằng bài toán có nghiệm với n-1 đĩa Nghiệm của bài toánvới n đĩa có thể nhận được bằng phương pháp đệ qui như sau :

1 - Chuyển n-1 đĩa trên cùng ở cọc A sang cọc B , dùng cọc Cnhư là cọc phụ

2- Chuyển đĩa còn lại ở cọc A sang cọc C

3 - Chuyển n-1 đĩa từ B sang C , dùng A như cọc phụ

Sơ đồ trên đây được cài đặt bằng thủ tục đệ qui sau đây :

Procedure Move ( n: integer ; StartPed, AuxPed, EndPed : Char) ;

( Thủ tục chuyển n đĩa từ StartPed sang EndPed bằng cách dùngAuxPed như là cọc phụ )

Trang 33

(* Chuyển một đĩa từ StartPed sang EndPed *)

Move( 1, StartPed,' ',EndPed );

(* Chuyển n-1 đĩa từ AuxPed sang EndPed dùng StartPed *)Move(n-1,AuxPed, StartPed, EndPed):

end;

end;

Giả sử có 4 đĩa trên cọc A B và C là hai cọc còn lại Chươngtrình dùng thủ tục trên đây để giải quyết bài toán trong trườnghợp này như sau :

Program TowersOf Hanoi ( Input,output);

NumDisk: Integer ; ( * Số lượng đĩa *)

Procedure Move ( n: integer ; StartPed, AuxPed, EndPed : Char) ;( Thủ tục chuyển n đĩa từ StartPed sang EndPed bằng cách dùngAuxPed như là cọc phụ )

(* Chuyển một đĩa từ StartPed sang EndPed *)

Move( 1, StartPed,' ',EndPed );

Trang 34

(* Chuyển n-1 đĩa từ AuxPed sang EndPed dùng StartPed *)Move(n-1,AuxPed, StartPed, EndPed):

end;

end;

Begin (* Chương trình chính *)

Write( ' Số lượng các đĩa là : '); Readln( NumDisk ) ;

Move ( NumDisk, Ped1, Ped2, Ped3 ):

end

Chạy mẫu chương trình :

Số lượng các đĩa : 4

Chuyển đĩa từ A sang B

Chuyển đĩa từ A sang C

Chuyển đĩa từ B sang C

Chuyển đĩa từ A sang B

Chuyển đĩa từ C sang A

Chuyển đĩa từ C sang B

Chuyển đĩa từ A sang B

Chuyển đĩa từ A sang C

Chuyển đĩa từ B sang C

Chuyển đĩa từ B sang A

Chuyển đĩa từ C sang A

Chuyển đĩa từ B sang C

Chuyển đĩa từ A sang B

Chuyển đĩa từ A sang C

Chuyển đĩa từ B sang C

1 5 PHƯƠNG PHÁP THIẾT KẾ GIẢI THUẬT

1.5.1 KHÁI NIỆM MODULE HOÁ

Trang 35

Trong phương pháp lập trình cấu trúc có một khái niệmrất cơ bản là khái niệm module Mỗi module có thể coi như mộtđơn thể chương trình độc lập có thể lắp ghép với nhau Tư tưởngchính của module hoá là phân chia bài toán lớn thành các bàitoán nhỏ hơn , ngày càng cụ thể và chi tiết hơn theo sơ đồ cấutrúc hình cây sau đây :

Trong sơ đồ trên đây module chính M được phân chiathành hai module M1 và M2 Đến lượt mình , module M1 lạiđược chia thành ba module nhỏ hơn là M11, M12, M13 , moduleM2 được chia thành M21 , M22 Module con M13 lại đượcphân chia ra ba module M131,M132, M133

Mỗi module giải quyết một vấn đề nhỏ riêng rẽ , độc lập với các module khác và do một lập trình viên đảm nhận Tư tưởng phân rã thành các module là tư tưởng chính tạo nên một

Trang 36

phương hướng lập trình rất quan trọng được gọi là lập trình cấu trúc ( Programing Structure )

1 5 2 THIẾT KẾ TỪ TRÊN XUỐNG ( TOP DOWN DESIGN)

Đây là một phương pháp thiết kế giải thuật dựa trên tưtưởng module hoá Nội dung của phương pháp thiết kế này nhưsau :

Trước hết người ta xác định các vấn đề chủ yếu nhất màviệc giải quyết bài toán yêu cầu , bao quát được toàn bộ bài toán Sau đó phân chia nhiệm vụ cần giải quyết thành các niệm vụ cụthể hơn, tức là chuyển dần từ môdule chính đến các môdun con

từ trên xuống dưới , do vậy phương pháp có tên gọi là thiết kế "

từ đỉnh xuống"(Top down design )

Để minh hoạ cho phương pháp này , chúng ta xét bài toánthiết kế hệ tin học quản lý hoá đơn bán hàng cho một tổng công

ty thương mại

Mục đích của bài toán là thiết kế một hệ thống cácchương trình quản lý cơ sở dữ liệu hoá đơn

Phân tích bài toán:

 Số liệu ban đầu:

Tệp hoá đơn với các trường :

Trang 37

 Cỏc phộp toỏn xử lý

Nạp số liệu cho tệp hoỏ đơn

Tỡm kiếm, hiển thị ,huỷ, sửa một hoỏ đơn

Lập bảng tổng hợp hàng tồn kho

Lập bảng tổng hợp kinh doanh theo từng thỏng

Lập bảng tổng hợp kinh doanh theo nhúm hàng

Phõn tớch, dự bỏo mức tiờu thụ hàng hoỏ

Như vậy ta cú phỏc thảo thứ nhất về bài toỏn đặt ra :

Phần mềm quản lý hoá đơn

Vào dữ liệu Bảo trì Xử lý

Module chớnh được phõn chia thành 3 module nhỏ :

- Module vào số liệu cho tệp

- Module bảo trỡ

- Module xử lý

Trong module bảo trỡ chỳng ta cần thực hiện một số cụng việcsau đõy:

Trang 38

- Đọc lại tệp hoá đơn

- Sửa chữa , bổ sung số liệu trong mỗi hoá đơn

Trong module xử lý các công việc chính là

- In bảng tổng hợp kinh doanh trong năm ( B1 )

Trang 39

Hệ quản lý hoá đơn

Vào số liệu Bảo trì Xử lý

READ FILE Print B1

đú trờn cơ sở đỏnh giỏ mức độ tương tự về chức năng của cỏc vấn

đề này trong việc giải quyết bài toỏn người ta gộp chỳng lại thànhtừng nhúm cựng chức năng từ dưới lờn trờn cho đến mụđun chớnh Sau đú sẽ thiết kế thờm một số chương trỡnh làm phong phỳ hơn,đầy đủ hơn chức năng của cỏc phõn hệ và cuối cựng là thiết kế

Trang 40

một chương trình làm nhiệm vụ tập hợp các môđun thành một hệchương trình thống nhất, hoàn chỉnh.

Để minh hoạ cho tư tưởng của phương pháp thiết kếbootom up design chúng ta xem xét bài toán sau đây :

Giả sử trong một doanh nghiệp , công việc ứng dụng tin họctrong quản lý đã được triển khai ở các bộ phận khác nhau vàtrong từng thời điểm khác nhau Kết quả là người ta đã thiết kế vàđưa vào sử dụng một số chương trình quản lý trong các phòngban ( Phòng tài vụ , Phòng tổ chức hành chính , Phòng cung ứngnguyên vật liệu ) Danh sách các chương trình như sau:

Prog 1 : Vào số liệu cho tệp hồ sơ cán bộ

Prog 2 : Sửa chữa , bổ sung, cập nhật hồ sơ

Prog 3 : Vào số liệu cho tệp quản lý nguyên vật liệu

Prog 4 : Vào số liệu cho tệp hoá đơn bán sản phẩm

Prog 5 : Tính lương cán bộ quản lý

Prog 6 : Lập bảng dự toán sử dụng nguyên liệu cho sản xuất Prog 7 :Quản lý cán bộ

Prog 8 : Lập bảng tính giá trị sản phẩm bán ra

Các chương trình này đã được ứng dụng có kết quả trongsản xuất kinh doanh và đã được thực tế kiểm nghiệm Bây giờ ,trên cơ sở các chương trình cụ thể này Lãnh đạo nhà máy có nhucầu thiết kế một hệ chương trình thống nhất phục vụ tốt hơn choviệc quản lý doanh nghiệp Trong trường hợp này chúng ta vậndụng phương pháp thiết kế " Từ đáy lên" theo các phác thảo sauđây :

 PHÁC THẢO THỨ NHẤT

Gộp các môđun 1,2,5,7 thành phân hệ quản lý nhân sự

Ngày đăng: 06/04/2018, 14:41

TỪ KHÓA LIÊN QUAN

🧩 Sản phẩm bạn có thể quan tâm

w