Tải bản đầy đủ (.docx) (23 trang)

BÀI TẬP NHÓM MÔN HỌC IT3040 – KỸ THUẬT LẬP TRÌNH

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (406.13 KB, 23 trang )

BÀI TẬP LỚN KSTN-CNTT
dn
Nguyễn Văn Thiện – Lê Anh Vũ – Vũ Văn Tú – Nguyễn Hoàng Hải Đỗ Quốc Đạt Page 1
TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI
VIỆN CÔNG NGHỆ THÔNG TIN VÀ TRUYỀN THÔNG
BÀI TẬP NHÓM MÔN HỌC
IT3040 – KỸ THUẬT LẬP TRÌNH 2012-2013
Giảng viên hướng dẫn : PGS. TS. Huỳnh Quyết Thắng
Nhóm học viên : Nguyễn Hoàng Hải
Nguyễn Văn Thiện
Vũ Văn Tú
Lê Anh Vũ
Đỗ Quốc Đạt
Lớp: KSTN_CNTT_K56
HÀ NỘI 2013
Hà Nội, 05/2013
BÀI TẬP LỚN
BÀI TẬP LỚN KSTN-CNTT

MỤC LỤC
Nguyễn Văn Thiện – Lê Anh Vũ – Vũ Văn Tú – Nguyễn Hoàng Hải Đỗ Quốc Đạt Page 2
BÀI TẬP LỚN KSTN-CNTT
I.
GIỚI THIỆU VÀ ỨNG DỤNG CỦA CÂY NHỊ PHÂN
1.
Định nghĩa:
1.1.
Cây
Là đồ thị có hướng, lien thông và không có chu trình. Cây bao gồm các nút, có một nút đặc biệt
gọi là gốc (root) và các cạnh nối các nút.
1.2.


Cây nhị phân:
Là cây mà mỗi nút có nhiều nhất là 2 con (con trái và con phải). Mỗi nút hoặc không có con,
hoặc chỉ có con trái, hoặc chỉ có con phải, hoặc có cả con trái con phải.

Cây nhị phân suy biến có dạng:

Cây nhị phân đầy đủ: là cây nhị phân thõa mãn mỗi nút lá đề có cùng độ sâu và các nút
có đúng 2 con.

Cây nhị phân hoàn chỉnh : là cây nhị phân mà các nút ở các mức trừ mức cuối đều đạt
tối đa.
Nguyễn Văn Thiện – Lê Anh Vũ – Vũ Văn Tú – Nguyễn Hoàng Hải Đỗ Quốc Đạt Page 3
BÀI TẬP LỚN KSTN-CNTT
Cây hoàn chỉnh Cây đầy đủ
2.
Tính chất

Số lượng nút tối đa trên mức i của cây nhị phân là 2
i-1
, tối thiểu là 1 (i≥1).

Một cây nhị phân chiều cao h có không quá 2
k
-1 nút, k≥1.

Một cây nhị phân có n nút có chiều cao tối thiểu là [log
2
(n+1)].
3.
Biểu diễn cây nhị phân.


Biểu diễn bằng mảng:
Với cây nhị phân đầy đủ, ta đánh số các nút từ 1 trở đi, hết mức này đến mức khác, từ trái qua
phải. Dùng mảng V lưu trữ cây nhị phân , nút thứ i của cây được lưu trữ ở phần tử V(i).

Ví dụ với cây đày đủ ở trên được lưu trữ như sau:


Biểu diễn bằng con trỏ:
Trong cách lưu trữ này , mỗi nút ứng với một phần tử nhớ có quy cách như sau:

LPTR INFO RPTR
Nguyễn Văn Thiện – Lê Anh Vũ – Vũ Văn Tú – Nguyễn Hoàng Hải Đỗ Quốc Đạt Page 4
BÀI TẬP LỚN KSTN-CNTT
LPTR : Con trỏ trỏ tới cây con trái của nút đó
RPTR : Con trỏ trỏ tới cây con phải của nút đó
INFO : Trường thông tin.

Ví dụ cây nhị phân sau đây:
4.
Các thao tác trên cây nhị phân:
4.1.
Cấu trúc:
typedef struct TreeNode {
char key[20];
struct TreeNode *lChild;
struct TreeNode *rChild;
}TreeNode;
4.2.
Tạo nút:

TreeNode *getNode(char *key){
TreeNode *tempNode;
tempNode=(TreeNode*)malloc(sizeof(TreeNode));
tempNode->lChild=NULL;
tempNode->rChild=NULL;
tempNode->key=key;
return tempNode;
}
4.3.
Tính số nút và chiều sâu của cây
Nguyễn Văn Thiện – Lê Anh Vũ – Vũ Văn Tú – Nguyễn Hoàng Hải Đỗ Quốc Đạt Page 5
BÀI TẬP LỚN KSTN-CNTT
int countNode(TreeNode *root){
if(root==NULL) return 0;
else{
int ld=countNode(root->lChild);
int rd=countNode(root->rChild);
return 1+ld+rd;
}
}
4.4.
Duyệt cây theo thứ tự trước NLR (preoder Traversal)
Void printPreoder(TreeNode *root){
if(root!=NULL){
printf(“%s\n”,root->key);
printPreoder(root->lChild);
printPreoder(root->rChild);
}
}
4.5.

Duyệt cây theo thứ tự giữa LNR (inoder Traversal)
Void printInoder(TreeNode *root){
if(root!=NULL){
printInoder(root->lChild);
printf(“%s\n”,root->key);
printInoder(root->rChild);
}
}
4.6.
Duyệt cây theo thứ tự sau LRN (postoder Traversal)
void printPostoder(TreeNode *root){
if(root!=NULL){
printPostoder(root->lChild);
printPostoder(root->rChild);
printf(“%s\n”,root->key);
}
}
Nguyễn Văn Thiện – Lê Anh Vũ – Vũ Văn Tú – Nguyễn Hoàng Hải Đỗ Quốc Đạt Page 6
BÀI TẬP LỚN KSTN-CNTT
II.
Bài toán đặt ra
1. Giới thiệu:
Nếu một nút trong một cây nhị phân hoặc không có con trái hoặc không có con phải hoặc là nút
lá thì con trỏ trái hoặc phải của nút đó có giá trị NULL. Một cách tránh con trỏ NULL đó là sử
dụng con trỏ này thay vì chứa giá trị NULL nó sẽ trỏ đến nút cao hơn trong cây đó là nút tổ
tiên. Một ví dụ cho thao tác này là việc cài đặt threaded binary tree, đây là cây nhị phân mà
trong đó các nút chứa con trỏ NULL sẽ được trỏ đến inorder predecessor(nút ngay trước nút
đang xét trong thứ tự giữa hoặc trỏ đến inorder sucecssor(nút ngay sau trong thứ tự giữa).
Bằng cách này, chúng ta có thể duyệt cây mà không cần dùng đệ quy.
Cấu trúc của cây này khác một chút so với cây nhị phân:

typedef struct TreeNode {
char key;
struct TreeNode *lChild;
struct TreeNode *rChild;
int lFlag;//TRUE neu lChild tro toi con, FALSE neu toi thread
int rFlag;//TRUE neu rChild tro toi con, FALSE neu toi thread
}TreeNode;
Xét cây nhị phân hình bên:
(Các luồng liên kết đặc biệt thể hiện
bằng mũi tên đứt.)
Nguyễn Văn Thiện – Lê Anh Vũ – Vũ Văn Tú – Nguyễn Hoàng Hải Đỗ Quốc Đạt Page 7
BÀI TẬP LỚN KSTN-CNTT
Khi duyệt cây theo thứ tự giữa ta được:
Ta hãy xét tiếp ví dụ:
Chuyển cây nhị phân sau thành cây TBT:
Duyệt cây theo thứ tự giữa: DBAEC. Vì vậy cây TBT tương ứng:
B không có con phải vì vậy có một luồng trỏ đến A là nút inorder successor. Tương tự các nút D và E.
Nút C không có con phải nhưng nó không có nút inorder successor để trỏ tới vì vậy nó có một luồng
Nguyễn Văn Thiện – Lê Anh Vũ – Vũ Văn Tú – Nguyễn Hoàng Hải Đỗ Quốc Đạt Page 8
BÀI TẬP LỚN KSTN-CNTT
không trỏ đến đâu.
2. Duyệt cây theo không dùng đệ quy
2.1 Thuật toán.
2.1.1 Duyệt theo thứ tự giữa
Bước 1: Tại nút hiện tại, tìm nút P ngay trước nó trong thứ tự giữa. Nếu P không có
con phải thì P->rChild được sửa lại để trỏ đến nút hiện tại
Bước 2: Từ nút hiện tại, gán
currentNode=currentNode->lChild (rẽ trái) hết
mức có thể, mỗi lần chuyển nút lại gọi đến hàm ở bước 1 để tìm các threads.
Bước 3: In ra nút hiện tại, nút này không thể rẽ trái được nữa do bước 2.

Bước 4: Tại nút vừa in ra, kiểm tra rChild là con thật sự hay thread. Nếu là thread,
gán
currentNode=currentNode->rChild và in ra nút đó. Nếu là con thực sự,
gán currentNode=currentNode->rChild
Xét ví dụ trên:
Nguyễn Văn Thiện – Lê Anh Vũ – Vũ Văn Tú – Nguyễn Hoàng Hải Đỗ Quốc Đạt Page 9
BÀI TẬP LỚN KSTN-CNTT
Bước 1
Tại nút A, ta tìm được B là nút ngay sau A trong thứ tự giữa, ta sửa lại con trỏ phải của B đến A
Bước 2
Rẽ trái qua B, sửa lại con trỏ phải của D, rẽ trái tiếp đến D
Bước 3
D không có con trái, không rẽ tiếp được nữa,i
n raD
Bước 4 Kiểm tra con trỏ phải của D không là con thực sự nên ta gán lại nút hiện tại là B và in ra B
Bước 5 Kiểm tra con trỏ phải của B không là con thực sự nên ta gán lại nút hiện tại là A và in ra A
Bước 6 Kiểm tra con trỏ phải của A là con thực sự nên ta gán lại nút hiện tại là C và quay lại bước 1 với nút hiện tại là
C
Bước 7 Rẽ trái hết mức đến E. In ra E
Bước 8 Con trỏ phải của E chỉ đến NULL nên ta kết thúc
void inorder(TreeNode *root){
TreeNode *currentNode, *tempNode;
currentNode=root;
while(currentNode!=NULL){ /*Nut cuoi cung trong thu tu giua se
co *rChild bang NULL va sau
lastNode->rChild vong lap ket thuc*/
tempNode=findInorderPre(currentNode); /*Tim nut nhan
currentNode lam right
thread, gan lai
rChild cua nut do*/

/*Re trai lien tuc den khi gap nut khong co con trai thi in ra*/
while(currentNode->lFlag==TRUE&&currentNode->lChild!=NULL){
currentNode=currentNode->lChild;
tempNode=findInorderPre(currentNode);
}
printf("%c ",currentNode->key);
/*Chung nao rChild con la thread thi in ra*/
while(currentNode->rFlag==FALSE&&currentNode->rChild!=NULL) {
currentNode=currentNode->rChild;
printf("%c ",currentNode->key);
}
/*Neu rChild chi den con thuc su thi re phai*/
currentNode=currentNode->rChild;
}
halt();//Dung man hinh
}
Nguyễn Văn Thiện – Lê Anh Vũ – Vũ Văn Tú – Nguyễn Hoàng Hải Đỗ Quốc Đạt Page 10
BÀI TẬP LỚN KSTN-CNTT
2.1.2 Duyệt theo thứ tự trước
Bước 1: Tại nút hiện tại, tìm nút P ngay trước nó trong thứ tự giữa. Nếu P không có
con phải thì P->rChild được sửa lại để trỏ đến nút hiện tại. In ra nút hiện tại
Bước 2: Từ nút hiện tại, gán
currentNode=currentNode->lChild (rẽ trái) hết
mức có thể, mỗi lần chuyển nút lại gọi đến hàm ở bước 1 để tìm các threads đồng
thời in ra nút hiện tại.
Bước 3: Tại nút không thể rẽ trái được nữa, kiểm tra rChild là con thật sự hay thread.
Nếu là thread, gán
currentNode=currentNode->rChild. Nếu là con thực sự, gán
currentNode=currentNode->rChild rồi quay lai bước 1
Xét ví dụ trên:

Bước 1
Tại nút A, ta tìm được B là nút ngay sau A trong thứ tự giữa, ta sửa lại con trỏ phải của B đến A. In ra A
Bước 2
Rẽ trái qua B, sửa lại con trỏ phải của D, rẽ trái tiếp đến D. In ra B
Bước 3
D không có con trái, không rẽ tiếp được nữa. I
n raD
Bước 4 Kiểm tra con trỏ phải của D không là con thực sự nên ta gán lại nút hiện tại là B
Nguyễn Văn Thiện – Lê Anh Vũ – Vũ Văn Tú – Nguyễn Hoàng Hải Đỗ Quốc Đạt Page 11
BÀI TẬP LỚN KSTN-CNTT
Bước 5 Kiểm tra con trỏ phải của B không là con thực sự nên ta gán lại nút hiện tại là A
Bước 6 Kiểm tra con trỏ phải của A là con thực sự nên ta gán lại nút hiện tại là C và quay lại bước 1 với nút hiện tại là
C.
Bước 7 In ra C
Bước 8 Rẽ trái đến E. In ra E
Bước 9 Con trỏ phải của E chỉ đến NULL, ta kết thúc
void preorder(TreeNode *root){
TreeNode *currentNode, *tempNode;
currentNode=root;
while(currentNode!=NULL){ /*Nut cuoi cung trong thu tu giua se
co *rChild bang NULL va sau
lastNode->rChild vong lap ket thuc*/
tempNode=findInorderPre(currentNode); /*Tim nut nhan
currentNode lam right
thread,gan lai rChild
cua nut do*/
/*In ra nut hien tai, re trai het muc co the, di den dau in den do*/
printf("%c ",currentNode->key);
while(currentNode->lFlag==TRUE&&currentNode->lChild!=NULL){
currentNode=currentNode->lChild;

tempNode=findInorderPre(currentNode);
printf("%c ",currentNode->key);
}
/*Chung nao rChild con la thread thi nhay theo thread nhung khong in*/
while(currentNode->rFlag==FALSE&&currentNode->rChild!=NULL){
currentNode=currentNode->rChild;
Nguyễn Văn Thiện – Lê Anh Vũ – Vũ Văn Tú – Nguyễn Hoàng Hải Đỗ Quốc Đạt Page 12
BÀI TẬP LỚN KSTN-CNTT
}
/*Neu rChild chi den con thuc su thi re phai*/
currentNode=currentNode->rChild;
}
halt();
}
2.2 Cài đặt
Thao tác cài đặt gồm có :
-2 File header TreeNode.h : khai báo cấu trúc dữ liệu của các nút.
funclist.h : khai báo tất cả các hàm sẽ được sử dụng trong project
-File createtree.cpp dùng để tạo cây.
-File menu.cpp đưa ra giao diện sử dụng .
-File makethreads.cpp chuyển đổi cây có con trỏ null thành cây không còn con trỏ
null.
-File traversals.cpp có tác dụng duyệt cây sau khi chuyển đổi.
-File printtree.cpp dùng in cây sau mỗi lần nhập để người sử dụng dễ hình dung cho
thao tác nhập.
-File main.cpp là file chứa chương trình chính của project.
2.2.1 Cài đặt file header
TreeNode.h
Cài đặt cấu trúc dữ liệu TreeNode cho các nút trên cây, gồm 5 trường :
• Char key; kiểu dữ liệu lưu trữ trên mỗi nút.

• TreeNode *lChild; con trỏ trỏ về con trái của nút cha.
• TreeNode *rChild; con trỏ trỏ về con phải của nút cha.
Nguyễn Văn Thiện – Lê Anh Vũ – Vũ Văn Tú – Nguyễn Hoàng Hải Đỗ Quốc Đạt Page 13
BÀI TẬP LỚN KSTN-CNTT
• Int lFlag; có giá trị bằng TRUE nếu có con trỏ lChild chỉ đến con, FALSE nếu
tới luồng;
• Int rFlag; có giá trị bằng TRUE nếu có con trỏ rChild chỉ đến con, FALSE nếu
tới luồng;

Các trường lFlag và rFlag dùng thay cho các việc xét con trái là null hay con
phải là null vì sau khi chuyển đổi cây thì không còn con trỏ nào trỏ đến nút null
nữa.
#define TRUE 1
#define FALSE 0
typedef struct TreeNode {
char key;
struct TreeNode *lChild;
struct TreeNode *rChild;
int lFlag;//TRUE neu lChild tro toi con, FALSE neu toi thread
int rFlag;//TRUE neu rChild tro toi con, FALSE neu toi thread
}TreeNode;
funtlist.h
Chứa các hàm được sử dụng trong project
TreeNode *getNode(char key);\\ Tạo nút từ 1 ký tự
TreeNode *findInorderPre(TreeNode *node);\\ Tìm nút đứng trước trong duyệt theo thứ
tự giữa
TreeNode *findInorderSuc(TreeNode *node);\\ Tìm nút đứng sau trong duyệt theo thứ
tự giữa
void inorder(TreeNode *root);\\ Duyệt cây theo thứ thự giữa
void preorder(TreeNode *root);\\ Duyệt cây theo thứ thự trước

void postorder(TreeNode *root);\\ Duyệt cây theo thứ thự sau
void insert(TreeNode *r,TreeNode *temp);\\ Chèn 1 nút temp vào cây r
void insertTree(TreeNode **root);\\
int heading();
int menu();
Nguyễn Văn Thiện – Lê Anh Vũ – Vũ Văn Tú – Nguyễn Hoàng Hải Đỗ Quốc Đạt Page 14
BÀI TẬP LỚN KSTN-CNTT
void halt();
void nothingInput();
int getData();
void gotoxy(int x, int y);
int wherex();
int wherey();
void cls();
int drawNode(char value,int &x,int &y,int &l,int type,int position);
void printTree(TreeNode *root,int px,int py,int pl,int t_node);
2.2.2 Tạo cây và thêm nút vào cây
File dùng trong việc nhập kí tự từ bàn phím để tạo nút và chèn vào cây. Gồm có 2
hàm:
void insert(TreeNode*r,TreeNode*temp),void insertTree(TreeNode
**root);
insert(TreeNode*r,TreeNode*temp)
Hàm này có nhiệm vụ chọn xem nút in vào sẽ được in vào vị trí như thế nào so với
gốc . Ví dụ như nếu gốc là nút a và ta chọn thêm vào nút b thì chương trình sẽ hỏi bạn
muốn thêm vào bên trái hay phải của nút a. Sau khi chọn xong cây sẽ in ra cây cho ta
theo dõi.
insertTree(TreeNode**root)
Hàm này có nhiệm vụ yêu cầu nhập kí tự để tạo nút và thêm vào cây. Sau khi nhập
xong kí tự chương trình sẽ hỏi là bạn có muốn nhập tiếp hay không, nếu nhập kí tự ‘y’
thì chương trình sẽ cho nhập thêm còn nếu ‘n’ thì chương trình sẽ in ra cây.

Nguyễn Văn Thiện – Lê Anh Vũ – Vũ Văn Tú – Nguyễn Hoàng Hải Đỗ Quốc Đạt Page 15
BÀI TẬP LỚN KSTN-CNTT
2.2.3 Tạo luồng
Ý tưởng Cách tìm nút đứng ngay trước 1 nút P trong thứ tự giữa
TH1:Nếu nút P có con trái, ta đi đến con trái rồi từ đó rẽ phải chừng nào nút hiện tại
vẫn có con phải (rflag=TRUE), nút cần tìm là nút hiện tại. Tóm lại, nút cần tìm là nút
phải nhất của con trái. Ta gán lại currentNode->right=P
TreeNode *findInorderPre(TreeNode *node){
TreeNode *tempNode;
if(node->lFlag==FALSE) return node->lChild;
else{
tempNode=node->lChild;
while(tempNode->rFlag==TRUE){
tempNode=tempNode->rChild;
}
tempNode->rChild=node;
return tempNode;
}
Nguyễn Văn Thiện – Lê Anh Vũ – Vũ Văn Tú – Nguyễn Hoàng Hải Đỗ Quốc Đạt Page 16
BÀI TẬP LỚN KSTN-CNTT
}
TH2: Nếu nút P không có con trái (lflag=FALSE), con trỏ left sẽ phải trỏ đến nút ngay
trước nút P trong thứ tự giữa. Trong quá trình duyệt các nút tổ tiên của P, đã tồn tại 1
nút làm thao tác gán lại con trỏ left của P.Vì vậy kết quả là P->left:
TreeNode *findInorderSuc(TreeNode *node){
TreeNode *tempNode;
if(node->rFlag==FALSE) return node->rChild;
else{
tempNode=node->rChild;
while(tempNode->lFlag==TRUE){

tempNode=tempNode->lChild;
}
tempNode->lChild=node;
return tempNode;
}
}

2.2.4 Duyệt cây nhị phân
void inorder(TreeNode *root){
TreeNode *currentNode, *tempNode;
currentNode=root;
while(currentNode!=NULL){/*Nut cuoi cung trong thu tu giua se
co *rChild bang NULL va sau currentNode->rChild
vong lap ket thuc*/
tempNode=findInorderPre(currentNode);/*Tim nut nhan currentNode lam right
thread, gan lai rChild cua nut do*/
/*Re trai lien tuc den khi gap nut khong co con trai thi in ra*/
while(currentNode->lFlag==TRUE&&currentNode->lChild!=NULL){
currentNode=currentNode->lChild;
tempNode=findInorderPre(currentNode);
}
printf("%c ",currentNode->key);
/*Chung nao rChild con la thread thi in ra*/
while(currentNode->rFlag==FALSE&&currentNode->rChild!=NULL) {
currentNode=currentNode->rChild;
printf("%c ",currentNode->key);
Nguyễn Văn Thiện – Lê Anh Vũ – Vũ Văn Tú – Nguyễn Hoàng Hải Đỗ Quốc Đạt Page 17
BÀI TẬP LỚN KSTN-CNTT
}
/*Neu rChild chi den con thuc su thi re phai*/

currentNode=currentNode->rChild;
}
halt();
}
void preorder(TreeNode *root){
TreeNode *currentNode, *tempNode;
currentNode=root;
while(currentNode!=NULL){/*Nut cuoi cung trong thu tu giua se
co *rChild bang NULL va sau currentNode->rChild
vong lap ket thuc*/
tempNode=findInorderPre(currentNode);/*Tim nut nhan currentNode lam right
thread, gan lai rChild cua nut do*/
/*In ra nut hien tai roi re trai het muc co the, di den dau in den do*/
printf("%c ",currentNode->key);
while(currentNode->lFlag==TRUE&&currentNode->lChild!=NULL){
currentNode=currentNode->lChild;
tempNode=findInorderPre(currentNode);
printf("%c ",currentNode->key);
}
/*Chung nao rChild con la thread thi nhay theo thread nhung khong in*/
while(currentNode->rFlag==FALSE&&currentNode->rChild!=NULL){
currentNode=currentNode->rChild;
}
/*Neu rChild chi den con thuc su thi re phai*/
currentNode=currentNode->rChild;
}
halt();
}
void postorder(TreeNode *root){
if(root->lFlag==TRUE&&root->lChild!=NULL) postorder(root->lChild);

if(root->rFlag==TRUE&&root->rChild!=NULL) postorder(root->rChild);
printf("%c ",root->key);
}
2.2.5 In cây nhị phân
Ý tưởng: Việc in cây nhị phân ra màn hình cần thể hiện rõ được mối quan hệ giữa các
nút. Giả sử ta biểu diễn được 1 nút ra màn hình và nút này nằm tại vị trí (x,y) trên
Nguyễn Văn Thiện – Lê Anh Vũ – Vũ Văn Tú – Nguyễn Hoàng Hải Đỗ Quốc Đạt Page 18
BÀI TẬP LỚN KSTN-CNTT
màn hình. Khi đó, nếu nút này có con trái thì ta biểu diễn sao cho vị trí nút con trái
root->lChild nằm lệch so với nút cha 1 khoảng cách offset nào đó và nằm thấp hơn
nút cha. Giả sử ta có thể có toạ độ nút con trái là (x-offset,y-1). Tương tự, nút con phải
có tọa độ (x+offset,y-1).
Dùng đệ quy ta lại coi nút con trái (hoặc con phải) là nút đang xét và đệ quy in ra các
con của nó cho đến khi các nút được xuất ra hết. Ta sử dụng hàm gotoxy(x,y) để trỏ
con trỏ đến tọa độ (x,y) trên màn hình, từ đó in ra nút. Tạo thêm các hàm wherex() là
vị trí cột con trỏ đang đứng, wherey() là vị trí hàng con trỏ đang đứng.
Do Dev C++ không có hàm gotoxy(x,y),wherex(), wherey()nên ta cần định nghĩa lại
các hàm này.
void gotoxy(int x,int y) {
HANDLE hStdout = GetStdHandle (STD_OUTPUT_HANDLE);
COORD position = {x, y};
SetConsoleCursorPosition (hStdout, position);
}
int wherex(){
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &csbi);
return csbi.dwCursorPosition.X;
}
int wherey(){
CONSOLE_SCREEN_BUFFER_INFO csbi;

GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi);
return csbi.dwCursorPosition.Y;
}
Nguyễn Văn Thiện – Lê Anh Vũ – Vũ Văn Tú – Nguyễn Hoàng Hải Đỗ Quốc Đạt Page 19
BÀI TẬP LỚN KSTN-CNTT
Để tiến hành vẽ cây, từ ý tưởng xây dựng, ta viết hàm vẽ nút drawNode và hàm
printTree để in cây.
// Vẽ nút.
int drawNode(char value,int &x,int &y,int &l,int type,int position){
switch(position){
case LEFT:{
y=y+4;
x=x-2-l;
break;
}
case RIGHT:{
x=x+2+l;
y=y+4;
break;
}
default: break;
}
l=l/2;
gotoxy(x,y);printf("|");
gotoxy(x,y+1);printf("|");
gotoxy(x-1,y+2);printf(" ");
gotoxy(x-2,y+3);printf("|%3c|",value);
gotoxy(x-1,y+4);printf(" ");
if (type==LEFT||type==FULL){
gotoxy(x-2-l,y+3);

for(int i=0;i<l;i++) printf("-");
Nguyễn Văn Thiện – Lê Anh Vũ – Vũ Văn Tú – Nguyễn Hoàng Hải Đỗ Quốc Đạt Page 20
BÀI TẬP LỚN KSTN-CNTT
}
if(type==RIGHT||type==FULL){
gotoxy(x+3,y+3);
for (int i=0;i<l;i++) printf("-");
}
return 1;
}
// In cây.
void printTree(TreeNode *root,int px,int py,int pl,int t_node){
if(root->rFlag==TRUE){
if(root->lFlag==TRUE){
drawNode(root->key,px,py,pl,FULL,t_node);
}
else drawNode(root->key,px,py,pl,RIGHT,t_node);
}
else{
if (root->lFlag==TRUE)
drawNode(root->key,px,py,pl,LEFT,t_node);
else
drawNode(root->key,px,py,pl,NO,t_node);
}
if (root->rFlag==TRUE) printTree(root->rChild,px,py,pl,RIGHT);
if (root->lFlag==TRUE) printTree(root->lChild,px,py,pl,LEFT);
}
Kết quả:
Nguyễn Văn Thiện – Lê Anh Vũ – Vũ Văn Tú – Nguyễn Hoàng Hải Đỗ Quốc Đạt Page 21
BÀI TẬP LỚN KSTN-CNTT

2.2.6 In giao diện chương trình:
Giao diện chương trình là một menu có các thao tác lựa chọn để người dùng thao tác
với cây như thêm nút, duyệt cây, in cây.
1. In theo thứ tự trước
2. In theo thứ tự giữa
3. In theo thứ tự sau
4. Thêm nút
5. In cây
6. Thoát
Khi người dùng yêu cầu thao tác nào thì hệ thống tương ứng sẽ gọi các hàm thực thi
chúng.
2.3 Hình ảnh chạy demo.
Khi bắt đầu, chương trình sẽ yêu cầu bạn nhập cây:
Nguyễn Văn Thiện – Lê Anh Vũ – Vũ Văn Tú – Nguyễn Hoàng Hải Đỗ Quốc Đạt Page 22
BÀI TẬP LỚN KSTN-CNTT
Nguyễn Văn Thiện – Lê Anh Vũ – Vũ Văn Tú – Nguyễn Hoàng Hải Đỗ Quốc Đạt Page 23
BÀI TẬP LỚN KSTN-CNTT
Sau khi nhập xong, sẽ hiện Menu
III. TÀI LIỆU THAM KHẢO
[1] Bài giảng Cấu trúc dữ liệu và giải thuật – Thầy Nguyễn Đức Nghĩa
[2] Data Structures and Algorithm Analysis - Clifford A. Shaffer
Nguyễn Văn Thiện – Lê Anh Vũ – Vũ Văn Tú – Nguyễn Hoàng Hải Đỗ Quốc Đạt Page 24
BÀI TẬP LỚN KSTN-CNTT
[3] />Nguyễn Văn Thiện – Lê Anh Vũ – Vũ Văn Tú – Nguyễn Hoàng Hải Đỗ Quốc Đạt Page 25

×