1 Đại học Quốc Gia TP Hồ Chí Minh Trường đại học Bách Khoa Khoa Khoa học & Kỹ thuật Máy tính Bộ môn Khoa học Máy tính ĐỀ THI CUỐI HỌC KỲ 1 Năm học 2011 – 2012 Môn Cấu trúc dữ liệu & Giải thuật MSMH 50[.]
Trang 11
Đại học Quốc Gia TP Hồ Chí Minh
Trường đại học Bách Khoa
Khoa: Khoa học & Kỹ thuật Máy tính
Bộ môn: Khoa học Máy tính
ĐỀ THI CUỐI HỌC KỲ 1
Năm học: 2011 – 2012
Môn: Cấu trúc dữ liệu & Giải thuật
MSMH: 503001 Ngày thi: 07/01/2012 - Thời gian: 120 phút
(Được sử dụng tài liệu)
Lưu ý: Đề thi gồm 4 câu với thang điểm 11/10
Câu 1: (1.5 điểm)
Cho một dãy gồm 11 số như sau: 6, 12, 4, 19, 22, 3, 2, 15, 13, 17, 30
a (1 điểm) Cây AVL được xây dựng dựa trên chuỗi số này, giả sử các số được nhập vào
khi xây dựng cây đúng theo thứ tự trên Hãy vẽ cây AVL tại các trạng thái chèn (insert)
thành công lần lượt các phần tử: 22, 2, 13, 17 và 30
+22
6
+2
6
+13
6
+17
6
+30
15
Trang 2b (0.5 điểm) Giả sử cây AVL được xây dựng ở câu a lần lượt bị xóa các phần tử sau: 17,
13, 22, 19 Vẽ lại các cây AVL sau khi từng phần tử trên bị xóa khỏi cây
Trường hợp “using largest node in the left-subtree”:
Trường hợp “using smallest node in the right-subtree”
Câu 2: (2.5 điểm)
Ta ký hiệu L(H) là dạng trình bày của max-heap H dưới dạng dãy
-17
15
12
-13
15
-22
15
30
-19
6
30
12
-19
6
30
12
-22
15
19
Trang 33
Ví dụ: Một dãy số ban đầu như sau: (1, 2, 3), sau khi xây dựng thành heap HT, thì L(HT)
= (3, 1, 2)
a (1 điểm) Với dãy số ban đầu gồm 11 số như sau: (6, 12, 4, 19, 22, 3, 2, 15, 13, 17, 30),
ta xây dựng thành heap H1 Giả sử các số được đưa vào H1 theo đúng thứ tự trên Cho biết L(H1)
Solution: L(H) = (30,22,4,15,19,3,2,6,13,12,17)
b (0.5 điểm) Sau khi loại bỏ 3 phần tử khỏi H1, ta được H2 Cho biết L(H2)
Solution: L(H_2) = (17,15,4,13,12,3,2,6)
c (1 điểm)
Cho cấu trúc dữ liệu heap với các phương thức sẵn có như hình 1 Hiện thực thêm
phương thức convert2MaxHeap để chuyển đổi heap từ min-heap thành max-heap
Lưu ý : Do số lượng phần tử n của heap là khá lớn, giải thuật sắp xếp này không được khai báo thêm biến phụ có dung lượng lưu trữ tương đương với n (ví dụ như khai
báo một dãy tạm có độ lớn là n/10 vì n/10 và n là tương đương)
Hình 1: Cấu trúc dữ liệu heap
Solution:
void convert2MaxHeap() {
for(int position=count/2-1; position>=0; position ){
reMaxHeapDown(position, count-1);
}
}
Câu 3: (2 điểm)
Xét dãy số: 6, 12, 4, 19, 22, 3, 2, 15, 13, 17, 30
Dành cho lớp thường (không cần làm câu b và câu c):
a (2 điểm) Vẽ bảng biểu diễn các bước thực thi dựa theo các thuật toán sau: straight selection sort, bubble sort và merge sort (Sinh viên xem ví dụ bảng biểu diễn các bước
thực thi trong hình 2)
Class heap Private:
data: array<element’stype>
count: int protected:
reMaxHeapUp(position) reMaxHeapDown(position, lastPosition) reMinHeapUp(position)
reMinHeapDown(position, lastPosition) Public:
insertMaxHeap(element) insertMinHeap(element) deleteMaxHeap()
deleteMinHeap() End class
Trang 4Hình 2 Bảng liệt kê các bước thực thi của giải thuật Straight Insertion Sort
Solution:
Straight selection sort:
6 12 4 19 22 3 2 15 13 17 30
2 12 4 19 22 3 6 15 13 17 30
2 3 4 19 22 12 6 15 13 17 30
2 3 4 19 22 12 6 15 13 17 30
2 3 4 6 22 12 19 15 13 17 30
2 3 4 6 12 22 19 15 13 17 30
2 3 4 6 12 13 19 15 22 17 30
2 3 4 6 12 13 15 19 22 17 30
2 3 4 6 12 13 15 17 19 22 30
2 3 4 6 12 13 15 17 19 22 30
2 3 4 6 12 13 15 17 19 22 30
Bubble sort:
6 12 4 19 22 3 2 15 13 17 30
2 6 12 4 19 22 3 13 15 17 30
2 3 6 12 4 19 22 13 15 17 30
2 3 4 6 12 13 19 22 15 17 30
2 3 4 6 12 13 15 17 19 22 30
2 3 4 6 12 13 15 17 19 22 30
2 3 4 6 12 13 15 17 19 22 30
2 3 4 6 12 13 15 17 19 22 30
2 3 4 6 12 13 15 17 19 22 30
2 3 4 6 12 13 15 17 19 22 30
2 3 4 6 12 13 15 17 19 22 30
Merge sort:
6 12 4 19 22 3 2 15 13 17 30
4 6 12 19 22 3 2 15 13 17 30
3 4 6 12 19 22 2 15 13 17 30
3 4 6 12 19 22 2 13 15 17 30
3 4 6 12 19 22 2 13 15 17 30
6 12 4 19 22 3 2 15 13 17 30
6 12 4 19 22 3 2 15 13 17 30
4 6 12 19 22 3 2 15 13 17 30
4 6 12 19 22 3 2 15 13 17 30
4 6 12 19 22 3 2 15 13 17 30
3 4 6 12 19 22 2 15 13 17 30
2 3 4 6 12 19 22 15 13 17 30
2 3 4 6 12 15 19 22 13 17 30
2 3 4 6 12 13 15 19 22 17 30
2 3 4 6 12 13 15 17 19 22 30
Trang 55
2 3 4 6 12 13 15 17 19 22 30
Dành cho lớp KSTN (không cần làm câu a):
b (1 điểm) Vẽ bảng biểu diễn các bước thực thi dựa theo hai trong các thuật giải được liệt kê trong câu a để thực hiện việc sắp xếp
c (1 điểm) Dựa trên thuật giải quicksort được trình bày trong bộ slide lý thuyết của môn học, viết thuật giải để trả về phần tử lớn thứ k trong một danh sách n phần tử phân biệt
(được lưu trữ trong một mảng cho trước) Độ phức tạp trong trường hợp xấu nhất có phải
là O(n log n) ? Nếu không, hãy đề xuất giải pháp cải tiến để có được độ phức tạp này
Solution:
Algorithm FindKth(k<int>)
If(k > count) return ;
recursiveFindKth(0,count-1,k)
End FindKth
Algorithm recursiveFindKth(int lowIndex, int highIndex, int k)
if(lowIndex >= highIndex) return lowIndex ;
// Divide data into 2 parts and return index of pivot
pivot_position= Partition(lowIndex, highIndex)
if(pivot_position == k-1)
return data[pivot_position] ; // Pivot is the kth maximum value
if(pivot_position > k-1) // just run recursive on the first division
return recursiveFindKth (lowIndex, pivot_position-1,k)
else
return recursiveFindKth (pivot_position+1, highIndex,k)
End recursiveFindKth
Trong trường hợp xấu nhất :
k = n và phần từ pivot được chọn luôn là phần tử cực đại hoặc cực tiểu trong mỗi partition Khi đó sẽ như trường hợp xấu nhất của giải thuật Quicksort là 0(n^2), không phải 0(nlogn)
Cải tiến :
Giải thuật Quicksort trong slide bài giảng chọn giá trị pivot ở vị trí giữa trong dãy dữ liệu Trong trường hợp xấu nhất, nếu phần tử pivot luôn có giá trị cực đại hoặc cực tiểu bên trong dãy dữ liệu thì giải thuật Quicksort sẽ phải thực hiện xấp xỉ n lần hàm Partition Trong khi chi phí mỗi lần gọi Partition để phân tách dữ liệu xấp xỉ n Do đó độ phức tạp
là O(n^2)
Để cải tiến ta phải cố gắng giảm số lần thực thi hàm Partition => chọn phần tử pivot có giá trị giữa để đạt được xấp xỉ logn lần gọi Partition
Trang 6=> Thêm vào bên trong hàm Partition của giải thuật Quicksort phần tiền xử lý, xác định
phần tử được chọn là pivot chính là phần tử có giá trị gần với giá trị trung bình của các giá trị có trong danh sách
Int findPivotPosition(int low, int high) {
int sum =0 ;
int count = high – low + 1 ;
fore(i from low to hight) {
sum+=data<i> ;
}
Int position = low;
For(i from low to high) {
if(|data<position> * count – sum| > |data<i> * count - sum|) {
position = i ;
}
}
}
int Partition(int low, int high) {
// last_smallis the position of the last key less than pivot
swap (low, findPivotPosition(low,hight)) // First entry is now pivot
pivot = entrylow
last_small= low
i= low+ 1
loop(i<= high)
if(datai< pivot) {
last_small= last_small+ 1
swap(last_small, i) // Move large entry to right and small to left
}
swap(low, last_small) // Put the pivot into its proper position
return last_small
}
Độ phức tạp của hàm tìm findPivotPosition là O(n) vì vậy độ phức tạp của cả hàm partition là O(n)
Câu 4: (3 điểm)
Xét bài toán về việc cập nhật thông tin giữa các chi nhánh đồng cấp trong một tổ chức
Dữ liệu cụ thể về một mạng lưới truyền tin như sau:
AB(6), AC(3), AE(9), AJ(6), BD(4), CD(2), CI(1), DE(4), DF(3), DH(7), EG(3), FG(6), FH(8), GK(4), HJ(1), HK(3), IJ(5), JK(2)
Trong đó XY(n) có nghĩa là thời gian truyền tin từ X đến Y mất n đơn vị thời gian và
ngược lại
a (1 điểm) Biểu diễn ma trận liền kề của đồ thị đã cho Dựa trên đồ thị đã cho, xây dựng
và biểu diễn ma trận liền kề của đồ thị con thỏa mãn điều kiện sau:
- Chứa tất cả các đỉnh của đồ thị ban đầu
- Có duy nhất một thành phần liên thông
Trang 77
- Tập cạnh là tập con của tập cạnh ban đầu và tổng thời gian của tập cạnh này là nhỏ nhất
Số cạnh của đồ thị con này là bao nhiêu ? Chứng minh đồ thị này không bao giờ xuất hiện chu trình
Solution:
Biểu diễn ma trận liền kề của đồ thị đã cho:
A B C D E F G H I J K
A 0 6 3 0 9 0 0 0 0 6 0
B 6 0 0 4 0 0 0 0 0 0 0
C 3 0 0 2 0 0 0 0 1 0 0
D 0 4 2 0 4 3 0 7 0 0 0
E 9 0 0 4 0 0 3 0 0 0 0
F 0 0 0 3 0 0 6 8 0 0 0
G 0 0 0 0 3 6 0 0 0 0 4
H 0 0 0 7 0 8 0 0 0 1 3
I 0 0 1 0 0 0 0 0 0 5 0
J 6 0 0 0 0 0 0 1 5 0 2
K 0 0 0 0 0 0 4 3 0 2 0
Với những yêu cầu của đồ thị con thì đồ thị con cần tìm là cây phủ tối thiểu của đồ thị ban đầu Áp dụng giải thuật Prim tìm cây phủ tối thiểu trên đồ thị vô hướng Ta có được
đồ thị cần tìm (theo ma trận liền kề bên dưới)
A B C D E F G H I J K
A 0 0 3 0 0 0 0 0 0 0 0
B 0 0 0 4 0 0 0 0 0 0 0
C 3 0 0 2 0 0 0 0 1 0 0
D 0 4 2 0 0 3 0 0 0 0 0
E 0 0 0 4 0 0 3 0 0 0 0
F 0 0 0 3 0 0 0 0 0 0 0
G 0 0 0 0 3 0 0 0 0 0 4
H 0 0 0 0 0 0 0 0 0 1 0
I 0 0 1 0 0 0 0 0 0 0 0
J 6 0 0 0 0 0 0 1 0 0 2
K 0 0 0 0 0 0 4 0 0 2 0
B
Trang 8Với cây phủ tối thiểu của đồ thị vô hướng, số cạnh bằng |V| -1 với V là tập các đỉnh của
đồ thị Nên trong trường hợp này, số cạnh bằng 10
Và theo định nghĩa cây phủ, đồ thị thu được không có chu trình
b (0.5 điểm) Cho biết thứ tự duyệt các đỉnh của đồ thị trong câu a tương ứng với các
phương pháp depth-first traveral và breadth-first traveral Lưu ý rằng trong trường hợp
nhiều đỉnh có thể được chọn, các đỉnh sẽ được chọn theo thứ tự trong bảng chữ cái
Solution:
Theo thứ tự bảng chữ cái, root trong quá trình duyệt sẽ bắt đầu từ A
Depth-first ordering
A – C – D – B – E – G – K – J – H – F - I
Breadth-first ordering
A – C – D – I – B – E – F – G – K – J – H
Dành cho lớp thường (không cần làm câu d):
c (1.5 điểm) Ứng với đồ thị trong câu a, viết giải thuật để xác định thời gian cần thiết để
truyền thành công một thông điệp từ chi nhánh X đến tất cả các chi nhánh còn lại (với X
được cho trước)
Solution:
Đồ thị thu được từ câu a là cây phủ tối thiểu nên không có chu trình hay giữa 2 đỉnh bất
kì sẽ có duy nhất một đường đi.Nếu là thời gian cần thiết để truyền thành công thông điệp
từ X tới mọi chi nhánh khác sẽ bằng: max( thời gian truyền từ X đến các node lá)
Tại mỗi đỉnh ta lưu trữ thông tin:
max: chứa giá trị thời gian cần thiết để truyền từ đỉnh đó tới tất cả các đỉnh con maxChild: chứa đỉnh con tương ứng với đường đi có giá trị thời gian max
int findTime(X) {
int max = 0;
recursiveFindTime1(X);
return X.max;
}
Void recursiveFindTime1(Vertex v) {
Foreach(Vertex w adjacent to v) {
recursiveFindTime1(w);
int newVal = w.max + weight(w,v);
if(v.max < newVal) {
v.max = newVal;
v.maxChild = w;
}
}
Trang 99
}
Dành cho lớp KSTN (không cần làm câu c):
d (1.5 điểm) Ứng với đồ thị con thu được ở câu a, xác định thời gian t cần thiết để truyền
thành công một thông điệp từ một chi nhánh bất kỳ đến tất cả các chi nhánh còn lại
d1 (0.5 điểm) Viết giải thuật để tính số t này
d2 (1 điểm) Do hạn chế về thời gian tính toán, yêu cầu thuật giải có độ phức tạp tối
đa là O(n) với n là số lượng thành phố (nếu thuật giải đề xuất ở câu d1 chưa đạt được O(n) thì cần đề xuất giải thuật cải tiến)
Solution:
Vì đồ thị ở câu a là cây phủ tối thiểu (không có chu trình) nên giữa 2 đỉnh bất kì sẽ có duy nhất một đường đi Vì vậy thời gian cần thiết để truyền từ nhánh bất kì đến tất cả các nhánh còn lại là Max(đường nối giữa 2 đỉnh bất kì)
int findTime() {
Int max = 0;
Vertex X in Graph; // X is any Vertex in Graph
recursiveFindTime1(X);
recursiveFindTime2(X);
return X.tmpMax;
}
// recursiveFindTime1(v) : dùng để xác định thời gian cần thiết để truyền tin từ chi nhánh
v đến các đỉnh con của nó (hay nói cách khác xác định đến các node lá con)
Void recursiveFindTime1(Vertex v) {
/*
Duyệt DFS bắt nguồn từ v
Pre: Subroot trong quá trình duyệt DFS
Post: Mỗi đỉnh sẽ chứa các giá trị max và childMax như lời giải ở câu c
max: chứa giá trị thời gian cần thiết để truyền từ đỉnh đó tới tất cả các đỉnh con
maxChild: chứa đỉnh con tương ứng với đường đi có giá trị thời gian max
*/
Foreach(Vertex w adjacent to v) {
recursiveFindTime1(w);
int newVal = w.max + weight(w,v);
if(v.max < newVal) {
v.max = newVal;
v.maxChild = w;
}
}
}
// recursiveFindTime2 dùng để xác định thời gian cần thiết để truyền tin từ 1 node lá con
bất kỳ của v đến một node lá con bất kỳ khác của v (v là tổ tiên chung đầu tiên của
chúng) Thuật giải này sẽ cần thừa kế kết quả của thuật toán recursiveFindTime1 Để
Trang 10hiện thực thuật giải này, tại một node chỉ cần xác đinh hai nhánh con có thời gian truyên tin xa nhất rồi tính tổng của chúng Sau mỗi lần duyệt thuật toán này tại mỗi node trong
đồ thị, ta cần cập nhật để xác đinh thời gian cần thiết để truyền tin từ 1 node (lá con) bất
kỳ đến một node lá con bất kỳ khác
Void recursiveFindTime2(Vertex v) {
Foreach(Vertex w adjacent to v) {
recursiveFindTime2(w);
w.tmpMax = w.max;
Foreach(Vertex u adjacent to w and u != w.maxChild) {
If(w.tmpMax < w.maxChild.max + u.max) {
w.tmpMax = w.maxChild.max + u.max;
}
}
If(v.tmpMax < tmpMax) v.tmpMax = w.tmpMax;
}
}
Câu 5: (2 điểm)
Cho một dãy gồm 11 số như sau: 6, 12, 4, 19, 22, 3, 2, 15, 13, 17, 30
a (1 điểm) Xây dựng hai cây B-tree tương ứng với dãy số trên, với số bậc của hai cây này là 3 và 5 Giả sử thứ tự các phần tử được đưa vào cây tương ứng với thứ tự trên dãy
Solution:
B-Tree với bậc 3:
Root hoặc là lá hoặc có ít nhất 2 cây con
Mỗi inner node có ít nhất 1 entry
Các lá có cùng level
B-Tree với bậc 5
Root hoặc là lá hoặc có ít nhất 2 cây con
Mỗi inner node có ít nhất 2 entry
Các lá có cùng level
6
15 17 22 30
12
2 3 4 6
12 17
13 15 19 22 30
Trang 1111
b (1 điểm) Vẽ lại hai cây B-Tree được xây dựng ở câu a sau khi xóa phần tử 15 ra khỏi hai cây này
Hết
6
17 22 30
12
2 3 4 6
12 19
13 17 22 30