Mỗi bài toán phải giải quyết thường bao gồm 2 phần: phần dữ liệu và phần xử lý. Phần dữ liệu liên quan đến thông tin của bài toán cụ thể đó như: đầu vào –các dữ liệu được cung cấp để xử lý và đầu ra là kết quả xử lý. Phần xử lý là những thao tác phải được máy tính tiến hành nhằm đáp ứng yêu cầu người dùng.
Thí dụ: Bài toán đơn giản là sắp xếp 1 dãy số nguyên a1, a2,…, antheo chiều tăng dần. Với bài toán này, dữ liệu đầu vào là số lượng phần tử của dãy n và n số nguyên ai, i=1, 2,…,n. Và đầu ra là dãy số đã sắp theo chiều tăng dần. Các xử lý là các thao tác để từ một dãy số không có thứ tự chuyển về một dãysố có thứ tự tăng dần.
Việc biểu diễn dữ liệu một cách trừu tượng là một vấn đề khá phức tạp, thí dụ như dãy số ở trên sẽ được lưu trữ ra sao trong máy tính (cả dãy vào lẫn dãy kết quả). Tạm thời chúng ta không xét ở đây mà sẽ trình bày trong một giáo trình khác.
Việc xác định các thao tác xử lý để đáp ứng yêu cầu đặt ra của người dùng là một nhiệm vụ rất quan trọng. Nó không phải là phương pháp chung mà phải cụ thể về các thao tác và việc liên kết các thao tác đó. Việc xác định các thao tác xử lý được các nhà tin học gọi là xây dựng giải thuật/thuật toán (algorithm). Có nhiều cách diễn đạt khác nhau về thuật ngữ này, song chúng ta có thể diễn đạt như sau:
Để hiểu rõ về thuật toán chúng ta xét một số thí dụ sau:
Thí dụ 1: Tìm giá trị lớn nhất của một dãy số nguyên có N số
- Đầu vào: số số nguyên dương N và N số nguyên a1, a2,…, aN
Thuật toán để giải một bài toán là một dãy hữu hạn các thao tác và trình tự thực hiện các thao tác đó sao cho sau khi thực hiện dãy thao tác này theo trình tự đã chỉ ra, với đầu vào (input) ta thu được kết quả đầu ra (output) mong muốn.
31
- Đầu ra: số nguyên lớn nhất của dãy ak, k trong khoảng [1…N]
Ý tưởng
Khởi tạo giá trị Max = a1
Lần lượt so sánh Max với i=2, 3,…, N, nếu ai> Max ta gán giá trị mới cho Max.
Thuật toán
B1: Nhập dãy số ai . B2: Max a1.
B3: Nếu i > N, thuật toán kết thúc và Max là giá trị lớn nhất của dãy cần tìm B4: Nếu ai > Max, gán ai cho Max.
B5: Tăng i lên 1 đơn vị. B6: Quay lên b4. B7: Kết thúc.
Vì thuật toán là chỉ ra dãy thao tác và trình tự thao tác để đạt mục đích và dùng cho người dùng con người, nên ngoài cách liệt kê trên, người ta có thể dùng sơ đồ khối để minh hoạ (biểu diễn). Với thuật toán trên, cách biểu diễn theo sơ đồ khối như sau:
Max a1 i 2 i > N ai > Max Max ai i i + 1 S Đ Đ S Hiển thị Max và kết thúc Nhập N và dãy các số nguyên ai Qui ước:
- Hình thoi biểu diễn thao tác so sánh
- Hình chữ nhật thể hiện 1 thao tác tính toán đơn giản hay phức tạp - Hình ô van thể hiện thao tác bắt đầu hay kết thúc.
Thí dụ 2: Sắp xếp bằng phương pháp tráo đổi (Exchange Sort) Đầu vào: Dãy A gồm N số nguyên a1, a2,…, aN
32
Ý tưởng
Với mỗi cặp số liên tiếp trong dãy , nếu số trước không lớn hơn số sau ta đổi chỗ chúng cho nhau.
Việc đó được lặp cho đến khi không có sự đổi chỗ nào cho nhau.
Thuật toán
B1: Nhập số N và dãy số a1,a2,…,aN B2: M N.
B3: Nếu M < 2 thì thuật toán kết thúc và hiển thị dãy đó. B4: M M – 1, i 0.
B5: Tăng i lên 1 đơn vị.
B6: Nếu i > M thì quay lại bước 3.
B7: Nếu ai > ai+1thì tráo đổi hai số đó cho nhau . B8: Quay lên bước 5.
Chú ý:
Thuật toán này tạo ra sau mỗi lượt sắp một phần tử đúng vị trí và phần tử này không còn tham gia vào quá trình sắp nữa. Nó giống như bọt nước nổi lên mặt nước: bóng nhẹ sẽ được đẩy dấn lên trên. Cũng chính vì thế mà sắp xếp tráo đổi còn có tên “nổi bọt” (Bubble Sort).
Quá trình được lặp lại với dãy sau khi đã bỏ phần tử cuối dãy, do vậy lúc đầu M được gán với giá trị N và dừng khi M < 2.
Trong thuật toán trên, i được khởi tạo giá trị 0 và tiến tới M + 1 Với thuật toán trên, cách biểu diễn theo sơ đồ khối như sau:
33 M ¬ N M < 2 i > M ai « ai+1 S Đ S S M ¬ M – 1 i ¬ 0 i ¬ i + 1 ai > ai+1 Đ Đ Kết thúc, dãy đã sắp xếp xong Nhập N và N số ai
Ngoài cách biểu diễn theo kiểu liệt kê hay sơ đồ khối, còn nhiều cách biểu diễn khác. Xu hướng chung hiện nay là sử dụng các ngôn ngữ lập trình như Pascal, C/C++ hay Java. Tuy nhiên, không nhất thiết phải sử dụng đúng ký pháp của các ngôn ngữ đó mà có thể được bỏ một số ràng buộc.
Cũng có khi người ta dùng một giả ngữ gọi là ngôn ngữ mô phỏng chương trình PDL (Programming Description Language).
Điều quan trọng của giải thuật mà chúng ta công nhận ở đây là giải thuật phải thoả mãn 3 tiêu chí sau:
1. Tính hữu hạn: giải thuật phải dừng sau một thời gian hữu hạn. 2. Khi kết thúc, giải thuật phải cung cấp kết quả đúng đắn.
3. Tính hiệu quả: thời gian tính toán nhanh, sử dụng ít tài nguyên không gian như bộ nhớ, thiết bị,… Hơn nữa, giải thuật cần mang tính phổ dụng, dễ hiểu, dễ cài đặt và mở rộng cho các lớp bài toán khác.
Theo phong cách lập trình cấu trúc, người ta khuyến cáo, giải thuật được xây dựng với 3 cấu trúc cơ bản sau:
34 Các bước được thực hiện theo 1 trình tự tuyến tính, hết bước này đến bước khác
Bước 1
Bước 2
Bước n
...
2. Cấu trúc rẽ nhánh
Việc thực hiện bước nào phụ thuộc vào điều kiện xác định. Thí dụ tìm max của 2 số a, b. Nếu a > b thì max là a, ngược lại max sẽ là b. Theo cách biểu diễn giải thuật ta có thể mô tả như sau:
B1: Nhập 2 số a, b.
B2: Nếu a > b thì max = a và đi đến bước kết thúc (B4). B3: max = b (a < b).
B4: Kết thúc.
Cấu trúc rẽ nhánh này thường được biểu diễn dưới dạng sơ đồ như sau:
Max = a Max = b
a > b
S Đ
Cấu trúc rẽ nhánh (2 nhánh) có thể mở rộng cho nhiều nhánh 3. Cấu trúc lặp
Một tác động/ nhiệm vụ có thể được thực hiện lặp nhiều lần. Tuy nhiên số lần lặp phải hữu hạn, và số lần lặp có thể biết trước hoặc không biết trước. Thí dụ tìm số lớn nhất của 1 dãy có n số. Để thực hiện yêu cầu này, ta lần lượt phải so sánh số max tạm thời (lúc đầu max được gán bằng phần tử thứ nhất, a1) với ai, với i từ 2, 3,…, n. Việc so sánh này được thực hiện lặp nhiều lần giữa max và ai. Khi kết thúc quá trình lặp, ta sẽ thu được số max, số lớn nhất của dãy n số.
Sơ đồchung của cấu trúc lặp:
Đ Bắt đầu Điều kiện Thực hiện Kết thúc S
35
Chƣơng trình = Giải thuật + Cấu trúc dữ liệu