You are on page 1of 7

Bài 3: CÂY THỨ TỰ BỘ PHẬN

I. MỤC TIÊU:
Giúp sinh viên hiểu được cấu trúc cây thứ tự bộ phận và cài đặt các phép toán trên cây thứ
tự bộ phận. Bài thực hành này sẽ cài đặt hàng ưu tiên bằng cây thứ tự bộ phận.
II. TÓM TẮT LÝ THUYẾT:
Hàng ưu tiên (priority queue) được xem là một tập hợp các đối tượng dữ liệu, mỗi đối tượng
có một giá trị ưu tiên. Thông thường các giá trị ưu tiên có thể là các số nguyên, các số thực,
các ký tự…; điều quan trọng là chúng ta có thể so sánh được các giá trị ưu tiên.
Các phép toán trên hàng ưu tiên:
1. Insert (P,x). Xen vào hàng ưu tiên P đối tượng x.
2. FindMin(P). Hàm trả về đối tượng trong P có giá trị ưu tiên nhỏ nhất (đối tượng được ưu
tiên nhất). Phép toán này đòi hỏi P không rỗng
3. DeleteMin(P). Loại bỏ và trả về đối tượng có giá trị ưu tiên nhỏ nhất trong P. P cũng cần
phải không rỗng
Có nhiều phương pháp cài đặt hàng ưu tiên:
• Bằng danh sách
• Bằng cây nhị phân tìm kiếm
• Bằng cây thứ tự bộ phận
Trong bài thực hành này chúng ta sẽ cài đặt hàng ưu tiên bằng cây thứ tự bộ phận.

Trong cây nhị phân tìm kiếm, các khóa của dữ liệu chứa trong các đỉnh của cây cần phải thỏa
mãn tính chất thứ tự: khóa của một đỉnh bất kỳ lớn hơn khóa của các đỉnh trong cây con trái và
nhỏ hơn khóa của các đỉnh trong cây con phải.
Trong cây thứ tự bộ phận, chỉ đòi hỏi các khóa chứa trong các đỉnh thỏa mãn tính chất thứ
tự bộ phận: Khóa của một đỉnh bất kỳ nhỏ hơn hoặc bằng khóa của các đỉnh con của nó.
• Cây nhị phân đầy đủ:
• Cây rỗng (độ cao bằng 0)
• Cây có 1 nút gốc (độ cao bằng 1)
• Cây nhĩ phân có độ cao lớn hơn hoặc bằng 2 được xem là đầy đủ nếu tất cả các đỉnh
ở mức trên (mức 1,2 3…) đều có đầy đủ cả 2 cây con
Ví dụ:

• Cây nhị phân hoàn toàn (complete binary tree):


• Cây rỗng (độ cao bằng 0)
• Cây có 1 nút gốc (độ cao bằng 1)
• Cây nhị phân có độ cao lớn hơn hoặc bằng 2 nếu:
• Cây kể từ mức h-1 trở lên là cây nhị phân đầy đủ

Khoa CNTT – Trường ĐH Công Nghệ Sài Gòn Trang 1


Bài 3: CÂY THỨ TỰ BỘ PHẬN

• Ở mức h-1, nếu 1 đỉnh chỉ có 1 con thì các đỉnh đứng trước nó (nếu có) có
đầy đủ 2 con, nếu 1 đỉnh chỉ có 1 con thì nó phải là đỉnh con trái.
• Ví dụ:

• Cây nhị phân cân bằng:


• Trong một cây nhị phân, nếu độ cao của cây con trái của một đỉnh bất kỳ và độ cao
của cây con phải của đỉnh đó khác nhau không quá 1 thì cây được gọi là cây nhị
phân cân bằng.
• Ví dụ:

Cây thứ tự bộ phận (partially ordered tree, hoặc heap) là một cây nhị phân hoàn toàn và thỏa
mãn tính chất thứ tự bộ phận. Ví dụ, cây nhị phân trong hình sau là cây thứ tự bộ phận

• Cây nhị phân hoàn toàn


• Cây kể từ mức h-1 trở lên là cây nhị phân đầy đủ
• Ở mức h-1, nếu 1 đỉnh chỉ có 1 con thì các đỉnh đứng trước nó (nếu có) có
đầy đủ 2 con, nếu 1 đỉnh chỉ có 1 con thì nó phải là đỉnh con trái.
• Tính chất này giúp cài đặt cây thứ tự bộ phận bởi mảng.

Khoa CNTT – Trường ĐH Công Nghệ Sài Gòn Trang 2


Bài 3: CÂY THỨ TỰ BỘ PHẬN

• Tính chất thứ tự bộ phận giúp ta nhận ra đặc điểm sau:


• Các giá trị khóa nằm trên đường đi từ gốc tới các nút lá tạo thành một dãy không
giảm.
• Ví dụ các giá trị từ gốc (đỉnh 0) đến đỉnh 8 là 3,6,9,15.
• Dữ liệu có khóa nhỏ nhất được lưu trong gốc của cây thứ tự bộ phận.

Thuật toán chèn phần tử vào cây thứ tự bộ phận:


Đi từ đỉnh mới thêm vào lên gốc cây, mỗi khi ta đang ở một đỉnh có khóa nhỏ hơn khóa của
đỉnh cha nó thì ta hoán vị dữ liệu chưá trong hai đinh đó và đi lên đỉnh cha. Quá trình đi lên sẽ
dừng lại khi ta đạt tới một đỉnh có khóa lớn hơn khóa của đỉnh cha nó, hoặc cùng lắm là khi đạt
tới gốc cây.
Ví dụ:

Khoa CNTT – Trường ĐH Công Nghệ Sài Gòn Trang 3


Bài 3: CÂY THỨ TỰ BỘ PHẬN

Thuật toán xóa phần tử khỏi cây thứ tự bộ phận:


Giả sử ta đang ở đỉnh p, con trái của p (nếu có) là vl, con phải (nếu có) là vr . Giả sử đỉnh p
có khóa lớn hơn khóa của ít nhất một trong hai đỉnh con là vl và vr. Khi đó, nếu khóa của đỉnh vl
nhỏ hơn khóa của đỉnh vr thì ta hoán vị các dữ liệu trong p và vl và đi xuống đỉnh vl; nếu ngược
lại, ta hoán vị các dữ liệu trong p và vr, rồi đi xuống đỉnh vr. Quá trình đi xuống sẽ dừng lại khi
ta đạt tới một đỉnh có khóa nhỏ hơn khóa của các đỉnh con, hoặc cùng lắm là khi đạt tới một đỉnh
lá.
Ví dụ:

Khoa CNTT – Trường ĐH Công Nghệ Sài Gòn Trang 4


Bài 3: CÂY THỨ TỰ BỘ PHẬN

III. NỘI DUNG THỰC HÀNH:


1. Tạo dữ liệu:
 Tạo hàng ưu tiên theo thứ tự nhập như sau: 3, 2, 1
 Xóa phần tử nhỏ nhất trong hàng ưu tiên
 Tiếp tục chèn các phần tử: 15, 5, 4, 45
 Lấy ra phần tử đầu tiên của hàng ưu tiên.
 Viết ra giấy kết quả cuối cùng của hàng ưu tiên trên.
2. Chương trình mẫu:
a. Lab3_1 (file Header.h):
Dòng Mã lệnh
1 #include <iostream>
2 using namespace std;
3
4 const int MAX = 100;
5 struct PriQueue
6 {
7 int list[MAX];
8 int count;
9 };
10
11 void init(PriQueue &pq);
12 bool isEmpty(PriQueue pq);
13 bool isFull(PriQueue pq);
14 void insertKey(PriQueue &pq, int key);
15 void deleteKey(PriQueue &pq);
16 int getFirst(PriQueue pq);
17
18 int getParent(int i);
19 int getLeft(int i);
20 int getRight(int i);
21
22 void shiftDown(PriQueue &pq, int i);
Khoa CNTT – Trường ĐH Công Nghệ Sài Gòn Trang 5
Bài 3: CÂY THỨ TỰ BỘ PHẬN

23 void shiftUp(PriQueue &pq, int i);


24
25 void swap(int *x, int *y);

b. Lab3_2 (file Source.cpp):

Dòng Mã lệnh
1 void init(PriQueue &pq)
2 {
3 pq.count = 0;
4 }
5 bool isEmpty(PriQueue pq)
6 {
7 return pq.count == 0;
8 }
9 bool isFull(PriQueue pq)
10 {
11 return pq.count == MAX;
12 }
13 int getFirst(PriQueue pq)//top
14 {
15 if (pq.count == 0)
16 {
17 cout << "khong co phan tu";
18 return 0;
19 }
20 return pq.list[0];
21 }
22
23 int getParent(int i)
24 {
25 return (i - 1) / 2;
26 }
27 int getLeft(int i)
28 {
29 return (2 * i + 1);
30 }
31 int getRight(int i)
32 {
33 return (2 * i + 2);
34 }
35 void shiftDown(PriQueue &pq, int i)
36 {
37 //lấy con trái và con phải của nút tại vị trí i
38 int left = getLeft(i);
39 int right = getRight(i);
40 int smallest = i;
41

Khoa CNTT – Trường ĐH Công Nghệ Sài Gòn Trang 6


Bài 3: CÂY THỨ TỰ BỘ PHẬN

42 //so sánh pqlist[i] với trái và phải để tìm giá trị


43 nhỏ nhất
44 if (left < pq.count && pq.list[left] < pq.list[i])
45 {
46 smallest = left;
47 }
48 if (right < pq.count && pq.list[right] <
49 pq.list[smallest])
50 {
51 smallest = right;
52 }
53 if (smallest != i)
54 {
55 swap(pq.list[i], pq.list[smallest]);
56 shiftDown(pq, smallest);
57 }
58 }
59 void swap(int *x, int *y)
60 {
61 int temp = *x;
62 *x = *y;
63 *y = temp;
64 }

c. Lab3_3 (file Main.cpp):


Sinh viên lần lượt gọi các hàm để tạo hàng ưu tiên như trong phần 1 (tạo dữ liệu).
3. Bài tập tổng hợp:
 Viết hàm void insertKey(PriQueue &pq, int key); để chèn phần tử vào hàng
đợi
 Viết hàm void deleteKey(PriQueue &pq); để xóa phần tử khỏi hàng đợi.
 Viết lại hàm void shiftUp(PriQueue &pq, int i) không dùng kỹ thuật đệ quy
(gợi ý: sử dụng vòng lặp để duyệt tất cả các phần tử).
4. Bài tập làm thêm:
Sinh viên cài đặt hàng ưu tiên theo thứ tự lớn nhất

Khoa CNTT – Trường ĐH Công Nghệ Sài Gòn Trang 7

You might also like