Đặt tên cho biến: Tự xác định cho mình một phong cách đặt tên cho biến.: Nếu là hằng thì luôn viết hoa Từ thứ nhất của biến không viết hoa.. Tên biến có tính gợi nhớ cao: Ví dụ:
Trang 1BÀI TỰ CHỮA PHẦN BINARY TREE
I Phong cách lập trình: Phần làm có nhiều điểm sửa những cái nho nhỏ Mong cô đọc
hết Tuy chỉ nhỏ thôi nhưng em thấy cũng quan trọng
1 Kỹ thuật làm việc với biến.
Đặt tên cho biến: Tự xác định cho mình một phong cách đặt tên cho biến.:
Nếu là hằng thì luôn viết hoa
Từ thứ nhất của biến không viết hoa Các từ còn lại viết hoa và viết liền với nhau Ví dụ: typeNode hoặc valueNode
Dùng danh từ hoặc cụm danh từ đặt tên cho biến
Tên biến có tính gợi nhớ cao: Ví dụ: Trước đây để đặt tên cho một biến thể hiện biến đó là giá trị của Node: thì đặt luôn là Node trong khi đó loại giá trị của node lại đặt là type Sau đó đặt lại là valueNode và typeNode
Khởi tạo biến
Luôn tránh việc dùng biến global một cách tối đa có thể
Hầu hết các biến được khởi tạo ngay sau khi khai báo so với việc trước đây thường khá ít làm Ví dụ: BinaryTree::node *root = NULL
2 Kỹ thuật viết mã chương trình hiệu quả.
Version 1 viết liền một mạch không có cách dòng giữa các phần chính Như khai báo biến Phần viết hàm Hàm main … Giữa các hàm cũng không có dấu cách
để phân biệt
Version 2 có khoảng cách giữa các phần rõ ràng Những phần chung xếp lại cạnh nhau như các contructor, setter,…Giữa các chức năng cụ thể có để lại những khoảng phân biện
Ví dụ InitBinaryTree _
//tất cả các hàm về khởi tạo cây ở đây _DuyetTruoc
Hàm duyệt trước để ở đây …
Đối với khoảng cách giữa các từ:
Ví dụ: version 1
node *SearchNode(node *root,char *type,ValueNode *valueNode);
node *SearchNode(node *root, char *type, ValueNode *valueNode);
Có khoảng cách giữa các từ sau dấu , hoặc dấu ;
Hoặc là khi có logic && version 2 đã chữa lại thành && có dấu cách giữa 2 &&
để dễ sửa hoặc dễ nhận ra sai các dấu ) hoặc ( mỗi khi có lỗi
Hình thành thói quen viết: ví dụ: a=a+b; viết thành a = a + b; có dấu cách để dễ nhìn
Version 2: Luôn để dấu () khi có phép logic đôi khi cũng hơi máy móc
Viết các biểu thức và phép toán theo đúng ý nghĩa:
Version 1 viết: if(!root){ }
->if(root != NULL)
Trang 2II Hàm , Chương trình con
1 Vấn đề rút gọn thành 1 hàm: version 1 có khá nhiều đoạn trùng mà hoàn toàn có thể tạo thành 1 hàm riêng biệt để có thể sử dụng
switch(*typeNode){
case 'i':
cin>>(valueNode->dataInt);
break;
case 'o':
cin>>(valueNode->op);
break;
default:
break; }
Đoạn này được sử dụng lại 3 lần trong hàm Input Và 1 lần trong hàm InitBinaryTree khi khỏi tạo root ( lúc đầu) -> đổi thành 1 hàm InputValueNode
void BinaryTree::InputValueNode(char *typeNode, BinaryTree::ValueNode
*valueNode){
switch(*typeNode){
case 'i':
cin>>(valueNode->dataInt);
break;
case 'o':
cin>>(valueNode->op);
break;
default:
break; }
}
Khi đó chỉ gọi hàm và truyền tham số
2 Một hàm chỉ làm một nhiệm vụ: Version 2 phân chia thành nhiều hàm hơn Mỗi hàm chỉ thực hiện 1 nhiệm vụ Ví dụ hàm nhập Input chỉ thực hiện việc nhâp sau đó có hàm test
để kiểm tra giá trị nhập Không cho hàm vừa kiểm tra vừa nhập Vấn đề này là một vấn
đề rất hay đã giúp em rất nhiều để chương trình đơn giản, dễ sửa và sử dụng lại được các hàm đó
3 Version 1 khi viết các hàm ko có một lời giải thích Chỉ viết hàm và nói qua về mục đích làm gì Không nói rõ dl đầu vào Và đầu ra cụ thể làm gì Khi viết như thế đã rất nhiều lần viết hàm xong rồi lại cho thêm một nhiệm vụ khác vào hàm đó, rồi lại thêm Cuối cùng nhiệm vụ của hàm lại bị đẩy sang một hướng khác Cho nên khi viết hàm thì sẽ nêu rõ mục đích của hàm đó Đầu ra và đầu vào tương ứng với thực hiện một nhiệm vụ
cụ thể
4 Version 2 viết theo kiểu top down, modun hóa dần Phân chia các hàm cụ thể không bị trùng code như version 1 Không viết tự phát ( chỉ để suy nghĩ trong đầu) rồi viết như version 1
III Những điểm cải tiến so với version 1
1 Sử dụng c++:
Chương trình version 1 sử dụng c để viết Các dữ liệu của node khai báo bằng struct Version 2 viết bằng c++ khai báo lớp BinaryTree Các thuộc tính của node đều ở trong lớp
2 Vấn đề thuộc tính
Trang 3Version 1 khai báo node chỉ có giá trị kiểu số nguyên không có kiểu char để thể hiện node cũng có thể là toán tử.( Không đúng với yêu cầu của đề bài
Version 2 viết lại các thuộc tính là kiểu hợp union có thể chứa cả 2 kiểu int là toán hạng và char là toán tử
union {
int dataInt;
char op;
}Node;
3 Vấn đề đệ quy
Trong version 1 dùng thuật toán khử đệ quy đối với tất cả các chức năng là duyệt trước, sau , giữa và cả kiểm tra xem đó có phải là cây biểu thức không Thuật toán khá lằng nhằng và tương đối là khó hiểu Nếu người khác test thì tương đối là khó
để phát hiện ra lỗi và sửa Nhưng nó lại nhanh nếu làm nhiều node so với kiểu đệ quy
Khai báo thêm một struct stack để khử đệ quy
Version 2 sử dụng đệ quy nên không có stack Rất dễ hiểu Rất dễ để test lỗi
Ví dụ: Hàm duyệt trước:
void BinaryTree::DuyetTruoc(BinaryTree::node *root){
if(root!=NULL){
displayNode(root);
DuyetTruoc(root->leftPointer);
DuyetTruoc(root->rightPointer);
}
}//_end_DuyetTruoc
4 Thuật toán khởi tạo cây:
Version 1 sử dụng cho người dùng nhập vào một giá trị n Và chương trình sẽ tự khởi tạo một cây có n nút Và cây đó là cây nhị phân đầy đủ Khi đó phải sử dụng thêm một queue để thực hiện thuật toán này
Version 2 dùng thuật toán cho phép người dùng nhập vào từng node một Như thế sẽ đúng ý của người dùng hơn Nhưng không có đồ họa người dùng phải tự
vẽ cây ra giấy để biết cây như nào để có thể nhập tiếp theo( Do visual c++ khônng có đồ họa của c++ )