Tiểu luận về Thuật toán và ứng dụng của Tìmm kiếm nhị phân (Binary Search) trong lập trình. Tài liệu có chứa thuật toán Duyệt bằng cách chia đôi tập hợp. Tiểu luận do nhóm Học sinh chuyên Tin Khóa K26 trường THPT chuyên Thái Nguyên thực hiện
Trang 1BÀI TIỂU LUẬN MÔN TIN HỌC
Trang 2MỤC LỤC
MỤC LỤC 2
LỜI NÓI ĐẦU 3
NỘI DUNG 4
CHƯƠNG I: ĐẶT VẤN ĐỀ 4
CHƯƠNG II: CƠ SỞ LÍ THUYẾT VÀ BÀI TẬP MINH HỌA 5
A - CƠ SỞ LÍ THUYẾT 5
B - BÀI TẬP MINH HỌA 9
CHƯƠNG III: ỨNG DỤNG VÀ PHÁT TRIỂN 12
KẾT LUẬN CHUNG 26
DANH MỤC TÀI LIỆU THAM KHẢO 27
Trang 3LỜI NÓI ĐẦU
Thế kỷ 21 được coi là kỷ nguyên của Công nghệ thông tin Các nhà khoa học khẳng định rằng chưa có một ngành khoa học - công nghệ nào lại có nhiều ứng dụng như công nghệ thông tin Nổi bật trong đó là ngành khoa học máy tính - ngành nghiên cứu các cơ sở lý thuyết về thông tin và tính toán cùng sự thực hiện và ứng dụng của chúng trong các hệ thống máy tính Khi tìm hiểu ngành này, chúng ta dễ dàng bắt gắp các bài toán yêu cầu tìm kiếm (tìm một phần tử trong một danh sách), ví dụ như trong một danh bạ điện thoại có thể tìm kiếm số điện thoại của một người theo tên người đó
Để giải những bài toán như vậy, chúng ta có rất nhiều cách khác nhau Hiểu đơn giản, mỗi cách đó là một phương pháp tìm kiếm Ở đây chúng ta đề cập đến các phương pháp tìm kiếm trong ngôn ngữ lập trình Pascal cũng chính là những thuật toán tìm
kiếm Có nhiều thuật toán tìm kiếm, đơn giản nhất là thuật toán Tìm kiếm tuyến tính
Thuật toán này kiểm tra từng phần tử trong danh sách theo thứ tự của danh sách đó Có thể sử dụng thẳng cho một danh sách bất kỳ mà không cần tiền xử lý Đối với các danh sách lớn, đòi hỏi các thuật toán tốt hơn với độ phức tạp nhỏ hơn Trong đó tiêu biểu là
Thuật toán Tìm kiếm nhị phân (hay còn gọi là chặt nhị phân) Qua hiểu biết của
chúng em đây là một thuật toán cao cấp hơn hẳn tìm kiếm tuyến tính nhưng nó đòi hỏi danh sách phải được sắp xếp từ trước, lại có ứng dụng khá nhiều Vì vậy, nhóm em muốn cùng tìm hiểu sâu hơn về thuật toán này và làm rõ những vấn đề liên quan đến
nó qua chính kiến thức của mình, qua sách vở và các tài liệu liên quan Những kiến thức này sẽ được trình bày bằng bài tiểu luận gồm 3 chương với các nội dung tìm hiểu
là vấn đề thực trạng, cơ sở lí thuyết, bài tập minh họa, ứng dụng và phát triển Bài tiểu luận này sẽ không tránh khỏi những sai sót, mong thầy và các bạn sẽ nhiệt tình đóng góp ý kiến để giúp chúng em hiểu biết thêm trong lĩnh vực này
Em xin trân thành cảm ơn!
Trang 4NỘI DUNG
CHƯƠNG I: ĐẶT VẤN ĐỀ
Trong ngành khoa học máy tính, một giải thuật tìm kiếm là một thuật toán lấy đầu vào là một bài toán và trả về kết quả là một lời giải cho bài toán đó, thường là sau khi cân nhắc giữa một loạt các lời giải có thể Hầu hết các thuật toán được nghiên cứu bởi các nhà khoa học máy tính để giải quyết các bài toán đều là các thuật toán tìm kiếm Tập hợp tất cả các lời giải có thể đối với một bài toán được gọi là không gian tìm kiếm Như chúng ta đã biết, hiện nay có rất nhiều các bài toán yêu cầu tìm kiếm cũng như các thuật toán tìm kiếm Tuy nhiên, những thuật toán đơn giản, dễ cài đặt chỉ đáp ứng được những yêu cầu của bài toán với dữ liệu nhỏ và có thời gian thực thi cao (như tìm kiếm tuyến tính) Còn những thuật toán tốt hơn hẳn thì lại có những mặt hạn chế là rất khó cài đặt đặc biệt là gây nhiều khó khăn cho những người mới nhập môn (như thuật toán Tìm kiếm nội suy hay Giải thuật Grover) Chính vì vậy, vấn đề đặt ra
là chúng ta phải có một thuật toán có những đặc tính hơn hẳn nhiều thuật toán khác mà
đặc biệt phải không quá khó hiểu hay khó sử dụng Thuật toán Tìm kiếm nhị phân
(Binary search) hay còn gọi đơn giản là chặt nhị phân rất thích hợp cho yêu cầu nói
trên Tuy nhiên, thuật toán này còn có một vài nhược điểm nhỏ và sử dụng thuật toán
này đôi khi là không có lợi, vậy chúng ta cùng đi tìm hiểu kĩ hơn về “ Thuật toán tìm
kiếm nhị phân”.
Trang 5CHƯƠNG II: CƠ SỞ LÍ THUYẾT VÀ BÀI TẬP MINH HỌA
A - CƠ SỞ LÍ THUYẾT
1 Định nghĩa và khái niệm tìm kiếm
Tìm kiếm là một đòi hỏi rất thường xuyên trong các ứng dụng tin học Bài toán tìm kiếm có thể phát biểu như sau:
Cho một dãy gồm n bản ghi r[1 n] Mỗi bản ghi r[i] (1 ≤ i ≤ n) tương ứng với một khoá k[i] Hãy tìm bản ghi có giá trị khoá bằng X cho trước X được gọi là khoá tìm kiếm hay đối trị tìm kiếm (argument)
Công việc tìm kiếm sẽ hoàn thành nếu như có một trong hai tình huống sau xảy ra:
• Tìm được bản ghi có khoá tương ứng bằng X, lúc
đó phép tìm kiếm thành công
• Không tìm được bản ghi nào có khoá tìm kiếm bằng
X cả, phép tìm kiếm thất bại
2 Sử dụng thuật toán tìm kiếm nhị phân để giải quyết các bài toán tìm kiếm
Phép có thể áp dụng trên dãy khoá đã có thứ tự: k[1] ≤ k[2] ≤ … ≤ k[n].Giả sử
ta cần tìm trong đoạn k[left right] với khoá tìm kiếm là X, trước hết ta xét khoá nằm giữa dãy k[mid] với mid = (left + right) div 2;
• Nếu k[mid] < X thì có nghĩa là đoạn từ k[left] tới k[right] chỉ chứa toàn khoá <
X, ta tiến hành tìm kiếm tiếp với đoạn từ k[mid+1] tới k[right]
• Nếu k[mid] > X thì có nghĩa là đoạn từ k[mid] tới k[right] chỉ chứa toàn khoá >
X, ta tiến hành tìm kiếm tiếp với đoạn từ k[left] tới k[mid-1]
• Nếu k[mid] = X thì việc tìm kiếm thành công (kết thúc quá trình tìm kiếm)
Quá trình tìm kiếm sẽ thất bại nếu đến một bước nào đó, đoạn tìm kiếm là rỗng (left>right)
Trang 6 Sơ đồ các bước thực hiện thuật toán tìm kiếm nhị phân (Binary search):
Thông báo dãy A không có
số gạng có giá trị bằng k;
KT
Trang 7{Tìm kiếm nhị phân trên dãy khoá k[1] ≤ k[2] ≤ … ≤ k[n]; hàm này thử tìm xem trong dãy có khoá nào = X không, nếu thấy nó trả về chỉ số của khoá ấy, nếu không thấy nó trả về 0}
Function BinarySearch(X: TKey): Integer;
Var left, right, mid: Integer;
Trang 82.1 Phân tích đánh giá
Người ta đã chứng minh được độ phức tạp tính toán của thuật toán trong trường hợp tốt nhất là O(1), trong trường hợp xấu nhất là O(lgn) và trong trường hợp trung bình là O(lgn) Tuy nhiên, ta không nên quên rằng trước khi sử dụng, dãy khoá phải được sắp xếp rồi, tức là thời gian chi phí cho việc sắp xếp cũng phải tính đến Nếu dãy khoá luôn luôn biến động bởi phép bổ sung hay loại bớt đi thì lúc đó chi phí cho sắp xếp lại nổi lên rất rõ làm bộc lộ nhược điểm của phương pháp này
Đánh giá giải thuật, ta có bảng so sánh sau:
Trang 9B - BÀI TẬP MINH HỌA
Bài toán 1 : Cho 1 dãy gồm n phần tử: A1, A2, An-1, An Các phần tử được sắp xếp theo thứ tự tăng dần Cần kiểm tra xem 1 khoá x=key cho trước có tồn tại trong dãy không
Dữ liệu:
• Dòng 1: Ghi 2 số nguyên n, m
• N dòng tiếp theo: Mỗi dòng ghi 1 số nguyên Ai
• M dòng tiếp theo: Mỗi dòng ghi 1 khoá keyKết quả: Gồm m dòng
• Nếu tìm thấy ghi vị trí tương ứng của khóa key trong dãy A
• Nếu không tìm thấy ghi -1Giới hạn:
Trang 10const fi='KEY.inp'; fo='KEY.out';
type mang=record gt,cs:longint; end;
var a:array[1 1000000] of mang;
begin
Trang 12CHƯƠNG III: ỨNG DỤNG VÀ PHÁT TRIỂN
Các bài toán ứng dụng thuật toán tìm kiếm nhị phân:
Bài toán 2: Biết rằng căn bậc N của một số S là một số nguyên <106 Tìm căn bậc N của S
81
3
Ý tưởng:
Cmin = 0, Cmax = 106 Output sẽ nằm trong đoạn [Cmin , Cmax]
Đặt Ctg = (Cmin + Cmax) div 2
Tính A = CtgN Để tính A ta dùng thuật toán nhân số lớn
o Nếu A>S thì tìm kiếm trong đoạn [Ctg+1, Cmax]
o Nếu A<S thì tìm kiếm trong đoạn [Cmin, Ctg-1]
o Nếu A=S thì căn bậc N của S chính là CtgTiếp tục tìm kiếm cho tới khi Cmin> Cmax
Trang 13var s : string; n : integer;
cmin, cmax, ctg: longint;
y:= chr(tich mod 10+48)+y;
nho:= tich div 10;
end;
while nho>0 do
begin
y:= chr(nho mod 10+48) + y;
nho:= nho div 10;
end;
Trang 14nhan:= y;
end;
Function kiemtra : integer;
var kq : string; k : integer;
Trang 15Bài tập 3: Có n người, n việc (1 < n ≤ 200) Người thứ i thực hiện công viêc j mất
C[i,j] đơn vị thời gian Giả sử tất cả bắt đầu vào thời điểm 0, hãy tìm cách bố trí mỗi công việc cho mỗi người sao cho thời điểm hoàn thành công việc là sớm nhất có thể
• Dự liệu vào trong file CONGVIEC.inp có dạng :
o Dòng đầu: N
o Tiếp theo là ma trận C[i,j] (thuộc kiểu Integer)
• Output ra file CONGVIEC.out :
o Ghi thời điểm sớm nhất hoàn thành
EXAMPLE:
CONGVIEC.inp CONGVIEC.out4
Code:
Trang 17Function slove :boolean;
var i,j,d: integer;
begin
Trang 19Bài tập 4: DÃY TĂNG DÀI NHẤT
Cho một dãy gồm N số nguyên (1 ≤N ≤30000) Hãy tìm dãy con tăng dài nhất trong dãy đó In ra số lượng phần tử của dãy con Các số trong phạm vi longint
Input : LIS.INP
• Dòng đầu tiên gồm số nguyên N
• Dòng thứ hai gồm N số mô tả dãy
Dùng chặt nhị phân, với h[i] là vị trí của số hạng nhỏ nhất của các dãy con tăng
có độ dài là i Gọi h[i] là vị trí của số hạng có a[h[i]] là nhỏ nhất trong số các dãy con tăng có độ dài là i Ban đầu h[1] = 1, res là độ dài cần tìm, ban đầu res = 1, ta duyệt
từ 2 -> n, đến vị trí i thì đảm bảo nó là một phần tử mới đối với các dãy con trước đó
đã kiểm và cập nhật, đồng thời ta sẽ cập nhật lại các trạng thái mới cho vị trí Đồng thời h[1] < h[2] < h[3] <… < h[n]
Trang 20nhị phân trong đoạn 1->res cho mid, vị trí res là độ dài tớn nhất hiện tại
{ l = 1 ; r = res ; mid = (l+r+1)/2 … } xem code
Nếu đã tìm xong rồi và (a[i] > a[h[mid]] (thỏa điều kiện ban đầu của ta) đồng thời (a[i]
Trang 21endelse
Trang 22 Kĩ thuật duyệt phân tập:
Một kĩ thuật cũng khá hay khi áp dụng binary search, đó là kĩ thuật phân tập.Trong việc lập trình cho máy tính, phương pháp duyệt toàn bộ các cấu hình để tìm phương án tối ưu hay đếm số lượng các cấu hình thỏa mãn một điều kiện nào đó, là một trong những phương pháp quan trọng
Duyệt toàn bộ là phương pháp liệt kê tất cả các phần tử của một tập hợp D hữu hạn nào đó, từ đó chỉ ra một phần tử thoả mãn tiêu chí tối ưu hoặc là đếm số lượng các phần tử thoả mãn yêu cầu nào đó Cách tư duy này xuất phát từ tập hợp D là hữu hạn
Có thể nói đây là cách tư duy đơn giản dễ viết chương trình, là phýõng án lập trình đầu tiên mà mọi học sinh khi bắt đầu học lập trình đều làm quen Các phương pháp duyệt toàn bộ thường gặp: duyệt toàn bộ bằng cách sử dụng các vòng lặp lồng nhau, duyệt quay lui
Tuy nhiên có thể thấy rằng phương pháp này còn hạn chế khi số lượng các phần
tử của tập D lớn Nó thể hiện ở chỗ thời gian tính toán để cho ra output thường không chấp nhận được Do đó trong phương pháp duyệt toàn bộ cần phải bổ sung các phương pháp cho phép bỏ qua hoặc gộp một số phần tử Điều này cải thiện đáng kể thời gian thực hiện chương trình Một số phương pháp duyệt cải tiến được đưa ra: duyệt ưu tiên,duyệt nhánh cận, duyệt bằng cách chia đôi tập hợp
Trong việc chia đôi tập hợp, hay phân tập chính là việc thay vì ta duyệt qua một tập hợp, ta chia thành hai hay nhiều tập hợp khác nhau và duyệt từng tập hợp sẽ giúp làm giảm độ phức tạp của thuật toán xuống đáng kể Sau đây là một ví dụ để thấy rõ cách
áp dụng thuật toán tìm kiếm nhị phân vào kĩ thuật phân tập:
Bài tập 5: VECTOR
Trong mặt phẳng tọa độ có N véc tơ.Mỗi một véc tơ được cho bởi hai chỉ số x và y Tổng của hai véc tơ (xi, yi) và (xj, yj) được định nghĩa là một véc tơ (xi + xj, yi + yj)
Trang 23Bài toán đặt ra là cần chọn một số véc tơ trong N véc tơ đã cho sao cho tổng của các vec tơ đó là véc tơ (U, V).7u8
Yêu cầu: Đếm số cách chọn thoả mãn yêu cầu bài toán đặt ra ở trên
0 0-1 2
Trang 24công thức : Res := Res + f[u-a, v-b];
_ Biến res chính là output bài toán
try2(i+1,u,v);
end;
procedure Readf;
var i,j:longint;
Trang 25END.
Trang 26KẾT LUẬN CHUNG
Hiện nay, có nhiều thuật toán sắp xếp khá hiệu quả và Tìm kiếm nhị phân
(Binary search) là thuật toán đang được ứng dụng khá rộng rãi Tuy nhiên muốn áp
dụng thuật toán tìm kiếm nhị phân cần phải xét đến thời gian sắp xếp dãy số để thỏa điều kiện dãy số đã có thứ tự Thời gian này không nhỏ, và khi dãy có biến động cần phải tiến hành sắp xếp lại Tất cả các nhu cầu đó tạo ra khuyết điểm chính cho giải
thuật Tìm kiếm nhị phân Vì vậy không phải lúc nào dùng thuật toán này cũng tốt,
chúng ta cần cân nhắc nhu cầu thực tế để chọn các thuật toán tìm kiếm sao cho phù hợp nhất
Trang 27
DANH MỤC TÀI LIỆU THAM KHẢO
Sách:
• Tài liệu giáo khoa chuyên tin (Lê Minh Hoàng)
• Một số vấn đề chọn lọc trong môn tin học
• Cấu trúc dữ liệu và giải thuật (Lê Minh Hoàng)
Internet:
o http://pyskys.blogspot.com/2014/09/thuat-toan-tim-kiem-nhi-phan-binary.html
o http://123doc.org/document/20163-thuat-toan-tim-kiem-nhi-phan.htm?page=4
o hthuật hop.htm