Giáo trình Cấu trúc dữ liệu và giải thuật - Chương 1: Giới thiệu

Thông thường phần quan trọng nhất của quá trình phân tích thiết kế là chia vấn đề thành nhiều vấn đề nhỏ dễ hiểu và chi tiết hơn. Nếu chúng vẫn còn khó hiểu, chúng lại được chia nhỏ hơn nữa. Trong bất kỳ một tổ chức nào, người quản lý cao nhất cũng không thể quan tâm đến mọi chi tiết cũng như mọi hoạt động. Họ cần tập trung vào mục tiêu và các nhiệm vụ chính, họ chia bớt trách nhiệm cho những người cộng sự dưới quyền của họ. Việc lập trình trong máy tính cũng tương tự. Ngay cả khi dự án đủ nhỏ cho một người thực hiện từ đầu tới cuối, việc chia nhỏ công việc cũng rất quan trọng. Phương pháp phân tích thiết kế hướng đối tượng dựa trên quan điểm này. Cái khó nhất là định ra các lớp sao cho mỗi lớp sau này sẽ cung cấp các đối tượng có các hành vi đúng như chúng ta mong đợi. Việc lập trình giải quyết bài toán lớn của chúng ta sẽ được tập trung vào những giải thuật lớn. Chương trình khi đó được xem như một kịch bản, trong đó các đối tượng sẽ được gọi để thực hiện các hành vi của mình vào những lúc cần thiết. Chúng ta không còn phải lo bị mất phương hướng vì những chi tiết vụn vặt khi cần phải phác thảo một kịch bản đúng đắn, một khi chúng ta đã tin tưởng hoàn toàn vào khả năng hoàn thành nhiệm vụ của các lớp mà chúng ta đã giao phó.

 

pdf16 trang | Chuyên mục: Cấu Trúc Dữ Liệu & Giải Thuật | Chia sẻ: tuando | Lượt xem: 471 | Lượt tải: 0download
Tóm tắt nội dung Giáo trình Cấu trúc dữ liệu và giải thuật - Chương 1: Giới thiệu, để xem tài liệu hoàn chỉnh bạn click vào nút "TẢI VỀ" ở trên
ất, 
4. Các khai báo bên trong một lớp CTDL. 
Lớp CTDL cung cấp các thao tác dữ liệu thông qua các phương thức được 
khai báo là public. 
Tất cả những thuộc tính và các hàm còn lại luôn được khai báo private 
hoặc protected. 
Các thuộc tính của một lớp CTDL có thể được phân làm hai loại: 
• Thuộc tính bắt buộc phải có để lưu dữ liệu. 
Chương 1: Giới thiệu 
Giáo trình Cấu trúc dữ liệu và Giải thuật 12/16 
• Thuộc tính mà đối tượng cần có để tự quản lý, trong số này có thuộc tính 
được bổ sung chỉ để đẩy nhanh tốc độ của các thao tác dữ liệu. 
Các hàm được che dấu bên trong lớp được gọi là các hàm phụ trợ (auxilary 
function), chúng chỉ được sử dụng bởi chính các phương thức của lớp CTDL 
đó mà thôi. 
Việc mở rộng thêm các tác vụ cho một lớp có sẵn có thể theo một trong 
hai cách: 
• Bổ sung thêm phương thức mới. 
• Xây dựng lớp thừa kế. 
5. Một số hướng dẫn cần thiết trong việc thử nghiệm chương trình. 
9 Bộ chương trình thử (driver): Đây là đoạn chương trình thường được viết 
trong hàm main và chứa một thực đơn (menu) cho phép thử mọi phương 
thức của lớp CTDL đang được xây dựng. 
Chúng ta sẽ viết, thử nghiệm, và hoàn chỉnh nhiều lớp CTDL khác nhau. 
Do đó ngay từ đầu chúng ta nên xây dựng một driver sao cho tổng quát, khi 
cần thử với một CTDL nào đó chỉ cần chỉnh sửa lại đôi chút mà thôi. 
Trong driver chúng ta nên chuẩn hóa việc đọc ghi tập tin, xử lý các thao 
tác đọc từ bàn phím và xuất ra màn hình. Phần còn lại là một menu cho 
phép người sử dụng chạy chương trình chọn các chức năng như tạo đối 
tượng CTDL mới, gọi các thao tác thêm, xóa, tìm kiếm, truy xuất, trên 
CTDL đó. 
9 Các mẩu tạm (stub): đây là một mẹo nhỏ nhưng rất hữu ích. Để dịch và 
chạy thử một vài phần nhỏ đã viết, những phần chưa viết của chương trình 
sẽ được tạo như những mẩu nhỏ và chỉ cần hợp cú pháp (Xem ứng dụng 
tính toán các đa thức trong chương 15). 
Ví dụ: Trong đoạn chương trình nào đó chúng ta đang muốn chạy thử mà 
có sử dụng lớp A, hàm B,, chúng ta sẽ tạm khai báo các stub: 
class A 
{ 
}; // Một lớp chưa có thuộc tính vì chúng ta chưa quyết định nên chọn 
kiểu thuộc tính như thế nào. 
void B() 
{ 
} // Một hàm với thân hàm còn rỗng mà chúng ta hẹn sẽ viết sau. 
Nếu một hàm đã có định nghĩa thì chỉ cần trả về sao cho hợp lệ: 
Chương 1: Giới thiệu 
Giáo trình Cấu trúc dữ liệu và Giải thuật 13/16 
int C() 
{ 
 return 1; 
} // chỉ cần cẩn thận trong trường hợp nếu như giá trị trả về lại được 
dùng trong một biểu thức luận lý để xét điều kiện lặp vòng thì có 
khả năng vòng lặp không được thực hiện hoặc lặp vô tận. 
9 Cách thức theo dõi một chương trình đang chạy hoặc nhu cầu khảo sát cách 
làm việc của một trình biên dịch nào đó: 
Ví dụ gợi ý: 
void D() 
{ 
 count << “\n Hàm D đang được gọi \n”; 
} 
Trong C++ các hàm constructor và destructor được trình biên dịch gọi khi 
một đối tượng vừa được tạo ra hoặc sắp bị hủy. Vậy nếu có thắc mắc về thứ 
tự gọi các hàm này của một lớp thừa kế từ lớp khác, chúng ta có thể dùng 
cách tương tự để viết trong constructor và destructor của từng lớp cha, con. 
Nếu chúng ta có thắc mắc về cách ứng xử của trình biên dịch khi gọi các 
hàm này hay các hàm được định nghĩa đè (overloaded, overwriten) trong 
trường hợp các lớp thừa kế lẫn nhau, hoặc một số trường hợp khác nào đó, 
thì đây là cách hay nhất để chúng ta tự kiểm nghiệm lấy. 
Phần lớn các giải thuật được nghiên cứu trước hết chỉ dựa trên ý tưởng 
(biểu diễn bằng ngôn ngữ giả và độc lập với mọi ngôn ngữ lập trình). Tuy 
nhiên khi hiện thực chúng ta thường gặp vướng mắc ở chỗ mỗi ngôn ngữ 
lập trình có một số đặc điểm khác nhau, và ngay cả khi dùng chung một 
ngôn ngữ, các trình biên dịch khác nhau (khác hãng sản xuất hay khác 
phiên bản) đôi khi cũng ứng xử khác nhau. Điều đó gây rất nhiều khó khăn 
và lãng phí thời gian của nhiều sinh viên. 
Chỉ cần lấy một ví dụ đơn giản, đó là việc đọc ghi file, việc thường xuyên 
phải cần đến khi muốn thử nghiệm một giải thuật nào đó. Các vòng lặp 
thường nhầm lẫn ở điều kiện kết thúc file trong ngôn ngữ C++, mà điều 
này hoàn toàn phụ thuộc vào việc xử lý con trỏ file của trình biên dịch. 
Ngay một phần mềm như Visual C++ hiện tại cũng chứa cùng lúc trong thư 
viện không biết bao nhiêu lớp phục vụ cho việc khai báo và đọc ghi file. 
Chúng ta chỉ có thể sử dụng một trong các thư viện đó một cách chính xác 
sau khi đã tìm hiểu thật kỹ! Một ví dụ khác cũng hay gây những lỗi mất 
rất nhiều thời gian, đó là việc so sánh các trị: NULL, ‘0’, ‘\0’, 0,  mà nếu 
không khảo sát kỹ chúng ta sẽ bị trả giá bởi sự chủ quan cho rằng mình đã 
hiểu đúng quy ước của trình biên dịch. 
Chương 1: Giới thiệu 
Giáo trình Cấu trúc dữ liệu và Giải thuật 14/16 
Việc tìm đọc tài liệu kèm theo trình biên dịch là một việc làm cần thiết, nó 
cho chúng ta sự hiểu biết đầy đủ và chính xác. Nhưng để rút ngắn thời gian 
thì gợi ý trên đây cũng là một lời khuyên quý báu. Không gì nhanh và 
chính xác bằng cách tìm câu trả lời trong thử nghiệm. Việc sửa đổi chương 
trình như thế nào để có được các stub thỏa những nhu cầu cần thử nghiệm 
là tùy thuộc vào sự tích cực, say mê và sáng tạo của sinh viên. 
9 Gỡ rối chương trình (debug) 
Đây là khả năng theo vết chương trình ở những đoạn mà người lập trình 
còn nghi ngờ có lỗi. Bất cứ người lập trình nào cũng có lúc cần phải chạy 
debug. Vì vậy tốt hơn hết là ngay từ đầu sinh viên nên tìm hiểu kỹ các khả 
năng của công cụ debug của trình biên dịch mà mình sử dụng (cho phép 
theo dõi trị các biến, lịch sử các lần gọi hàm,). 
Một gợi ý trong phần này là sinh viên cần biết cách cô lập từng phần của 
chương trình đã viết bằng cách dùng ký hiệu dành cho phần chú thích 
(comment) để khóa bớt những phần chưa đến lượt kiểm tra. Hoặc khi lỗi do 
trình biên dịch báo có vẻ mơ hồ, thì cách cô lập bằng cách giới hạn dần 
đoạn chương trình đang dịch thử sẽ giúp chúng ta sớm xác định được phạm 
vi có lỗi. Cũng có thể làm ngược lại, chỉ dịch thử và chỉnh sửa từng đoạn 
chương trình nhỏ, cho đến khi hết lỗi mới nới dần phạm vi chương trình để 
dịch tiếp. 
1.6. Giới thiệu về ngôn ngữ giả: 
Phần lớn chương trình được trình bày trong giáo trình này đều sử dụng ngôn 
ngữ C++, sau khi ý tưởng về giải thuật đã được giải thích cặn kẽ. Phần còn lại có 
một số giải thuật được trình bày bằng ngôn ngữ giả. 
Ngôn ngữ giả, hay còn gọi là mã giả (pseudocode), là một cách biểu diễn độc 
lập với mọi ngôn ngữ lập trình, nó không ràng buộc sinh viên vào những cú pháp 
nghiêm ngặt cũng như cách gọi sao cho chính xác các từ khóa, các hàm có trong 
thư viện một trình biên dịch nào đó. Nhờ đó sinh viên có thể tập trung vào ý 
tưởng lớn của giải thuật. 
Các quy định về mã giả được sử dụng trong giáo trình này: 
¾ Biểu diễn sự tuần tự của các lệnh chương trình: các lệnh được thực thi tuần tự 
lệnh này sang lệnh khác sẽ có cùng khoảng cách canh lề như nhau và được 
đánh số thứ tự tăng dần, luôn bắt đầu từ 1. 
Chương 1: Giới thiệu 
Giáo trình Cấu trúc dữ liệu và Giải thuật 15/16 
¾ Cấu trúc khối lồng nhau: một khối nằm trong một khối khác sẽ có khoảng 
cách canh lề lớn hơn. 
Trong giáo trình này, chỉ những phần được trình bày bằng mã giả mới có số 
thứ tự ở đầu mỗi dòng lệnh. 
Ví dụ: 
 1. 
 1. 
 2. 
 1. // Đây là dòng lệnh có số thứ tự là 1.2.1 
 2. 
 3. 
 2. 
 1. 
 3. 
 1. 
 2. 
¾ Sự rẽ nhánh: chúng ta sử dụng các từ khóa: 
• if 
endif 
• if 
else 
 endif 
• case 
case1:  
case2:  
case3:  
else:  
 endcase 
¾ Sự lặp vòng: 
• loop 
endloop // lặp trong khi biểu thức luận lý còn đúng. 
• repeat 
until // lặp cho đến khi biểu thức luận lý 
đúng. 
Chương 1: Giới thiệu 
Giáo trình Cấu trúc dữ liệu và Giải thuật 16/16 
¾ Khai báo hàm: 
 tên hàm (danh sách thông số) 
trong đó danh sách thông số: val/ ref tên thông số, val/ ref 
 tên thông số, 
val: dành cho tham trị; ref: dành cho tham biến. 
¾ Khai báo cấu trúc, lớp: 
 struct tên kiểu dữ liệu cấu trúc 
 end struct 
 class tên kiểu dữ liệu cấu trúc 
 end class 
¾ Khai báo phương thức của lớp: 
 tên lớp::tên hàm (danh sách thông số); 
¾ Khai báo biến: 
 tên biến 
Một chút lưu ý về cách trình bày trong giáo trình: 
Do các đoạn chương trình sử dụng font chữ Courier New, nên các tên biến, 
tên lớp, tên đối tượng, tên các hàm khi được nhắc đến cũng dùng font chữ này. 
Các từ tiếng Anh khác được in nghiêng. Đặc biệt những phần có liên quan chặt 
chẽ đến những đặc thù của ngôn ngữ lập trình C++ thường dùng kích cỡ chữ nhỏ 
hơn, để phân biệt với những phần quan trọng khác khi nói về ý tưởng và giải 
thuật, và đó mới là mục đích chính của môn học này. 
Có một số từ hay đoạn được in đậm hay gạch dưới nhằm giúp sinh viên đọc dễ 
dàng hơn. 

File đính kèm:

  • pdfgiao_trinh_cau_truc_du_lieu_va_giai_thuat_chuong_1_gioi_thie.pdf