- Nội dung: Thê m 1 nút có khóa x, nội dung a và o câ y nhị phâ n tì m kiế m
câ n bằ ng sao cho sau khi thê m thì câ y nhị phâ n vẫ n là câ y nhị phâ n tì m kiế m câ n
bằ ng.
- Giả i thuậ t:
& Thêm nút và o câ y nh bì nh thờng, nghĩ a là nút vừa thêm sẽ là nút lá .
& Tí nh lạ i chỉ số câ n bằ ng của cá c nút có bị ả nh hởng
& Kiểm tra xem câ y có bị mấ t câ n bằ ng hay không? Nế u câ y bị mấ t câ n
bằ ng thì ta câ n bằ ng lạ i câ y.
* Trớc hế t, ta hãy xét xem các trờng hợp nào khi thêm nút làm cây bị
mất cân bằng.
Xem câ y hì nh 5.15, ta nhậ n thấ y:
- Nế u thêm nút và o 1 trong 6 vị trí B trê n câ y thì câ y vẫ n câ n bằ ng.
- Nế u thêm nút và o 1 trong cá c vị trí U1%U12 trê n câ y thì câ y sẽ mấ t
câ n bằ ng.
+ Thêm cá c nút và o sau bê n trá i của nút A (cfA = 1) thì câ y sẽ bị
mấ t câ n bằ ng vì nút A đang bị lệ ch trá i. Đó là cá c vị trí U1, U2, U3, U4.
+ Thêm cá c nút và o sau bê n phả i của nút C (cfC = -1) thì câ y sẽ bị
mấ t câ n bằ ng vì nút C đang bị lệ ch phả i. Đó là cá c vị trí U9, U10, U11, U12.
Tóm lạ i: Ta có 2 trờng hợp khi thê m nút x vào cây AVL làm cây mất
cân bằng, đó là thê m các nút vào sau bê n trái của nút có cf = 1, và thê m các nút
vào sau bê n phải của nút có cf = -1.
134 trang |
Chia sẻ: hachi492 | Ngày: 07/01/2022 | Lượt xem: 414 | Lượt tải: 0
Bạn đang xem trước 20 trang tài liệu Giáo trình môn Kỹ thuật lập trình, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
ê n kế t cũng có thể nhiề u hơn một nế u là danh sá ch đa liê n
kế t hoặ c danh sá ch liê n kế t kép.
' First là con trỏ trỏ đế n phầ n tử đầ u tiê n của danh sá ch liê n kế t, nó có thể
là kiể u con trỏ (như khai bá o trê n), và cũng có thể là một struct có hai
thà nh phầ n: First trỏ đế n phầ n tử đầ u tiê n của danh sá ch liê n kế t, và Last
trỏ đế n phầ n tử cuối của danh sá ch liê n kế t.
struct Linked_List;
{ First NODEPTR;
Last NODEPTR;
};
II. Các phép toán trên danh sách liên kết:
II.1. Tạo danh sách:
a. Khởi tạ o danh sá ch (Initialize): dùng để khởi động một danh sá ch liê n
kế t, cho chương trì nh hiể u là hiệ n tạ i danh sá ch liê n kế t chưa có phầ n tử.
void Initialize(NODEPTR &First)
{
Kỹ thuật lập trì nh 99
First = NULL;
}
b. Cấ p phá t vùng nhớ (New_Node): cấ p phá t một nút cho danh sá ch liê n
kế t. Hà m New_Node nà y trả về địa chỉ của nút vừa cấ p phá t.
Trong chương trì nh có sử dụng hà m malloc (trong ) , hà m nà y cấ p
phá t một khối nhớ tí nh theo byte từ bộ nhớ heap. Nế u cấ p phá t thà nh công, hà m
malloc trả về địa chỉ của vùng nhớ vừa cấ p phá t, ngược lạ i nó sẽ trả về NULL.
NODEPTR New_Node()
{
NODEPTR p;
p = (NODEPTR)malloc(sizeof(struct node));
return (p);
}
c. Thê m và o đầ u danh sá ch (Insert_First): thê m một nút có nội dung x và o
đầ u danh sá ch liê n kế t.
void Insert_First (NODEPTR &First, int x)
{
NODEPTR p;
p = New_Node();
p->info = x;
p->next = First;
First = p;
}
d. Thê m nút mới và o sau nút có địa chỉ p (Insert_After): thê m một nút có
nội dung x và o sau nút có địa chỉ p trong danh sá ch liê n kế t First.
void Insert_After(NODEPTR p, int x)
{
NODEPTR q;
if(p == NULL)
printf("khong them nut moi vao danh sach duoc");
else
{
q = New_Node();
q->info = x;
q->next = p->next;
p->next = q;
}
}
Kỹ thuật lập trì nh 100
II.2. Cập nhật danh sách:
a. Giả i phóng vùng nhớ(Free_Node): Hà m nà y dùng để hủy nút đ∙ cấ p
phá t, và trả vùng nhớ về lạ i cho memory heap.
void Free_Node(NODEPTR p)
{
free(p);
}
b. Kiể m tra danh sá ch liê n kế t rỗng hay không (Empty): hà m Empty trả về
TRUE nế u danh sá ch liê n kế t rỗng, và ngược lạ i.
int Empty(NODEPTR First)
{
return(First == NULL ? TRUE : FALSE);
}
c. Xóa phầ n tử đầ u của danh sá ch (Delete_First): muốn xóa 1 phầ n tử khỏi
danh sá ch liê n kế t thì ta phả i kiể m tra xem danh sá ch có rỗng hay không. Nế u
danh sá ch có phầ n tử thì mới xóa được.
void Delete_First (NODEPTR First)
{ NODEPTR p;
if (Empty(First))
printf("Danh sach rong nen khong the xoa");
else
{
p = First; // nut can xoa la nut dau
First = p->next;
Free_Node(p);
}
}
d. Xóa phầ n tử đứng sau nút có địa chỉ p (Delete_After):
void Delete_After(NODEPTR p)
{ NODEPTR q;
// nế u p là NULL hoặ c sau p không có nút
if((p == NULL) || (p->next == NULL))
printf("khong xoa duoc");
else
{
q = p->next; // q chi nut can xoa
p->next = q->next;
Kỹ thuật lập trì nh 101
Free_Node(q);
}
}
e. Xóa toà n bộ danh sá ch (Delete_All): ta có thể sử dụng lệ nh *First =
NULL để xóa toà n bộ danh sá ch, nhưng trong bộ nhớ, cá c vùng nhớ đ∙ cấ p phá t
cho cá c nút không giả i phóng về lạ i cho memory heap, nê n sẽ l∙ng phí vùng nhớ.
Do đó, ta sử dụng giả i thuậ t sau:
void Delete_All (NODEPTR &First)
{ NODEPTR p;
while (First != NULL)
{ p=First;
First = First->next; // hoặ c First = p->next
Free_Node(p);
}
}
II.3. Duyệ t danh sách: Thông thường ta hay duyệ t danh sá ch liê n kế t để thực
hiệ n một công việ c gì đó, như liệ t kê dữ liệ u trong danh sá ch hay đế m số nút
trong danh sá ch...
void Traverse(NODEPTR First)
{ NODEPTR p;
int stt = 0;
p = First;
if(p == NULL)
printf("\n (Khong co sinh vien trong danh sach)");
while(p != NULL)
{
printf("\n %5d%8d", stt++, p->info);
p = p->next;
}
}
II.4. Tì m kiế m (Search): Tì m nút đầ u tiê n trong danh sá ch có info bằ ng với x.
Do đâ y là danh sá ch liê n kế t nê n ta phả i tì m từ đầ u danh sá ch.
Hà m Search nế u tì m thấ y x trong danh sá ch thì trả về địa chỉ của nút có trị
bằ ng x trong danh sá ch, nế u không có thì trả về trị NULL.
NODEPTR Search(NODEPTR First, int x)
{
NODEPTR p;
Kỹ thuật lập trì nh 102
p = First;
while(p != NULL && p->info != x )
p = p->next;
return (p);
}
II.5. Sắp xế p (Selection_Sort): sắ p xế p danh sá ch liê n kế t theo thứ tự info tă ng
dầ n.
- Nội dung: Ta so sá nh tấ t cả cá c phầ n tử của danh sá ch để chọn ra một
phầ n tử nhỏ nhấ t đưa về đầ u danh sá ch; sau đó, tiế p tục chọn phầ n tử nhỏ nhấ t
trong cá c phầ n tử còn lạ i để đưa về phầ n tử thứ hai trong danh sá ch. Quá trì nh
nà y lặ p lạ i cho đế n khi chọn ra được phầ n tử nhỏ thứ (n-1).
- Giả i thuậ t:
void Selection_Sort(NODEPTR First)
{ NODEPTR p, q, pmin;
int min;
for(p = First; p->next != NULL; p = p->next)
{ min = p->info;
pmin = p;
for(q = p->next; q != NULL; q = q->next)
if(min > q->info)
{
min = q->info;
pmin = q;
}
// hoan doi truong info cua hai nut p va pmin
pmin->info = p->info;
p->info = min;
}
}
Kỹ thuật lập trì nh 103
Bài tập:
1. Viế t chương trì nh tạ o một menu thực hiệ n cá c công việ c sau:
a. Nhậ p danh sá ch liê n kế t theo giả i thuậ t thê m về đầ u danh sá ch, mỗi phầ n tử
gồm có cá c thông tin sau: mssv (int), và hoten ( char hoten[30] ).
b. Liệ t kê danh sá ch ra mà n hì nh
c. Cho biế t tổng số nút trong danh sá ch liê n kế t, đặ t tê n hà m là Reccount
( int Reccount(NODEPTR First) )
d. Thê m 1 phầ n tử có nội dung info (mssv, hoten) và o sau phầ n tử có thứ tự
thứ i trong danh sá ch.
Ghi chú: - Thứ tự theo qui ước bắ t đầ u là 1
- Nế u (i = 0) thê m và o đầ u danh sá ch
Nế u i > Reccount(&First) thì thê m và o cuối danh sá ch.
e. In ra họ tê n của sinh viê n có m∙ do ta nhậ p và o.
f. Loạ i bỏ nút có m∙ do ta nhậ p và o, trước khi xóa hỏi lạ i "Bạ n thậ t sự muốn
xóa (Y/N) ? "
g. Sắ p xế p lạ i danh sá ch theo thứ tự m∙ số giả m dầ n.
h.Ghi toà n bộ danh sá ch và o file tê n 'DSSV.DAT'
i. Nạ p danh sá ch từ file 'DSSV.DAT' và o danh sá ch liê n kế t. Nế u trong danh
sá ch liê n kế t đ∙ có nút thì xóa tấ t cả dữ liệ u hiệ n có trong danh sách liê n kế t
trước khi đưa dữ liệ u từ file và o.
2. Viế t chương trì nh tạ o một danh sá ch liê n kế t theo giả i thuậ t thê m và o cuối
danh sá ch, mỗi nút chứa một số nguyê n.
3. -Viế t hà m tê n Delete_Node để xóa nút có địa chỉ p.
- Viế t một hà m loạ i bỏ tấ t cả cá c nút có nội dung x trong danh sá ch liê n kế t
First.
4. Viế t hà m Copy_List trê n danh sá ch liê n kế t để tạ o ra một danh sá ch liê n kế t
mới giống danh sá ch liê n kế t cũ.
5. Ghép một danh sá ch liê n kế t có địa chỉ đầ u là First2 và o một danh sá ch liê n
kế t có địa chỉ đầ u là First1 ngay sau phầ n tử thứ i trong danh sá ch liê n kế t
First1.
6. Viế t hà m lọc danh sá ch liê n kế t để trá nh trường hợp cá c nút trong danh sá ch
liê n kế t bị trùng info.
7. Đả o ngược vùng liê n kế t của một danh sá ch liê n kế t sao cho:
- First sẽ chỉ đế n phầ n tử cuối
- Phầ n tử đầ u có liê n kế t là NULL.
Kỹ thuật lập trì nh 104
8. Viế t hà m Left_Traverse (NODEPTR &First) để duyệ t ngược danh sá ch liê n
kế t.
9. Viế t giả i thuậ t tá ch một danh sá ch liê n kế t thà nh hai danh sá ch liê n kế t, trong
đó một danh sá ch liê n kế t chứa cá c phầ n tử có số thứ tự lẽ và một danh sá ch
liê n kế t chứa cá c phầ n tử có số thứ tự chẵ n trong danh sá ch liê n kế t cũ.
10. - Tạ o một danh sá ch liê n kế t chứa tê n học viê n, điể m trung bì nh, hạ ng của
học viê n (với điề u kiệ n chỉ nhậ p tê n và điể m trung bì nh). Quá trì nh nhậ p sẽ
dừng lạ i khi tê n nhậ p và o là rỗng.
- Xế p hạ ng cho cá c học viê n. In ra danh sá ch học viê n thứ tự hạ ng tă ng dầ n
(Ghi chú : Cùng điể m trung bì nh thì cùng hạ ng).
11. Nhậ p hai đa thức theo danh sá ch liê n kế t. In ra tí ch của hai đa thức nà y.
Ví dụ: Đa thức First1 : 2x5+4x2-1
Đa thức First2 : 10x7-3x4+x2
⇒ Kế t quả in ra : 20x12 + 34x9 - 8x7 - 12x6 + 7x4 - x2
(Ghi chú : Không nhậ p và in ra cá c số hạ ng có hệ số bằ ng 0)
12. Viế t giả i thuậ t thê m phầ n tử có nội dung x và o danh sá ch liê n kế t có thứ tự
tă ng dầ n sao cho sau khi thê m danh sá ch liê n kế t vẫ n có thứ tự tă ng.
13. Loạ i bỏ phầ n tử có nội dung là x trong danh sá ch liê n kế t có thứ tự tă ng dầ n.
14. Cho 2 danh sá ch liê n kế t First1, First2 có thứ tự tă ng dầ n theo info. Viế t giả i
thuậ t Merge để trộn 2 danh sá ch liê n kế t nà y lạ i sao cho danh sá ch liê n kế t
sau khi trộn cũng có thứ tự tă ng dầ n.
Kỹ thuật lập trì nh 105
CHươNG 6 các thuật toán trên cấu trúc câY
(Tree)
Câ y là một cấ u trúc dữ liệ u rấ t thông dụng và quan trọng trong nhiề u phạ m
vi khá c nhau của kỹ thuậ t má y tí nh.
Ví dụ : Tổ chức cá c quan hệ họ hà ng trong một gia phả , mục lục của một
cuốn sá ch, xâ y dựng cấ u trúc về cú phá p trong cá c trì nh biê n dịch.
Trong chương trì nh nà y, chúng ta khả o sá t cá c khá i niệ m cơ bả n về câ y, các
phép toá n trê n câ y nhị phâ n, cũng như cá c phép toá n trê n câ y nhị phâ n câ n bằ ng
( AVL tree) và ứng dụng của hai loạ i câ y nhị phâ n tì m kiế m (BST), câ y nhị phâ n
câ n bằ ng ( AVL tree).
I. Phân loại cây:
I.1. Một số khái niệ m cơ bản:
1. Cây: Câ y là tậ p hợp cá c phầ n tử gọi là nút, một nút (tương tự như một
phầ n tử của d∙ y) có thể có kiể u bấ t kỳ. Cá c nút được biể u diễ n bởi 1 ký tự chữ,
một chuỗi, một số ghi trong một vòng tròn.
Một số định nghĩ a theo đệ quy
( Một nút đơn cũng chí nh là một câ y.
( Cá c nút được gọi là ở cùng một câ y khi có đường đi giữa cá c nút nà y.
( Một câ y sẽ bao gồm một nút gốc (Root) và m câ y con, trong mỗi câ y con
lạ i có một nút gốc và m1 câ y con nhỏ hơn v.v.
( Một câ y không có một nút nà o cả gọi là câ y rỗng.
Ví dụ 1 :
A
B C
G H E
J
D
F
KI
1
2
3
4
Nuựt goỏc
Hì nh 5.1. Câ y với nút gốc là A
- A là nút gốc với 3 câ y con lầ n
lượt có 3 nút gốc riê ng là ứ B, C, D
- Nút cha (ancestor)
Nút con (descendent)
A là nút cha của B, C, D
G, H là nút con của C
G, H không quan hệ cha con
với A
Kỹ thuật lập trì nh 106
Ví dụ 2 : Với đề cương một môn học T, ta có thể biể u diễ n dạ ng câ y như
sau :
T
CHệễNG I CHệễNG II CHệễNG III
I.1 I.2 II.1 II.3II.2
II.1.1 II.1.2
Hì nh 5.2
CHươNG I
I.1
I.2
CHươNG II
II.1
II.1.1
II.1.2
II.2
II.3
CHươNG III
2. Nút cha (Ancestor) : Nút đứng trê n của một nút được gọi là nút cha
C là nút cha của G, H
Nút con (descendent) : Nút đứng sau một nút khá c được gọi là nút con của
nút đó.
Nút I, J, K là nút con của nút E
3. Bậc (degree) :
- Bậ c của nút là số câ y con của nút đó.
C có bậ c là 2, E có bậ c là 3 (Hì nh 5.1)
- Bậ c của câ y là bậ c lớn nhấ t của cá c nút trong câ y.
Câ y trong hì nh 5.1 có bậ c là 3.
Câ y bậ c n được gọi là câ y n phâ n như câ y nhị phâ n, câ y tam phâ n.
4. Nút lá và nút trung gian:
- Nút lá là nút có bậ c bằ ng 0 (tức là không có câ y con nà o) :
- Nút trung gian: là một nút có bậ c khá c 0 và không phả i là nút gốc.
Ví dụ: Trong hì nh 5.1, B, G, H, I, J, K, F là nút lá
C, D, E là nút trung gian.
5. Mức của nút (level) : Nút gốc có mức là 1
Mức của nút con = mức của nút cha + 1
Kỹ thuật lập trì nh 107
Ví dụ: trong hì nh 5.1,
A có mức là 1
B, C, D có mức là 2
G, H, E, F có mức là 3
I, J, K có mức là 4
6. Chiề u cao của cây (height) : là mức lớn nhấ t của cá c nút lá trong câ y.
Ví dụ: Câ y trong hì nh 5.1 có chiề u cao là 4
7. Thứ tự của các nút (order of nodes) : Nế u câ y được gọi là có thứ tự thì
phả i đả m bả o vị trí của cá c nút con từ trá i qua phả i, tức là nế u thay đổi vị trí của
một nút con bấ t kỳ thì ta đ∙ có một câ y mới.
Ví dụ :
A
B C
A
C B
caõy khaực
Hì nh 5.3: Sau khi đổi vị trí của 2 nút B, C ta đ∙ có câ y mới.
8. Chiề u dài đường đi (Path length):
- Chiề u dà i đường đi của nút x: là số cá c cạ nh đi từ nút gốc đế n nút x.
Ví dụ: Trong hì nh 5.1:
Nút gốc A có chiề u dà i đường đi là 1
Nút B, C, D có chiề u dà i đường đi là 2
Tổng quá t: một nút tạ i mức i có chiề u dà i đường đi là i
- Chiề u dà i đường đi của câ y: là tổng của cá c chiề u dà i đường đi của tấ t cả
cá c nút trong câ y.
Ví dụ: Chiề u dà i đường đi của câ y trong hì nh 5.1 là 31.
Chiề u dà i đường đi trung bì nh của câ y:
n/)i.n(P
i
ii ∑=
trong đó ni là số cá c nút ở mức i và n là tổng số cá c nút trong câ y.
I.2. Cách biể u diễ n cây: để biể u diễ n 1 câ y, ta có nhiề u cá ch như biể u diễ n
bằ ng đồ thị,bằ ng giả n đồ, bằ ng chỉ số.. Nhưng thông thường, ta hay dùng dạ ng
đồ thị để biể u diễ n 1 câ y như hì nh 5.1
I.3. Biể u diễ n thứ tự các nút trong cây :
Kỹ thuật lập trì nh 108
Một câ y thường tổ chức cá c nút theo một thứ tự nhấ t định că n cứ và o một
nội dung gọi là khóa của cá c nút. Có thể tổ chức câ y có khóa tă ng dầ n theo mức
từ trá i qua phả i như ví dụ sau :
1
2 3
4
Root
76 8
5
9
ROOT %1%2%3%4%5%6%7%8%9
Như vậ y khi duyệ t lạ i câ y theo mức
tă ng dầ n và từ trá i qua phả i ta sẽ lạ i
có được thứ tự cá c nút như trê n.
Hì nh 5.4. Câ y có thứ tự tă ng dầ n theo mức từ trá i qua phả i
II. Cây nhị phân (Binary tree)
II.1. Định nghĩ a :
1. Cây nhị phân là câ y có bậ c bằ ng 2, tức là số nút con tối đa của một nút
bấ t kỳ trong câ y là 2.
Câ y nhị phâ n có thể là một câ y rỗng (không có nút nà o) hoặ c câ y chỉ có
một nút, hoặ c câ y chỉ có cá c nút con bê n trá i (Left Child) hoặ c nút con bê n phả i
(Right Child) hoặ c cả hai.
Ví dụ: Hì nh 5.4 là câ y nhị phâ n.
2. Các cây nhị phân đặc biệ t:
- Câ y nhị phâ n đúng: Một câ y nhị phâ n được gọi là câ y nhị phâ n đúng nế u
nút gốc và tấ t cả cá c nút trung gian đề u có 2 nút con.
A
B
D E
G Y
C
X F
H I
Hì nh 5.5. Câ y nhị phâ n đúng
Kỹ thuật lập trì nh 109
Ghi chú: nế u câ y nhị phâ n đúng có n nút lá thì câ y nà y sẽ có tấ t cả 2n-1 nút.
- Câ y nhị phâ n đầ y: Một câ y nhị phâ n gọi là câ y nhị phâ n đầ y với chiề u cao
d thì :
. Nó phả i là câ y nhị phâ n đúng và
. Tấ t cả cá c nút lá đề u có mức là d.
Hì nh 5.5 không phả i là câ y nhị phâ n đầ y
A
B
D
H I
E
J K
C
F
L M
G
N O
Hì nh 5.6. Câ y nhị phâ n đầ y.
Ghi chú: Câ y nhị phâ n đầ y là câ y nhị phâ n có số nút tối đa ở mỗi mức.
- Câ y nhị phâ n tì m kiế m (Binary Search Tree): Một câ y nhị phâ n gọi là câ y
nhị phâ n tì m kiế m nế u và chỉ nế u đối với mọi nút của câ y thì khóa của một nút
bấ t kỳ phả i lớn hơn khóa của tấ t cả cá c nút trong câ y con bê n trá i của nó và phả i
nhỏ hơn khóa của tấ t cả cá c nút trong câ y con bê n phả i của nó.
Ví dụ:
8
7 9
3
12
11
102
1
5
4 6
k1 <k1 <k1
Hì nh 5.7. Câ y nhị phâ n tì m kiế m (BST)
Kỹ thuật lập trì nh 110
- Câ y nhị phâ n câ n bằ ng (AVL): Một câ y nhị phâ n được gọi là câ y nhị phâ n
câ n bằ ng nế u và chỉ nế u đối với mọi nút của câ y thì chiề u cao của câ y con bê n
trá i và chiề u cao của câ y con bê n phả i hơn kém nhau nhiề u nhấ t là 1. (Theo
Adelson-Velski và Landis).
A
C
E F
B
D
G I JH
Hì nh 5.8. Câ y nhị phâ n câ n bằ ng
- Câ y nhị phâ n câ n bằ ng hoà n toà n: Một câ y nhị phâ n được gọi là câ y nhị
phâ n câ n bằ ng hoà n toà n nế u và chỉ nế u đối với mọi nút của câ y thì số nút của
câ y con bê n trá i và số nút của câ y con bê n phả i hơn kém nhau nhiề u nhấ t là 1.
A
C
E F
B
D
IH
E
H
Hì nh5.9. Câ y nhị phâ n câ n bằ ng hoà n toà n
3. Các phép duyệ t cây nhị phân (Traverse) : là quá trì nh đi qua cá c nút
đúng một lầ n. Khi duyệ t câ y, ta thường dùng 3 cá ch duyệ t cơ bả n sau :
' Preorder - Tiề n tự (NLR) duyệ t qua nút gốc trước, sau đó đi qua câ y con
bê n trá i lạ i á p dụng Preorder cho câ y con bê n trá i. Cuối cùng qua câ y con bê n
phả i, á p dụng Preorder cho câ y con bê n phả i.
Ví dụ: Theo câ y nhị phâ n 5.4, ta có:
ROOT % 1 % 2 % 3 % 4 % 6 % 7 % 5 % 8 % 9
'Inorder - Trung tự (LNR) : qua câ y con bê n trá i duyệ t trước (theo thứ tự
LNR), sau đó thă m nút gốc. Cuối cùng qua câ y con bê n phả i (theo thứ tự LNR)
Ví dụ: Theo câ y nhị phâ n 5.4, ta có:
ROOT % 2 % 1 % 6 % 4 % 7 % 3 % 8 % 5 % 9
'Postorder - Hậ u tự (LRN) : qua câ y con bê n trá i duyệ t trước (theo thứ tự
LRN), sau đó qua câ y con bê n phả i (theo thứ tự LRN). Cuối cùng thă m nút gốc.
Ví dụ: Theo câ y nhị phâ n 5.4, ta có:
ROOT % 2 % 6 % 7 % 4 % 8 % 9 % 5 % 3 % 1
Kỹ thuật lập trì nh 111
Ghi chú : Đối với câ y ta có thể tổ chức thứ tự theo khóa là một nội dung
của nút hoặ c ta đặ t thê m 1 field gọi là khóa của nút .
II.2. Các phép toán trê n cây nhị phân:
- Khai báo: Để tổ chức dữ liệ u theo câ y nhị phâ n, ta có thể dùng một nội
dung của dữ liệ u để là m khóa sắ p xế p và tổ chức câ y theo nhiề u cá ch khá c nhau.
Nhưng thông thường để thuậ n tiệ n cho việ c tì m kiế m và thực hiệ n cá c phép toá n
khá c trê n câ y, người ta tạ o thê m một khóa riê ng trong cá c phầ n tử và tạ o ra câ y
nhị phâ n tì m kiế m.
Để khai bá o biế n tree quả n lý một câ y nhị phâ n, với nội dung info chứa số
nguyê n, ta khai bá o như sau:
struct nodetype
{
int key;
int info;
struct nodetype *left;
struct nodetype *right;
};
typedef struct nodetype *NODEPTR;
NODEPTR tree;
1. Tạo cây:
a. Khởi tạ o câ y(Initialize): dùng để khởi động câ y nhị phâ n, cho chương
trì nh hiể u là hiệ n tạ i câ y nhị phâ n rỗng.
void Initialize(NODEPTR &root)
{
root = NULL;
}
Lời gọi hà m: Initialize(tree);
b. Cấ p phá t vùng nhớ (New_Node): cấ p phá t một nút cho câ y nhị phâ n.
Hà m New_Node nà y trả về địa chỉ của nút vừa cấ p phá t.
NODEPTR New_Node(void)
{
NODEPTR p;
p = (NODEPTR)malloc(sizeof(struct nodetype));
return(p);
}
Lời gọi hà m: p= New_Node();
Kỹ thuật lập trì nh 112
c. Tạ o câ y BST (Create_Tree): Trong giả i thuậ t tạ o câ y BST, ta có dùng
hà m Insert.
Hà m Insert: dùng phương phá p đệ qui thê m nút có khóa x, nội dung a và o
câ y có nút gốc root . Câ y nhị phâ n tạ o được qua giả i thuậ t Create_Tree là câ y
nhị phâ n tì m kiế m (BST).
void Insert(NODEPTR root, int x, int a)
{ NODEPTR p;
if(x == root->key) // khóa bị trùng, dừng chương trì nh
{
printf("bi trung khoa, khong them nut nay duoc");
return;
}
if(x info && root->left == NULL) // điề u kiệ n dừng giả i thuậ t đệ qui
{
p = New_Node(); // cấ p phá t vùng nhớ
p->key =x;
p->info = a;
p->left = NULL;
p->right = NULL;
root->left=p;
return;
}
if(x > root->info && root->right == NULL) //điề u kiệ n dừng giả i thuậ t đệ qui
{
p = New_Node();
p->key =x;
p->info = a;
p->left = NULL;
p->right = NULL;
root->right=p ;
return;
}
if(x info) // bước đệ qui
Insert(root->left, x,a); // gọi đệ qui qua nhá nh trá i
else
Insert(root->right, x,a); // gọi đệ qui qua nhá nh phả i
}
Kỹ thuật lập trì nh 113
void Create_Tree(NODEPTR &root)
{ int khoa, noidung;
char so[10];
NODEPTR p;
do
{ printf("Nhap khoa :");
gets(so) ;
khoa = atoi(so);
if (khoa !=0)
{ printf("Nhap noi dung :");
gets(so) ;
noidung = atoi(so);
if (root==NULL)
{ p = New_Node();
p->key = khoa;
p->info = noidung;
p->left = NULL;
p->right = NULL;
root =p;
}
else Insert(root,khoa,noidung);
}
} while (khoa!=0); // khóa =0 thì dừng nhậ p
}
Ghi chú : Để tạ o câ y nhị phâ n do biế n tree quả n lý, ta gọi:
Create_Tree(tree);
2. Cập nhật cây:
a. Giả i phóng vùng nhớ(Free_Node): giả i phóng vùng nhớ mà p đang trỏ đế n.
void Free_Node(NODEPTR p)
{
free(p);
}
Lời gọi hà m: Free_Node (p);
b. Kiể m tra câ y nhị phâ n rỗng hay không (Empty): hà m Empty trả về
TRUE nế u câ y nhị phâ n rỗng, và ngược lạ i.
int Empty(NODEPTR root)
return(root == NULL ? TRUE : FALSE);
}
Kỹ thuật lập trì nh 114
Lời gọi hà m: Empty(tree)
c. Hủy bỏ một nút trong câ y nhị phâ n BST (Remove):
Xóa nút có khóa là x trong câ y nhị phâ n tì m kiế m sao cho sau khi xóa thì
câ y nhị phâ n vẫ n là câ y nhị phâ n tì m kiế m. Ta có 3 trường hợp :
- Trường hợp 1: nút p cầ n xóa là nút lá . Việ c xóa nút p chỉ đơn giả n là hủy
nút p
p1
p
p1
p1
p
p1
- Trường hợp 2: Nút p cầ n xóa có 1 câ y con, thì ta cho rp chỉ tới nút p. Sau
đó, ta tạ o liê n kế t từ nút cha của p tới nút con của rp, cuối cùng hủy nút p.
10
5
3
15
12 20
2 4
p xoựa nuựt p
10
3 15
12 202 4
rp
Hì nh 5.10. Xóa nút p trong trường hợp nút nà y có 1 câ y con bê n trá i.
2
10
5
3
15
4
20
18 25
rp
p
xoựa nuựt p
10
5
3
20
18 25
2 4
Hì nh 5.11. Xóa nút p trong trường hợp nút nà y có 1 câ y con bê n phả i.
- Trường hợp 3: Nút p cầ n xóa có 2 câ y con. Ta cho rp chỉ tới nút p. Do tí nh
chấ t nút cực trá i của câ y con bê n phả i của p có khóa vừa lớn hơn khóa của p,
nê n để loạ i p thì ta sẽ cho r chỉ tới nút cực trá i đó. Sau đó, ta sao chép nội dung
Kỹ thuật lập trì nh 115
và khóa của nút r và o nút mà rp đang chỉ tới. Ta tạ o liê n kế t thí ch hợp để bứt nút
rp ra khỏi câ y nhị phâ n và cuối cùng xóa nút rp.
10
5 20
15 30
12 18
28
25 35
p
nuựt traựi nhaỏt cuỷa
caõy con beõn phaỷi
10
5 25
15 30
12 18 28 35
r
Hì nh 5.12. Xóa nút p trong trường hợp nút nà y có 2 câ y con.
Hà m Remove xóa nút có khóa là x:
NODEPTR rp;
void remove_case_3 ( NODEPTR &r )
{
if (r->left != NULL)
remove_case_3 (r->left);
//den day r la nut cuc trai cua cay con ben phai co nut goc la rp}
else
{
rp->key = r->key; //Chep noi dung cua r sang rp ";
rp->info =r->info; // de lat nua free(rp)
rp = r;
r = r->right;
}
}
void remove (int x , NODEPTR &p )
{
if (p == NULL) printf ("Khong tm thay");
else
if (x key) remove (x, p->left);
else if (x > p->key)
Kỹ thuật lập trì nh 116
remove (x, p->right);
else // p^.key = x
{
rp = p;
if (rp->right == NULL) p = rp->left;
// p là nút lá hoac la nut chi co cay con ben trai
else if (rp->left == NULL)
p = rp->right; // p là nut co cay con ben phai
else remove_case_3 (rp->right);
free (rp);
}
}
Lời gọi hà m: Remove(x, tree); // x là khóa của nút muốn xóa
d. Tì m kiế m (Search): Tì m nút có khóa bằ ng x trê n câ y nhị phâ n BST có
gốc là root. Nế u tì m thấ y x trong câ y thì trả về địa chỉ của nút có trị bằ ng x trong
câ y, nế u không có thì trả về trị NULL.
Do câ y nhị phâ n là BST nê n ta có thể tì m kiế m nhanh bằ ng phương phá p
tì m kiế m nhị phâ n.
NODEPTR Search(NODEPTR root, int x)
{
NODEPTR p;
p = root;
while(p != NULL && x!=p->key)
if(x key)
p = p->left;
else
p = p->right;
return(p);
}
Lời gọi hà m: p=Search(tree, x);
3. Các phép duyệ t cây: Có 3 cá ch duyệ t cơ bả n là NLR, LNR, LRN và
một cá ch đặ c biệ t là duyệ t câ y theo mức. ở đâ y, ta chỉ xét 3 phương phá p duyệ t
NLR, LNR và LRN. Xét câ y sau :
Kỹ thuật lập trì nh 117
4
2
1
5
3 6
a. Duyệ t cây theo thứ tự NLR (Preorder):
void Preorder (NODEPTR root)
{ if(root != NULL)
{ printf("%d ", root->info);
Preorder(root->left);
Preorder (root->right);
}
}
b. Duyệ t cây theo thứ tự LNR (Inorder):
void Inorder(NODEPTR root)
{ if(root != NULL)
{ Inorder(root->left);
printf("%d ", root->info);
Inorder(root->right);
}
}
c. Duyệ t cây theo thứ tự LRN (Posorder):
void Posorder(NODEPTR root)
{ if(root != NULL)
{ Posorder(root->left);
Posorder(root->right);
printf("%d ", root->info);
}
}
III. cây nhị phân TìM KIếM cân bằng (AVL):
Chúng ta tạ o câ y nhị phâ n tì m kiế m mục đí ch là để tì m khóa cho nhanh, tuy
nhiê n để tă ng tốc độ tì m kiế m thì câ y cầ n phả i câ n đối về 2 nhá nh theo từng nút
trong câ y. Do vậ y, ta sẽ tì m cá ch tổ chức lạ i câ y BST sao cho nó câ n bằ ng.
Kỹ thuật lập trì nh 118
III.1. Định nghĩ a:
- Câ y nhị phâ n tì m kiế m câ n bằ ng (AVL) là câ y nhị phâ n tì m kiế m mà tạ i
tấ t cả cá c nút của nó chiề u cao của câ y con bê n trá i của nó và chiề u cao của câ y
con bê n trá i chê nh lệ ch nhau không quá một.
10
20
15 30
6
8
12 25 4018
Hì nh 5.14. Câ y nhị phâ n tì m kiế m câ n bằ ng
Lưu ý: Với câ y AVL, việ c thê m và o hay loạ i bỏ 1 nút trê n câ y có thể là m
câ y mấ t câ n bằ ng, khi đó ta phả i câ n bằ ng lạ i câ y. Tuy nhiê n việ c câ n bằ ng lạ i
trê n câ y AVL chỉ xả y ra ở phạ m vi cục bộ bằ ng cá ch xoay trá i hoặ c xoay phả i ở
một và i nhá nh câ y con nê n giả m thiể u chi phí câ n bằ ng.
- Chỉ số cân bằng (balance factor) của một nút p trê n câ y AVL= lh(p) - rh(p)
Trong đó: lh (p) là chiề u cao của câ y con bê n trá i của p
rh(p) là chiề u cao của câ y con bê n phả i của p
Ta có cá c trường hợp sau:
bf(p) = 0 nế u lh(p) = rh(p) nút p câ n bằ ng
bf(p) = 1 nế u lh(p) = rh(p) +1 nút p bị lệ ch về trá i
bf(p) = -1 nế u lh(p) = rh(p) -1 nút p bị lệ ch về phả i
-1
1
0
B
0
B
0
1 -1
00
U4
0
U3U2
0
U1 B
0
B B
0
B
U8
0
U7U6
0
U5 U10
0
U9 U12
0
U11
A
B C
Hì nh 5.15. Minh họa cá c vị trí có thể thê m nút lá và o câ y AVL, khi thê m nút lá
và o 1 trong cá c vị trí B thì câ y vẫ n câ n bằ ng, khi thê m nút lá và o 1 trong cá c vị
Kỹ thuật lập trì nh 119
trí U thì câ y sẽ mấ t câ n bằ ng. Cá c số trê n câ y là chỉ số câ n bằ ng của cá c nút
trước khi thê m nút
III.2. Các phép toán trê n cây AVL:
* Khai báo: Ta khai bá o câ y AVL với mỗi nút có thê m trường bf cho biế t
chỉ số câ n bằ ng của nút đó.
struct nodetype
{
int key;
int info;
int bf;
struct nodetype *left, *right;
};
typedef struct nodetype *NODEPTR;
III.2.1. Thê m nút:
- Nội dung: Thê m 1 nút có khóa x, nội dung a và o câ y nhị phâ n tì m kiế m
câ n bằ ng sao cho sau khi thê m thì câ y nhị phâ n vẫ n là câ y nhị phâ n tì m kiế m câ n
bằ ng.
- Giả i thuậ t:
& Thê m nút và o câ y như bì nh thường, nghĩ a là nút vừa thê m sẽ là nút lá .
& Tí nh lạ i chỉ số câ n bằ ng của cá c nút có bị ả nh hưởng
& Kiể m tra xem câ y có bị mấ t câ n bằ ng hay không? Nế u câ y bị mấ t câ n
bằ ng thì ta câ n bằ ng lạ i câ y.
* Trước hế t, ta hãy xét xem các trường hợp nào khi thê m nút làm cây bị
mất cân bằng.
Xem câ y hì nh 5.15, ta nhậ n thấ y:
- Nế u thê m nút và o 1 trong 6 vị trí B trê n câ y thì câ y vẫ n câ n bằ ng.
- Nế u thê m nút và o 1 trong cá c vị trí U1%U12 trê n câ y thì câ y sẽ mấ t
câ n bằ ng.
+ Thê m cá c nút và o sau bê n trá i của nút A (cfA = 1) thì câ y sẽ bị
mấ t câ n bằ ng vì nút A đang bị lệ ch trá i. Đó là cá c vị trí U1, U2, U3, U4.
+ Thê m cá c nút và o sau bê n phả i của nút C (cfC = -1) thì câ y sẽ bị
mấ t câ n bằ ng vì nút C đang bị lệ ch phả i. Đó là cá c vị trí U9, U10, U11, U12.
Tóm lạ i: Ta có 2 trường hợp khi thê m nút x vào cây AVL làm cây mất
cân bằng, đó là thê m các nút vào sau bê n trái của nút có cf = 1, và thê m các nút
vào sau bê n phải của nút có cf = -1.
Kỹ thuật lập trì nh 120
* Cân bằng lại cây: Gọi ya là nút trước gầ n nhấ t bị mấ t câ n bằ ng khi thê m
nút x và o câ y AVL. Do cả 2 trường hợp bị mấ t câ n bằ ng khi thê m nút x là tương
tự nhau nê n ta chỉ xét trường hợp bfya=1 và nút lá thê m và o là nút sau bê n trá i
của nút ya.
1
0 T3
chieàu
cao
nT1
chieàu
cao
n
T2
chieàu
cao
n
S
ya
Hì nh 5.16. Nhá nh câ y con nút gốc ya trước khi thê m nút.
Nhậ n xét:
- Vì nút ya có bfya = 1 nê n nút ya chắ c chắ n có nút con bê n trá i s với bfs = 0
- Vì ya là nút gầ n nhấ t có bf là 1 nê n nút s và cá c nút trước khá c của nút x
(sẽ thê m và o) có bf là 0.
-Độcao (T1) = Độcao(T2) = Độcao(T3)
Trường hợp 1a: Nế u thê m nút mới x và o vị trí nút sau bê n trá i của s (thuộc
nhá nh T1) ta xoay phả i quanh nút ya
- Nút s sẽ là nút gốc mới của nhá nh câ y nà y với bfs = 0
- Nút ya là nút con bê n phả i của s với bfya = 0.
0
T1
chieàu
saõu
n
0
T2
chieàu
saõu
n
T3
chieàu
saõu
n
S
ya
x
2
1 T3
chieàu
saõu
nT1
chieàu
saõu
n
T2
chieàu
saõu
n
S
ya
x
xoay phaỷi
quanh nuựt ya
Hì nh 5.17. Xoay phả i quanh nút ya để câ n bằ ng lạ i câ y.
Kỹ thuật lập trì nh 121
Trường hợp 1b: Nế u thê m nút mới x và o vị trí nút sau bê n phả i của s (thuộc
nhá nh T2) ta xoay 2 lầ n (xoay kép): xoay trá i quanh nút s và xoay phả i quanh
nút ya
- Nút p sẽ là nút gốc mới của nhá nh câ y nà y với bfp = 0
- Nút ya là nút con bê n phả i của p với bfya = -1
- Nút s là nút con bê n trá i của p với bfs = 0
2
-1 T3
chieàu
saõu
nT1
chieàu
saõu
n
S
ya
1
T2-1
chieàu
saõu
n-1
T2-2
chieàu
saõu
n-1
x
p
Cây AVL sau khi thêm nút x
x
T2-1
chieàu
saõu
n-1
2
0
T1
chieàu
saõu
n
S
p
T2-2
chieàu
saõu
n-1
T3
chieàu
saõu
n
ya
2
xoay traựi
quanh nuựt S
Kỹ thuật lập trì nh 122
xoay phaỷi
quanh nuựt ya
x
T2-1
chieàu
saõu
n-1
0
0
T1
chieàu
saõu
n
S
p
-1
T2-2
chieàu
saõu
n-1
T3
chieàu
saõu
n
ya
Hì nh 5.18. Xoay kép (xoay trá i quanh nút s, xoay phả i quanh nút ya) để câ n
bằ ng lạ i câ y.
Bả ng sau đâ y phâ n biệ t cá c trường hợp câ y bị mấ t câ n bằ ng khi thê m nút và
cá c phép xoay câ y tương ứng để câ n bằ ng lạ i câ y:
Trường hợp Trước khi thê m
nút x
Sau khi thê m
nút x
Các phép xoay cây và chỉ
số cân bằng mới
1.a bfya = 1
bfs = 0
bfya = 2
bfs = 1
Xoay phải quanh nút ya
bfs=0, bf ya = 0
1.b bfya = 1
bfs = 0
bfya = 2
bfs = -1
Xoay kép
1. Xoay trá i quanh nút s
2. Xoay phả i quanh nút ya
bfs=0, bf ya = -1
2.a bfya = -1
bfs = 0
bfya = -2
bfs = -1
Xoay trái quanh nút ya
bfs=0, bf ya = 0
2.b bfya = -1
bfs = 0
bfya = -2
bfs = 1
Xoay kép
1. Xoay phả i quanh nút s
2. Xoay trá i quanh nút ya
bfs=0, bf ya = 1
- Giả i thuậ t:
! Phép xoay trá i (Rotate_Left): xoay trá i câ y nhị phâ n tì m kiế m có nút
gốc là root, yê u cầ u root phả i có nút con bê n phả i (gọi là nút p). Sau khi xoay
trá i thì nút p trở thà nh nút gốc, nút gốc cũ trở thà nh nút con bê n trá i của nút gốc
mới.
Phép xoay trá i trả về con trỏ chỉ nút gốc mới.
Kỹ thuật lập trì nh 123
NODEPTR Rotate_Left(NODEPTR root)
{
NODEPTR p;
if(root == NULL)
printf("Khong the xoay trai vi cay bi rong.");
else
if(root->right == NULL)
printf("Khong the xoay trai vi khong co nut con ben phai.");
else
{
p = root->right;
root->right = p->left;
p->left = root;
}
return p;
}
! Phép xoay phả i (Rotate_Right): xoay phả i câ y nhị phâ n tì m kiế m có nút
gốc là root, yê u cầ u root phả i có nút con bê n trá i (gọi là nút p). Sau khi xoay
phả i thì nút p trở thà nh nút gốc, nút gốc cũ trở thà nh nút con bê n phả i của nút
gốc mới.
Phép xoay phả i trả về con trỏ chỉ nút gốc mới.
NODEPTR Rotate_Right(NODEPTR root)
{
NODEPTR p;
if(root == NULL)
printf("Khong the xoay phai vi cay bi rong.");
else
if(root->left == NULL)
printf("Khong the xoay phai vi khong co nut con ben trai.");
else
{
p = root->left;
root->left = p->right;
p->right = root;
}
return p;
}
Kỹ thuật lập trì nh 124
!Thê m nút (Insert): thê m nút có khóa x, nội dung a và o câ y AVL:
- Thê m nút theo giả i thuậ t thê m nút và o câ y nhị phâ n tì m kiế m .
- Câ n bằ ng lạ i câ y bằ ng cá ch xoay đơn hay xoay kép
void Insert(NODEPTR &pavltree, int x, int a)
{
NODEPTR fp, p, q, // fp là nút cha của p, q là con của p
fya, ya, /* ya là nút trước gầ n nhấ t có thể mấ t câ n bằ ng
fya là nút cha của ya */
s; // s là nút con của ya theo hướng mấ t câ n bằ ng
int imbal; /* imbal = 1 nế u bị lệ ch về nhá nh trá i
= -1 nế u bị lệ ch về nhá nh phả i */
// Khởi động cá c giá trị
fp = NULL;
p = pavltree;
fya = NULL;
ya = p;
// tim nut fp, ya va fya, nut moi them vao la nut la con cua nut fp
while(p != NULL)
{
if(x == p->info) // bi trung noi dung
return;
if (x info)
q = p->left;
else
q = p->right;
if(q != NULL)
if(q->bf != 0) // truong hop chi so can bang cua q la 1 hay -1
{
fya = p;
ya = q;
}
fp = p;
p = q;
}
// Them nut moi (nut la) la con cua nut fp
q = New_Node(); // cấ p phá t vùng nhớ
q->key =x;
q->info = a;
q->bf = 0;
q->left = NULL;
Kỹ thuật lập trì nh 125
q->right = NULL;
if(x info)
fp->left = q;
else
fp->right = q;
/* Hieu chinh chi so can bang cua tat ca cac nut giua ya va q, neu bi lech
ve phia trai thi chi so can bang cua tat ca cac nut giua ya va q deu la
1, neu bi lech ve phia phai thi chi so can bang cua tat ca cac nut giua
ya va q deu la -1 */
if(x info)
p = ya->left;
else
p = ya->right;
s = p; // s la con nut ya
while(p != q)
{
if(x info)
{
p->bf = 1;
p = p->left;
}
else
{
p->bf = -1;
p = p->right;
}
}
// xac dinh huong lech
if(x info)
imbal = 1;
else
imbal = -1;
if(ya->bf == 0)
{
ya->bf = imbal;
return;
}
if(ya->bf != imbal)
{
Kỹ thuật lập trì nh 126
ya->bf = 0;
return;
}
if(s->bf == imbal) // Truong hop xoay don
{
if(imbal == 1) // xoay phai
p = Rotate_Right(ya);
else // xoay trai
p = Rotate_Left(ya);
ya->bf = 0;
s->bf = 0;
}
else // Truong hop xoay kep
{
if(imbal == 1) // xoay kep trai-phai
{
ya->left = Rotate_Left(s);
p = Rotate_Right(ya);
}
else // xoay kep phai-trai -
{
ya->right = Rotate_Right(s);
p = Rotate_Left(ya);
}
if(p->bf == 0) // truong hop p la nut moi them vao
{
ya->bf = 0;
s->bf = 0;
}
else
if(p->bf == imbal)
{
ya->bf = -imbal;
s->bf = 0;
}
else
{
ya->bf = 0;
s->bf = imbal;
}
Kỹ thuật lập trì nh 127
p->bf = 0;
}
if(fya == NULL)
pavltree = p;
else
if(ya == fya->right)
fya->right = p;
else
fya->left = p;
}
* Để tạ o câ y nhị phâ n tì m kiế m câ n bằ ng, ta sử dụng giả i thuậ t sau:
void Create_AVLTree(NODEPTR &root)
{ int khoa, noidung;
char so[10];
NODEPTR p;
do
{ printf("Nhap khoa :");
gets(so) ;
khoa = atoi(so);
if (khoa !=0)
{ printf("Nhap noi dung :");
gets(so) ;
noidung = atoi(so);
if (root==NULL)
{ p = New_Node();
p->key = khoa;
p->info = noidung;
p->bf = 0 ;
p->left = NULL;
p->right = NULL;
root =p;
}
else Insert(root,khoa,noidung);
}
} while (khoa!=0); // khóa =0 thì dừng nhậ p
}
Ghi chú : Để tạ o câ y nhị phâ n do biế n tree quả n lý, ta gọi:
Create_AVLTree(tree);
Kỹ thuật lập trì nh 128
III.2.2. Cập nhật cây:
1. Tì m kiế m (Search): Tì m nút có khóa bằ ng x trê n câ y nhị phâ n AVL có
gốc là root. Nế u tì m thấ y x trong câ y thì trả về địa chỉ của nút có trị bằ ng x
trongcâ y, nế u không có thì trả về trị NULL.
Do AVL là câ y nhị phâ n BST nê n ta có thể tì m kiế m nhanh bằ ng phương
phá p tì m kiế m nhị phâ n, và do tí nh chấ t lúc nà y câ y câ n bằ ng nê n thời gian tì m
kiế m sẽ nhanh hơn rấ t nhiề u.
NODEPTR search(NODEPTR root, int x)
{
NODEPTR p;
p = root;
while(p != NULL && x!=p->key)
if(x key)
p = p->left;
else
p = p->right;
return(p);
}
2. Xóa nút: Remove(root, x):
- Nội dung: xóa nút có khóa x trê n câ y AVL với địa chỉ sao đầ u root sao
cho sau khi xóa thì câ y vẫ n là AVL.
- Giả i thuậ t:
Nế u root == NULL thì Thôngbá o ("Không thể xóa được nút x trê n câ y")
Nế u root != NULL thì
Nế u xinfo thì :
+ Gọi đệ qui để xóa nút x ở nhá nh bê n trá i của root :
Remove(root->left, x)
+ Gọi balance_left để câ n bằ ng lạ i câ y nút gốc root nế u nhá nh câ y
con bê n trá i bị giả m độ cao.
Nế u x > root->info thì :
+ Gọi đệ qui để xóa nút x ở nhá nh bê n phả i của root :
Remove(root->right, x)
+ Gọi balance_right để câ n bằ ng lạ i câ y nút gốc root nế u nhá nh câ y
con bê n phả i bị giả m độ cao.
Nế u x==root->info thì :
Xóa nút root như phép toá n xóa trê n câ y nhị phâ n BST.
- Chương trì nh : tự cà i đặ t.
Kỹ thuật lập trì nh 129
III.2.3. Các phép duyệ t cây:
Do câ y AVL cũng là câ y nhị phâ n nê n ta sẽ á p dụng lạ i cá c phương phá p
duyệ t Preorder, Inorder và Postorder và o câ y AVL.
a. Duyệ t cây theo thứ tự NLR (Preorder):
void Preorder (NODEPTR root)
{
if(root != NULL)
{
printf("%d ", root->info);
Preorder(root->left);
Preorder (root->right);
}
}
b. Duyệ t cây theo thứ tự LNR (Inorder):
void Inorder(NODEPTR root)
{
if(root != NULL)
{
Inorder(root->left);
printf("%d ", root->info);
Inorder(root->right);
}
}
c. Duyệ t cây theo thứ tự LRN (Posorder):
void Posorder(NODEPTR root)
{
if(root != NULL)
{
Posorder(root->left);
Posorder(root->right);
printf("%d ", root->info);
}
}
Kỹ thuật lập trì nh 130
Bài tập:
1. Viế t lạ i cá c chương trì nh duyệ t câ y nhị phâ n theo phương phá p không đệ qui.
2. Viế t chương trì nh tạ o một menu thực hiệ n cá c mục sau:
a. Tạ o câ y nhị phâ n tì m kiế m với nội dung là số nguyê n (không trùng nhau).
b. Liệ t kê câ y nhị phâ n ra mà n hì nh theo thứ tự NLR
c. Đế m tổng số nút, số nút lá , và số nút trung gian của câ y.
d. Tí nh độ cao của câ y.
e. Loạ i bỏ nút có nội dung là x trong câ y nhị phâ n BST.
f. Thê m nút có nội dung x và o câ y nhị phâ n BST sao cho sau khi thê m thì câ y
vẫ n là BST.
3. Cho một câ y nhị phâ n tree, h∙ y viế t chương trì nh để sao chép nó thà nh một
câ y mới tree2, với khóa, nội dung, và liê n kế t giống như câ y tree.
4. Viế t cá c hà m kiể m tra xem câ y nhị phâ n:
a. Có phả i là câ y nhị phâ n đúng không.
b. Có phả i là câ y nhị phâ n đầ y không.
5. Viế t hà m kiể m tra nút x và y có trê n câ y hay không, nế u có cả x lẫ n y trê n
câ y thì xá c định nút gốc của câ y con nhỏ nhấ t có chứa x và y.
6. Cho một câ y biể u thức, h∙ y viế t hà m Calculate (NODEPTR root) để tí nh giá
trị của câ y biể u thức đó, biế t rằ ng cá c toá n tử được dùng trong biể u thức là :
+ - * / ^ % !
7. Vẽ lạ i hì nh ả nh câ y nhị phâ n tì m kiế m, câ y nhị phâ n tì m kiế m câ n bằ ng nế u
cá c nút thê m và o câ y theo thứ tự như sau:
8 3 5 2 20 11 30 9 18 4
8. Nhậ p và o 1 biể u thức số học, chuyể n biể u thức đó thà nh câ y nhị phâ n, nút
gốc là toá n tử, nút lá là cá c toá n hạ ng, biế t rằ ng cá c toá n tử được dùng trong
biể u thức là : + - * / ^ % !
Kỹ thuật lập trì nh 131
MụC LụC
CHƯƠNG i ĐạI CƯƠNG Về LậP TRìNH--------------------------------------------------- 1
I. Khái niệm thuật toán--------------------------------------------------------------------------- 1
I.1. Khái niệm --------------------------------------------------------------------------------------------------- 1
I.2. Các tí nh chấ t đặc trưng của thuậ t toán ----------------------------------------------------- 1
I.3. Phân loạ i ----------------------------------------------------------------------------------------------------- 1
II. Mô tả thuật toán bằng lưu đồ ---------------------------------------------------- 1
II.1. Lưu đồ ------------------------------------------------------------------------------------------------------ 1
II.2. Các ký hiệu trên lưu đồ --------------------------------------------------------------------------- 1
II.3. Một số ví dụ biểu diễn thuậ t toán bằng lưu đồ---------------------------------------- 2
III. CáC NGôN NGữ LậP TRìNH & CHươNG TRìNH DịCH -------------------- 5
III.1. Ngôn ngữ lập trì nh ---------------------------------------------------------------------------------- 5
III.2. Chương trì nh dịch------------------------------------------------------------------------------------ 6
CHươNG 2 LàM QUEN VớI NGôN NGữ C--------------------------------------------- 7
* Giới thiệu ngôn ngữ C ------------------------------------------------------------------------- 7
I. CáC KHáI NIệM Cơ BảN---------------------------------------------------------------------------- 7
I.1. Cấu trúc cơ bản của một chương trì nh C -------------------------------------------------- 7
I.2. Kiểu dữ liệu cơ bản---------------------------------------------------------------------------------- 13
I.3. Biến----------------------------------------------------------------------------------------------------------- 14
I.4 Hằng----------------------------------------------------------------------------------------------------------- 18
I.5. Phép toán -------------------------------------------------------------------------------------------------- 20
* Sự chuyển kiểu----------------------------------------------------------------------------------------- 29
* Mức độ ưu tiên của cá c phép toán---------------------------------------------------------- 29
I.6. Chuỗi--------------------------------------------------------------------------------------------------------- 30
II. Các cấu trúc điều khiển trong C ---------------------------------------------- 33
II.1 Cấu trúc tuần tự (Sequence) ------------------------------------------------------------------ 33
II.2. Cấu trúc chọn------------------------------------------------------------------------------------------ 34
II.2.1. Lệnh if else -------------------------------------------------------------------------------------- 34
II.2.2. Lệnh switch_case ---------------------------------------------------------------------------- 35
II.3. Cấu trúc lặp --------------------------------------------------------------------------------------------- 37
II.3.1. Lệnh while --------------------------------------------------------------------------------------- 37
II.3.2. Lệnh do while ---------------------------------------------------------------------------------- 38
II.3.3. Lệnh for-------------------------------------------------------------------------------------------- 39
* Phát biểu break, continue, goto -------------------------------------------------------------- 40
Bà i tập ---------------------------------------------------------------------------------------------------------------- 41
Kỹ thuật lập trì nh 132
III. Hàm - Đệ quy ------------------------------------------------------------------------------------------ 45
III.1. Hàm-------------------------------------------------------------------------------------------------------- 45
III.2. Đệ qui (Recursion)-------------------------------------------------------------------------------- 52
IV. Structure----------------------------------------------------------------------------------------------- 54
IV.1. Định nghĩ a------------------------------------------------------------------------------------ 55
IV.2. Khai báo--------------------------------------------------------------------------------------- 55
V. FILE---------------------------------------------------------------------------------------------------------------- 56
V.1. File vă n bản--------------------------------------------------------------------------------------------- 56
V.2. File nhị phân (file có cấu trúc) -------------------------------------------------------------- 61
V.3. Phát hiện lỗi khi truy xuấ t tập tin ---------------------------------------------------------- 66
Bà i tập ---------------------------------------------------------------------------------------------------------------- 67
CHươNG 3. CáC THUậT TOáN TRÊN CấU TRúC Dữ LIệU MảNG 69
I. Mảng không sắp xếp và thuật toán tìm kiếm ------------------ 69
trên mảng chưa có thứ tự
I.1. Một số khái niệm về mảng ---------------------------------------------------------------------- 69
I.2. Thuật toán tì m kiếm trên mảng chưa có thứ tự -------------------------------------- 71
II. Các thuật toán sắp xếp ------------------------------------------------------------------- 73
II.1. Sắp xếp theo phương pháp Bubble_Sort ------------------------------------------------ 73
II.2. Sắp xếp theo phương pháp Quick_Sort-------------------------------------------------- 75
III. Tìm kiếm trên mảng đã có thứ tự --------------------------------------------- 79
III.1. Tì m kiếm nhanh bằng phương pháp lặp----------------------------------------------- 79
III.2. Phép tì m kiếm nhị phân ------------------------------------------------------------------------ 80
III.3. Phép tì m kiếm nhị phân đệ qui ------------------------------------------------------------- 81
Bà i tập ---------------------------------------------------------------------------------------------------------------- 82
CHƯƠNG 4 CON TRỏ (POINTER) ---------------------------------------------------------- 84
I. ĐịNH NGHĩA ------------------------------------------------------------------------------------------------- 84
I.1. Khai báo---------------------------------------------------------------------------------------------------- 84
I.2. Truyền địa chỉ cho hàm --------------------------------------------------------------------------- 85
II Các phép toán trên biến con trỏ ----------------------------------------------- 85
II.1. Toán tử địa chỉ &----------------------------------------------------------------------------------- 85
II.2. Toán tử nội dung * --------------------------------------------------------------------------------- 85
II.3. Phép cộng trừ biến con trỏ với một số nguyên-------------------------------------- 86
II.4. Phép gán và phép so sá nh----------------------------------------------------------------------- 86
II.5. Sự chuyển kiểu---------------------------------------------------------------------------------------- 86
II.6. Khai báo một con trỏ hằng và con trỏ chỉ đến đối tượng hằng ------------ 87
III. Sự tương quan giữa con trỏ và mảng----------------------------------- 87
Kỹ thuật lập trì nh 133
IV. Con trỏ và chuỗi-------------------------------------------------------------------------------- 91
IV.1. Khai báo------------------------------------------------------------------------------------------------- 91
IV.2. Xét một số ví dụ về cá c hàm xử lý chuỗi--------------------------------------------- 91
IV.3. Mảng con trỏ chỉ đến chuỗi------------------------------------------------------------------ 93
Bà i tập ---------------------------------------------------------------------------------------------------------------- 95
CHƯƠNG 5 CáC THUậT TOáN TRÊN CấU TRúC --------------------------- 96
DANH SáCH LIÊN KếT (LINKED LIST).
I. Khái niệm---------------------------------------------------------------------------------------------------------------- 96
II. Các phép toán trên danh sách liên kết----------------------------------- 97
II.1. Tạo danh sá ch ----------------------------------------------------------------------------------------- 97
II.2. Cập nhật danh sá ch--------------------------------------------------------------------------------- 99
II.3. Duyệt danh sá ch------------------------------------------------------------------------------------100
II.4. Tì m kiếm-----------------------------------------------------------------------------------------------100
II.5. Sắp xếp --------------------------------------------------------------------------------------------------101
Bà i tập --------------------------------------------------------------------------------------------------------------102
CHươNG 6 các thuật toán trên cấu trúc câY---------------------104
I. Phân loại cây----------------------------------------------------------------------------------------104
I.1. Một số khái niệm cơ bản -----------------------------------------------------------------------104
I.2. Cách biểu diễn cây ---------------------------------------------------------------------------------106
I.3. Biểu diễn thứ tự các nút trong cây---------------------------------------------------------106
II. Cây nhị phân (Binary tree)----------------------------------------------------------107
II.1. Định nghĩ a---------------------------------------------------------------------------------------------107
II.2. Các phép toán trên cây nhị phân----------------------------------------------------------110
1. Tạo cây--------------------------------------------------------------------------------------------------110
2. Cập nhật cây -----------------------------------------------------------------------------------------112
3. Các phép duyệ t cây ------------------------------------------------------------------------------116
III. cây nhị phân TìM KIếM cân bằng (AVL) --------------------------------117
III.1. Định nghĩ a-------------------------------------------------------------------------------------------117
III.2. Các phép toán trên cây AVL --------------------------------------------------------------118
III.2.1. Thêm nút---------------------------------------------------------------------------------------118
III.2.2. Cập nhật cây---------------------------------------------------------------------------------126
III.2.3. Các phép duyệt cây----------------------------------------------------------------------127
Bà i tập --------------------------------------------------------------------------------------------------------------129
TàI LIệU THAM KHảO
1. Kỹ thuậ t lậ p trì nh Turbo C Đỗ Phúc, Nguyễ n Phi Khử, 1992
Tạ Minh Châ u,
Nguyễ n Đì nh Tê
2. Cấ u trúc dữ liệ u – ứng dụng Nguyễ n Hồng Chương 1999
và cà i đặ t bằ ng C
3. Những viê n ngọc Kỹ thuậ t JohnBentley
lậ p trì nh
Các file đính kèm theo tài liệu này:
- giao_trinh_mon_ky_thuat_lap_trinh.pdf