Tải bản đầy đủ (.pdf) (19 trang)

bài báo cáo môn phân tích thuật toán chia để trị

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 (492.83 KB, 19 trang )





Nhóm thực hiện
Trần Đình Anh Huy
0811062

Nguyễn Hồng Quy
0811137

Nguyễn Hoàng Quốc
0811300
GV: TS. Trần Nam Dũng
Đại Học Khoa Học Tự Nhiên Hồ Chí Minh
Khoa Toán – Tin Học
Bài Báo Cáo Môn Phân Tích Thuật Toán
Tóm tắt nội dung
Chia để trị là một mô hình thiết kế thuật toán rất quan trọng trong
ngành khoa học máy tính. Mô hình sử dụng chủ yếu giải thuật đệ quy,
được sử dụng phổ biến để giải quyết các vấn đề , bài toán phức tạp nhằm
mục đích giảm chi phí của bài toán đến mức tối ưu có thể. Tư tưởng của
phương pháp chia để trị hình thành rất sớm (khoảng 200 năm trước công
nguyên
1
) từ một bài toán sắp xếp các mặt hàng một cách đơn giản của
người Babylon. Trong khuôn khổ bài báo cáo môn học, nhóm thực hiện chỉ
nêu lên những vấn đề cơ bản của phương pháp này.
1
theo http:// en.wikipedia
Mục lục


1 Tư Tưởng Chia Để Trị 3
1.1 Tại Sao Phải Chia . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1.1 Ưu Điểm . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1.2 Nhược Điểm . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 Các Bước Thực Hiện . . . . . . . . . . . . . . . . . . . . . . 4
1.3 Các Vấn Đề Cài Đặt . . . . . . . . . . . . . . . . . . . . . . . 5
1.3.1 Chia Ra Nhiều Sẽ Dễ Trị? . . . . . . . . . . . . . . . 5
1.3.2 Mối Quan Hệ Với Đệ Quy . . . . . . . . . . . . . . . 6
1.3.3 Các Vấn Đề Về Cài Đặt . . . . . . . . . . . . . . . . . 6
2 Những Bài Toán Sử Dụng Phương Pháp Chia Để Trị 7
2.1 Thuật Toán Tìm Kiếm . . . . . . . . . . . . . . . . . . . . . 7
2.1.1 Quick Sort . . . . . . . . . . . . . . . . . . . . . . . . 7
2.1.2 Merge Sort . . . . . . . . . . . . . . . . . . . . . . . 8
2.2 Nhân 2 Số Nhị Phân N Bit . . . . . . . . . . . . . . . . . . . 10
2.3 Đọc Ảnh Vệ Tinh . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3.1 Vấn Đề . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3.2 Ý tưởng . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.3.3 Thực Hiện . . . . . . . . . . . . . . . . . . . . . . . . 11
Tài Liệu Tham Khảo 15
1
Danh sách hình vẽ
1.1 Các bước của mô hình chia để trị . . . . . . . . . . . . . . . 4
2.1 một minh họa cho thuật toán Merge Sort . . . . . . . . . . . 9
2.2 Mô hình cây nhị nhân 2 chiều . . . . . . . . . . . . . . . . . 12
2.3 Minh họa các bước tìm kiếm . . . . . . . . . . . . . . . . . . 13
2.4 Minh họa các bước tìm kiếm, màu xanh là các vùng bị cách
ly nhanh chóng . . . . . . . . . . . . . . . . . . . . . . . . . 14
2
Chương 1
Tư Tưởng Chia Để Trị

1.1 Tại Sao Phải Chia
Tư tưởng chính mô hình chia để trị là chia một bài toán (một vấn đề)
thành hai hay nhiều bài toán (vấn đề) nhỏ hơn cùng loại hoặc liên quan
với nhau. Cho đến khi kết quả bài toán (vấn đề) đó có được từ cách tổng
hợp kết quả của những bài toán (vấn đề) cơ sở hoặc đơn giản có thể giải
quyết một cách trực tiếp dễ dàng. Nguyên lý mô hình Chia Để Trị giải xử
lý vấn đề từ trên xuống. Ta cũng có một mô hình khác giải quyết theo cách
ngược lại đó là mô hình Quy Hoạch Động xử lý vấn đề từ dưới lên.
1.1.1 Ưu Điểm
Đối với tin học mô hình chia để trị ngày này được sử dụng ngày càng
mạnh mẻ trong tin học dựa trên sự phát triển của công nghệ và sự ra đời
các bộ xử lý đa luồng, các mô hình tính toán song song. Giúp các vấn đề
nhỏ được xử lý gần như một lúc, giúp giảm thiểu thời gian và chi phí thực
thi đi gấp nhiều lần, đây là một trong những ưu điểm chính của mô hình
chia để trị. Hơn thế nữa, mô hình thuật toán còn giúp tận dụng bộ nhớ đêm
(cache) một cách hiểu quả, đó là kết quả của việc chia nhỏ vấn đề mà bản
thân các vấn để đó (đủ nhỏ đến mức cần thiết) có thể giải quyết được trên
bộ nhớ cache, không cần gửi thông tin đến bộ nhớ truy cập.
1.1.2 Nhược Điểm
Chia để trị có một nhược điểm khá lớn đó là chia để trị không thể lưu
lại kết quả của những vấn đề đã giải quyết cho lần yêu cầu tiếp theo, vì vậy
ta phải xem xét lại vấn đề bài toán có nên sử dụng chia để trị hay không.
3
Hình 1.1: Các bước của mô hình chia để trị
Một bài toán áp dụng được chia để trị tốt nhất là một bài toán có thể chia
nhỏ thành nhiều vấn đề nhỏ khác cùng loại và trong quá trình giải quyết
vấn đề số lần giải quyết lại cùng một vấn để đã giải quyết là cực tiểu.
1.2 Các Bước Thực Hiện
Các bước thiết kế thuật toán:
1. Chia vấn đề thành các vấn đề con.

2. Giải quyết vấn đề con một cách đệ quy, nếu vấn đề con có kích thước
đủ nhỏ thì giải quyết một cách trực tiếp.
3. Tổng hợp các kết quả của vấn đề con là kết quả của vấn đề cần tìm.
Ví dụ: cho mảng A gồm các số thực được sắp xếp tăng dần: A = [a
1
, a
2
, a
3
, . . . , a
n
].
Tìm một phần tử của mảng có giá trị là x
Giải quyết cách đơn giản nhất là vét cạn, duyệt hết các vị trí trong mảng
từ đầu mảng. Với cách làm này thì độ phức tạp thuật toán sẽ là O(n). Trong
thực tế có những mảng dữ liệu lên tới hàng tỷ phần tử , điều đó có nghĩa
là chi phí của thuật toán sẽ rất lớn, ta sẽ phải tìm một thuật toán khác có
độ phức tạp thấp hơn để giảm chi phí một cách đáng kể. Đối với chia để trị
ta sẽ sử dụng thuật toán BinarySearch để minh họa và so sánh.
Đặt F (i) là kết quả của việc xem xét phần tử giá trị x có nằm trong
mảng dữ liệu đang xét hay không và xuất ra vị trí. Với BinarySearch cứ chia
đôi dãy ra, theo đó ta có hệ thức truy hồi:
F (n) = F(n − 1) + F(n − 2) + . . . + F (1)
4
Với F (1) là kết quả của việc xét xem a
i
có bằng giá trị x hay không. Khi đã
có được kết quả của F(1), F (2) ta truy hồi lại kết quả của F (n)
Gọi T (n) là độ phức tạp thuật toán, ta có hệ thức truy hồi: T (n) =
T (

n
2
) + 1 và T(1) = 1 Giả sử n = 2
k
,theo hệ thức truy hồi:
T (n) = T(
n
2
) + 1 = T(
n
2
2
) + 2 = . . . = T(
n
2
k
) + k
Theo cách đặt đó ta có: n = 2
k
,T (1) = 1, T (n) = 1 + k mà k = log
2
(n) ⇒
T (n) = log
2
(n) + 1 ⇒ T(n) = O(log
2
(n))
1.3 Các Vấn Đề Cài Đặt
1.3.1 Chia Ra Nhiều Sẽ Dễ Trị?
Trong đa số các bài toán chia để trị trên lý thuyết người ta thường chia

nhỏ vấn đề đến mức tối đa để dễ dàng giải quyết. Chúng ta hãy cùng xem
xét 1 câu hỏi: chia càng nhỏ có hẳn là đã tốt không?
Nhắc lại: Thuật toán chia để trị thường có dạng phân rã 1 vấn đề có
kích thước n thành a vấn đề kích thước
n
b
rồi tổ hợp kết quả trong O(n
d
) với
a, b, d > 0 ( trong phép nhân thì a = 3, b = 2, d = 1).Thời gian chạy có thể
được tính bằng công thức T(n) = aT(
n
b
) + O(n
d
). Chiều cao của cây tạo ra
là log
b
n xét lại bài toán phép nhân khi chưa rút gọn a(a = 4, b = 2, d = 1)
có thời gian chạy là O(n
2
) bây giờ ta thay b = 4
x = x
4
+ x
3
.2
n/4
+ x
2

.2
n/2
+ x
1
.2
3n/4
y = y
4
+ y
3
.2
n/4
+ y
2
.2
n/2
+ y
1
.2
3n/4
xy = (x
4
+ x
3
.2
n/4
+ x
2
.2
n/2

+ x
1
.2
3n/4
)(y
4
+ y
3
.2
n/4
+ y
2
.2
n/2
+ y
1
.2
3n/4
)
Nhìn vào biểu thức ta thấy a = 16, b = 4, d = 1, log
b
a = 2 > d nên
T (n) = O(n
log
b
a
) = O (n
2
) Vậy độ phức tạp bằng với phương pháp chia đôi
(b = 2). Tuy nhiên biểu thức tổ hợp của ta lại phức tạp và khó cài đặt hơn

khi b = 2. Vậy chia nhỏ chưa hẳn đã tốt hơn.
Định lý 1.3.1 (Định Lý Master). Nếu T(n) = aT ([
n
b
]) + O(n
d
) với a > 0,
b > 1 và d ≥ 0 thì:
T (n) = O(n
d
) nếu d > log
b
a
T (n) = O(n
d
logn) nếu d = log
b
a
T (n) = O(n
log
b
a
) nếu d < log
b
a
5
Vậy theo định lý Master, cách chia tối ưu nhất là chia sao cho d = log
a
b
Ngoài ra, để dễ dàng hơn, người ta còn chia theo định nghĩa đệ quy của

nó. Có thể lấy ví dụ lại bài toán luỹ thừa, bây giờ ta muốn luỹ thừa x
n
, với
n khá lớn. Như ta đã biết, luỹ thừa có thể dễ dàng tách ra từ A
a+b
thành A
a
và A
b
, do đó ta có định nghĩa đệ quu cho nó như sau:
x
n
=





1 nếu n=0
(x
n
2
)
2
nếu n chẵn
x
n−1
x nếu n lẻ
Dễ thấy khi có biểu thức trên, rõ ràng n đã giảm một nữa, khi n khá
lớn, đây là một sự giảm đáng kể

1.3.2 Mối Quan Hệ Với Đệ Quy
Đệ Qui
Để có thể hiểu được mối quan hệ giữa chia để trị với đệ quy thì ta cần
xét những điểm mạnh của đệ quy. Đệ quy mạnh ở chỗ có thể định nghĩa
một tập rất lớn các tác động chỉ bởi số rất ít mệnh đề, rất thích hợp để giải
quyết những bài toán có tính chất đệ qui. Khi dùng đệ quy, bài toán giải
quyết sẽ sáng sủa, dễ hiểu hơn. Từ đó có thể nói bản chất của của đệ quy là
giải quyết bài toán theo kiểu qui nạp, hạ bậc (ThS.Trần Đức Huyên
1
), điều
này rất có ý nghĩa trong việc chúng ta chia bài toán ra để "trị".
Theo như hiện nay, nhiều thuật toán vẫn chưa có cách giải nào khác
nếu không sử dụng đệ quy. Nhưng bên cạnh đó, không ít những bài toán
đệ quy bị khử đệ quy bằng nhiều phương pháp khác nhau. Lý do để khử đệ
quy là tránh cho máy mất quá nhiều tài nguyên hay thực hiện thừa các tác
vụ.
Mối Quan Hệ
Có thể nói rằng mối quan hệ giữa đệ quy và chia để trị là hết sức khắng
khít. Với bản chất của đệ quy, chúng ta có thể dùng nó để thiết kế việc chia
như thế nào trong thuật toán đặt ra hết sức dễ dàng, sáng sủa. Nếu như
khẳng định việc sử dụng đệ quy trong việc chia để trị là yếu tố hiển nhiên
là không sai.
Tuy nhiên, ta cần chú ý rằng đệ quy không phải là chìa khoá vàng. Đệ
quy cũng có một số khiếm khuyết như đã đề cập ở trên, cho nên đệ quy
1
NXB Giáo Dục, phương pháp giải các bài toán trong Tin Học
6
không hẳn là co đường duy nhất đi đến thành công. Chúng ta có thể sử
dụng những phương pháp khử đệ quy khác đã biết như: stack, vòng lặp,
1.3.3 Các Vấn Đề Về Cài Đặt

Sử dụng lưu trữ tùy thuộc vào "Input" mà ta phải chọn một loại hình
lưu trữ các bài toán con thích hợp. Ví dụ với một mảng cực lớn các số khi
chia ra có rất nhiều bài toán con nên ta phải sử dụng một danh sách liên
kết hoặc một stack nào đó để lưu trữ.
Môi trường cài đặt bất cứ ngôn ngữ lập trình nào có hổ trợ giải thuật đệ
quy ta đều có thể cài đặt chia để trị. Nhưng ta phải lưu ý đến việc hổ trợ
vùng nhớ đệm của ngôn ngữ lập trình. Vì đối với những vấn đề lớn ta cần
bộ nhớ rất lớn. Ngày này hầu như toàn bộ các ngôn ngữ lập trình đều hổ
trợ giải thuật đệ quy.
7
Chương 2
Những Bài Toán Sử Dụng Phương
Pháp Chia Để Trị
2.1 Thuật Toán Tìm Kiếm
2.1.1 Quick Sort
Sắp xếp nhanh (Quicksort), còn được gọi là sắp xếp kiểu phân chia
(part sort) là một thuật toán sắp xếp dựa trên phép phân chia danh sách
được sắp thành hai danh sách con. Khác với sắp xếp trộn, chia danh sách
cần sắp xếp a[1 n] thành hai danh sách con có kích thước tương đối bằng
nhau nhờ chỉ số đứng giữa danh sách, sắp xếp nhanh chia nó thành hai
danh sách bằng cách so sánh từng phần tử của danh sách với một phần tử
được chọn được gọi là phần tử chốt. Những phần tử nhỏ hơn hoặc bằng
phần tử chốt được đưa về phía trước và nằm trong danh sách con thứ nhất,
các phần tử lớn hơn chốt được đưa về phía sau và thuộc danh sách đứng
sau. Cứ tiếp tục chia như vậy tới khi các danh sách con đều có độ dài bằng
1.
Phần tử chốt (pivot) là một phần tử được chọn dùng để đối sánh 2 bên
của mảng để hoán vị. Kỹ thuật chọn phần tử chốt ảnh hưởng khá nhiều đến
khả năng rơi vào các vòng lặp vô hạn đối với các trường hợp đặc biệt. Tốt
nhất là chọn phần tử chốt là trung vị của danh sách. Khi đó sau log

2
(n) lần
phân chia ta sẽ đạt tới kích thước danh sách bằng 1. Tuy nhiên điều đó rất
khó. Có các cách chọn phần tử chốt như sau:
1. Chọn phần tử đứng đầu hoặc đứng cuối làm phần tử chốt.
2. Chọn phần tử đứng giữa danh sách làm phần tử chốt.
8
3. Chọn phần tử trung vị trong 3 phần tử đứng đầu, đứng giữa và đứng
cuối làm phần tử chốt.
4. Chọn phần tử ngẫu nhiên làm phần tử chốt. (Cách này có thể dẫn đến
khả năng rơi vào các trường hợp đặc biệt)
Thuật phân chia sau khi phần tử chốt được chọn giải thuật phân chia
nên tiến hành như thế nào? Một giải pháp đơn giản nhất cho vấn đề này là
duyệt từ đầu đến cuối lần lượt so sánh các phần tử của danh sách với phần
tử chốt. Theo cách này, ta phải tiến hành n phép so sánh, ngoài ra còn phải
dành n đơn vị bộ nhớ để lưu giữ các giá trị trung gian.
Một giải pháp khác được đề nghị là duyệt theo hai đường. Một đường từ
đầu danh sách, một đường từ cuối danh sách. Theo cách này, ta tìm phần
tử đầu tiên tính từ trái lớn hơn phần tử chốt và phần tử đầu tiên phía phải
nhỏ hơn hoặc bằng phần tử chốt rồi đổi chỗ cho nhau. Tiếp tục như vậy
cho đến khi hai đường gặp nhau.
Để có thể gọi đệ quy ta xét bài toán phân chia một danh sách con của a:
a[k1, k2] thành hai danh sách. Công thức truy hồi và cách tính độ phức tạp
giống hoàn toàn với phương pháp Merge Sort. Với một mảng n phần tử ta
cần sắp xếp theo Merge Sort. Đặt T(n) là độ phức tạp của thuật toán, ta có
được công thức truy hồi theo độ phức tạp thuật toán: T (n) = 2T(n/2) + Cn
(với Cn là chi phí thực hiện bài toán ở mức n phần tử), T (
n
2
) = 2T (

n
4
) + C
n
2
Như vậy ta có: T (n) = 2T (
n
2
) + Cn = 4T(
n
4
) + 2Cn = = 2
k
T (
n
2
k
) +
Cnk = 2
k
+ Cnk = n + Cnlog
2
(n) với n = 2
k
, T (
n
2
k
) = T (1) = 1. Vậy thuật
toán Quick có độ phức tạp là O(n) = nlog

2
(n)
2.1.2 Merge Sort
Sắp xếp trộn (merge sort) là một thuật toán sắp xếp để sắp xếp các
danh sách (hoặc bất kỳ cấu trúc dữ liệu nào có thể truy cập tuần tự, (v.d:
luồng tập tin) theo một trật tự nào đó. Thuật toán này là một ví dụ tương
đối điển hình của lối thuật toán chia để trị. Nó được xếp vào thể loại sắp
xếp so sánh.
Trộn có hai danh sách đã được sắp xếp a[1 m] và b[1 n.]. Ta có thể trộn
chúng lại thành một danh sách mới c[1, m + n] được sắp xếp theo cách sau:
So sánh hai phần tử đứng đầu của hai danh sách, lấy phần tử nhỏ hơn cho
vào danh sách mới. Tiếp tục như vậy cho tới khi một trong hai danh sách là
rỗng. Khi một trong hai danh sách là rỗng ta lấy phần còn lại của danh sách
kia cho vào cuối danh sách mới. Ví dụ: Cho hai danh sách a = (1, 3, 7, 9),
b = (2, 6), quá trình hòa nhập diễn ra như sau:
9
Hình 2.1: một minh họa cho thuật toán Merge Sort
10
Danh sách a Danh sách b So sánh Danh sách c
1,3,7,9 2,6 1<2 1
3,7,9 2,6 2<3 1.2
3,7,9 6 3<6 1,2,3
7,9 6 6<7 1,2,3,6
7,9 1,2,3,6,7,9
Trộn tại chỗ: giả sử trong danh sách a[1 n] có 2 danh sách con kề nhau
a[k1 k2] và a[k2 + 1 k3] đã được sắp. Ta áp dụng cách trộn tương tự như
trên để trộn hai danh sách con vào một danh sách tạm T [k1 k3] rồi trả lại
các giá trị của danh sách tạm T về danh sách A. Làm như vậy gọi là trộn tại
chỗ.
Trộn từ dưới lên nếu danh sách con chỉ gồm hai phần tử, mối nửa của

nó gồm một phần tử đương nhiên đã được sắp. Do đó việc trộn tại chố hai
nửa danh sách này cho danh sách con 2 phân tử được sắp. Xuất phát từ
đầu danh sách a ta trộn a[1] với a[2], a[3] với a[4], Khi đó mọi danh sách
con gồm hai phần tử của a đã được sắp. Tiếp tục trộn các danh sách con
kế tiếp nhau gồm 2 phần tử thành các danh sách con 4 phần tử Mỗi lần
trộn số các danh sách con cần trộn giảm đi một nửa. Quá trình dừng lại khi
số danh sách con chỉ còn một. Ví dụ: Cho danh sách a = (2, 3, 5, 6, 4, 1, 7)
Công việc Số Danh sách con Kết quả
Trộn các phần tử đứng kề nhau 7 2,3-5,6-1,4-7
Trộn các danh sách con 2 phần tử kề nhau 4 2,3,5,6-1,4,7
Trộn các danh sách con 4 phần tử kề nhau 2 1,2,3,4,5,6,7
Độ Phức Tạp: với một mảng n phần tử ta cần sắp xếp theo Merge Sort
,đặt T (n) là độ phức tạp của thuật toán. Ta có được công thức truy hồi theo
độ phức tạp thuật toán : T(n) = 2T (
n
2
) + Cn , với C là một hằng số (với
Cn là chi phí thực hiện bài toán ở mức n phần tử) T (
n
2
) = 2T (
n
4
) + C
n
2
, như
vậy ta có : T (n) = 2T(
n
2

) + Cn = 4T (
n
4
) + 2Cn = = 2
k
T (
n
2
k
) + Cnk =
2
k
+ Cnk = n + Cnlog
2
(n) với n = 2
k
, T(
n
2
k
) = T (1) = 1. Vậy thuật toán
Merge Sort có độ phức tạp là O(n) = nlog
2
(n)
2.2 Nhân 2 Số Nhị Phân N Bit
Nhân 2 số tự nhiên n-bit X và Y thông thường độ phức tạp ở mức O(n
2
).
Bây giờ chúng ta sẽ xét lại bài toán này với kỹ thuật chia để trị. Ta phân
11

tách mỗi số X, Y thành 2 phần, mỗi phần
n
2
. Để đơn giản, ta luôn xét n là
luỹ thừa của 2. X, Y sẽ được phân tách như sau:
X = A|B(X = A2
n
2
+ B)
Y = C|D
Khi đó XY sẽ có dạng:
XY = AC2
n
+ (AD + BC)2
n
2
+ BD
Từ công thức kiếm được, ta thấy việc tính XY chỉ còn là tính 4 pháp nhân
với các số
n
2
là AC, AD, BC và BD, sau đó thực hiện phép cộng 2n bit, cuối
cùng là 2 phép chuyển chữ số (2 phép nhân với luỹ thừ của 2). Các phép
cộng và phép chuyển chữ số đều được thực hiện với thời gian O(n), do đó
ta thu được công thức tính động phức tạp của pháp toán trên T(n) là:
T (1) = 1
T (n) = 4T (
n
2
) + Cn

Và do đó T (n) = O(n
2
) nên không hiệu quả lắm với cách thông thường cho
nên chúng ta tiếp tục biến đổi XY như sau:
XY = AC2
n
+ ((A − B)(D − C) + AC + BD)2
n
2
+ BD
Đến đây ta thấy hiệu quả của phép biến đổi vừa được tạo ra, cụ thể để tính
XY ta tốn 3 phép nhân
n
2
bit: AC, BD và (A − B)(D − C), 6 phép tính
cộng trừ số
n
2
, 2 phép chuyển chữ số (nhân với luỹ thừa của 2). Do vậy với
cách tính trên ta có độ phức tạp của thuật toán này
T (1) = 1
T (n) = 3T (
n
2
) + Cn
Ta dễ thấy phương pháp chia đôi này sẽ đệ quy log
2
n bước và ở bước cuối
thì chỉ còn 1 bit. Cây đệ quy có chiều cao là log
2

n và ở mỗi bước có 3 nhánh.
vậy ở độ sâu k thì số bài toán con là 3
k
, mỗi bài có kích thước là (
n
2
)
k
bước.
Với mỗi bài toán con ta cần 1 thời gian tuyến tính để phân rã chúng và gom
nhóm nên đến bước k, thời gian chạy sẽ là
T (n) = 3
k
.O(
n
2
k
) = (
3
2
)
k
.O(n)
Do đó, độ phức tạp của thuật toán chỉ còn O(n
log
3
2
) = O(n
1.59
)

12
2.3 Đọc Ảnh Vệ Tinh
Để hiện thực hoá đều này, ngoài thuật toán ra, chúng ta còn phải quan
tâm đến vấn đề Cấu Trúc Dữ Liệu, cho nên trong phương diện báo cáo
môn học Phân Tích Thuật Toán, chúng tôi chỉ đề cập đến ý tưởng chia -
trị như thế nào của thuật toán, không đề cập sâu vào Cấu Trúc Dữ Liệu.
2.3.1 Vấn Đề
Việc đọc ảnh kích thước là một nhu cầu thiết yếu trong nhiều ngành
khoa học và đời sống hiện nay. Tuy nhiên ta thường gặp nhiều khó khăn
trong việc đọc trực tiếp những bức ảnh kích thước lớn, ảnh vệ tinh là một
ví dụ. Ta biết rằng ảnh chụp của một vệ tinh về một phần nào đó của một
hành tinh hoặc vũ trụ đều là những ảnh có kích thước rất lớn. Những ảnh
này được truyền về mặt đất sau khi chụp và yêu cầu đầu tiên đặt ra cho
những người tiếp nhận là làm sao đọc được nó. Tất nhiên việc đọc trực tiếp
là không thể, vì bộ nhớ của máy có giới hạn rất nhỏ so với kích thước ảnh.
2.3.2 Ý tưởng
Ảnh lớn ban đầu sẽ được cắt thành các ảnh hình vuông nhỏ có kích
thước bằng nhau. Mỗi ảnh nhỏ đó gọi là một ảnh đơn vị. Tiếp đó, ta đánh
dấu tọa độ của các ô vuông nhỏ đó trong bức ảnh lớn. Khi đọc ảnh, ta thiết
kế sao có ảnh được gọi là “vùng nhìn thấy”, sau đó ta chỉ cần đọc những
bức ảnh kề nó.
Sau khi chia nhỏ ảnh và gán mỗi bức ảnh đơn vị thành những điểm
trong mặt phẳng Oxy thì bài toán đến đây quy về bài toán tìm kiếm điểm
kề trong không gian.
Cần lưu ý điều sau: do bức ảnh vệ tinh thường tương đối lớn, nên khi
chia ra số lượng cũng tương đối lớn, nếu dùng những thuật toán thông
thường để tìm những điểm kề với điểm thấy được (toạ độ được đánh dấu
của “vùng nhìn thấy”), khó lòng thực hiện với chi phí thấp.
2.3.3 Thực Hiện
Để thực hiện, trước hết cần một CTDL để lưu trữ, ở đây chúng tôi dùng

kd − tree với số chiều 2 (cây tìm kiếm nhị phân 2D). Điểm thấy được chính
là node gốc.
13
Hình 2.2: Mô hình cây nhị nhân 2 chiều
Bước 1: Bắt đầu từ node gốc, thuật toán sẽ xét hai nhánh con của node
gốc, sau đó so sánh khoảng cách 2 node con đến điểm cần tìm láng giềng,
thuật toán sẽ duyệt xuống node nào có khoảng cách tới điểm cần tìm gần
hơn. Trong quá trình tìm xét tới một node nào đó, thuật toán sẽ so sánh
độ dài từ điểm tỉm kiếm đến node đó. Nếu độ dài này là nhỏ nhất tới thời
điểm hiện tại thì sẽ cập nhất lưu node đó thành điểm gần nhất tạm thời.
Bước 2: Thực hiện bước 1 cho tới khi gặp một node lá thì dừng lại. Khi
đó ta sẽ có một điểm gần nhất ứng với toàn bộ phần đã duyệt.
Bước 3: Thự hiện dò ngược lại cây(bung đệ quy với các node còn lại được
so sánh khoảng cách lớn hơn) với các bước sau:
1. Nếu node đang xét có khoảng cách tới điểm tìm kiểm là nhỏ nhất
hiện tại thì cập nhật nó là điểm gần nhất.
2. Thuật toán sẽ tìm kiếm trong các phần còn lại của không gian bị chia
cắt (các nhánh còn lại của cây) có node nào của cây có khoảng cách
tới điểm đang xét là gần nhất hiện thời hay không. Thực hiện bằng
cách xét quả cầu có tâm là điểm tìm kiếm, bán kính là khoảng cách
gần nhất hiện thời xem nó có giao với các không gian bị chia cắt nào
không rồi tiến hành so sánh với các điểm trong miền không gian đó:
• Đối với mỗi mặt phẳng giao với quả cầu, ta thực hiện duyệt phần
nhánh con tương ứng với mặt phẳng đó.
• Đối với các nhánh không cắt quả cầu, thuật toán sẽ bỏ qua nhánh
đó.
14
Hình 2.3: Minh họa các bước tìm kiếm
Bước 4: khi quá trình duyệt quay trở về node gốc, thuật toán kết thúc.
Mở rộng: tìm N điểm gần nhất. Trong trường hợp muốn tìm N node gần

điểm tìm kiếm nhất, chúng ta có nhiều cách dựa trên thuật toán tìm láng
giềng gần nhất đã được trình bày phía trên, ở đây chúng tôi đề xuất cải tiến
thuật toán như sau: Trong quá trình tìm kiếm, khi đã tìm được láng giềng
gần nhất ta tiến hành bung độ lớn của bán kính vòng tròn để tìm và đánh
dấu những điểm được cho là gần nhất tiếp theo điểm đã tìm được.
15
Hình 2.4: Minh họa các bước tìm kiếm, màu xanh là các vùng bị cách ly
nhanh chóng
16
Tài liệu tham khảo
[1] ThS.Trần Đức Huyên: phương pháp giải các bài toán trong Tin Học,
NXB Giáo Dục
[2] Ian Parberry: Lecture Notes on Algorithm Analysis and Computational
Complexity Department of Computer Science, University of North
Texas
[3] Internet

×