Tìm kiếm tuyến tính
Cập nhật lần cuối
Tìm kiếm tuyến tính (linear search), còn gọi là tìm kiếm tuần tự, là thuật toán tìm kiếm đơn giản nhất: bắt đầu từ phần tử đầu tiên và so sánh từng phần tử với giá trị cần tìm cho đến khi khớp hoặc hết phần tử. Thuật toán không đặt giả định nào về dữ liệu, nên mảng có thể chưa sắp xếp và các phần tử có thể là bất cứ thứ gì so sánh bằng được.
Hình động ở trên tô sáng từng lần so sánh khi quá trình quét đi từ trái sang phải và dừng ngay khi gặp giá trị cần tìm. Sự đơn giản phải trả giá bằng tốc độ: trong trường hợp xấu nhất mọi phần tử đều bị kiểm tra, nên thuật toán chạy trong O(n). Khi dữ liệu đã sắp xếp, tìm kiếm nhị phân cho cùng kết quả trong O(log n), và nếu cần sắp xếp dữ liệu trước, hãy xem merge sort.
Độ phức tạp thời gian và không gian
| Trường hợp | Độ phức tạp | Ghi chú |
|---|---|---|
| Tốt nhất | O(1) | Phần tử đầu tiên chính là giá trị cần tìm. |
| Trung bình | O(n) | Trung bình phải kiểm tra một nửa số phần tử mới tìm thấy. |
| Xấu nhất | O(n) | Giá trị cần tìm nằm cuối cùng, hoặc hoàn toàn không có. |
| Không gian | O(1) | Chỉ cần lưu chỉ số hiện tại. |
Từng bước
| Bước | Điều gì xảy ra |
|---|---|
| 1 | Bắt đầu ở chỉ số 0, phần tử đầu tiên của mảng. |
| 2 | So sánh phần tử hiện tại với giá trị cần tìm. |
| 3 | Nếu bằng nhau, trả về chỉ số hiện tại (đã tìm thấy). |
| 4 | Nếu không, dịch sang phải một vị trí và lặp lại. |
| 5 | Nếu đến cuối mảng mà không khớp, giá trị cần tìm không có trong mảng (trả về -1). |
Ví dụ minh họa
Tìm 5 trong [7, 3, 9, 1, 5, 8, 2]:
| Lần so sánh | Chỉ số | Phần tử | Kết quả |
|---|---|---|---|
| 1 | 0 | 7 | 7 ≠ 5: tiếp tục quét. |
| 2 | 1 | 3 | 3 ≠ 5: tiếp tục quét. |
| 3 | 2 | 9 | 9 ≠ 5: tiếp tục quét. |
| 4 | 3 | 1 | 1 ≠ 5: tiếp tục quét. |
| 5 | 4 | 5 | 5 = 5: tìm thấy ở chỉ số 4. |
Khi nào nên dùng tìm kiếm tuyến tính
| Nên dùng khi | Tránh dùng khi |
|---|---|
| Dữ liệu chưa sắp xếp hoặc thay đổi liên tục | Dữ liệu đã sắp xếp, khi đó tìm kiếm nhị phân nhanh hơn theo cấp số mũ |
| Tập dữ liệu nhỏ, nên sự đơn giản là lợi thế | Tập dữ liệu lớn và phải tìm kiếm nhiều lần |
| Bạn chỉ truy cập được tuần tự (luồng dữ liệu, danh sách liên kết) | Bạn có thể dùng chỉ mục hoặc bảng băm để tra cứu trong O(1) |
Code Linear Search
Một cách cài đặt Linear Search gọn gàng, chạy được ngay bằng Python, JavaScript, Java, C++, C, Pseudocode. Chọn một ngôn ngữ, sao chép code hoặc mở sẵn trong Coddy Playground.
Code Linear Search bằng Python
1def linear_search(a, target):2 # Scan left to right until the target appears3 for i in range(len(a)):4 if a[i] == target:5 return i6 return -17
8
9nums = [7, 3, 9, 1, 5, 8, 2]10print("Index of 5:", linear_search(nums, 5))11print("Index of 4:", linear_search(nums, 4))Code Linear Search bằng JavaScript
1function linearSearch(a, target) {2 // Scan left to right until the target appears3 for (let i = 0; i < a.length; i++) {4 if (a[i] === target) return i;5 }6 return -1;7}8
9const nums = [7, 3, 9, 1, 5, 8, 2];10console.log("Index of 5:", linearSearch(nums, 5));11console.log("Index of 4:", linearSearch(nums, 4));Code Linear Search bằng Java
1public class Main {2 static int linearSearch(int[] a, int target) {3 // Scan left to right until the target appears4 for (int i = 0; i < a.length; i++) {5 if (a[i] == target) return i;6 }7 return -1;8 }9
10 public static void main(String[] args) {11 int[] nums = {7, 3, 9, 1, 5, 8, 2};12 System.out.println("Index of 5: " + linearSearch(nums, 5));13 System.out.println("Index of 4: " + linearSearch(nums, 4));14 }15}Code Linear Search bằng C++
1#include <iostream>2#include <vector>3
4int linearSearch(const std::vector<int>& a, int target) {5 // Scan left to right until the target appears6 for (std::size_t i = 0; i < a.size(); i++) {7 if (a[i] == target) return static_cast<int>(i);8 }9 return -1;10}11
12int main() {13 std::vector<int> nums = {7, 3, 9, 1, 5, 8, 2};14 std::cout << "Index of 5: " << linearSearch(nums, 5) << "\n";15 std::cout << "Index of 4: " << linearSearch(nums, 4) << "\n";16 return 0;17}Code Linear Search bằng C
1#include <stdio.h>2
3int linear_search(const int a[], int n, int target) {4 /* Scan left to right until the target appears */5 for (int i = 0; i < n; i++) {6 if (a[i] == target) return i;7 }8 return -1;9}10
11int main(void) {12 int nums[] = {7, 3, 9, 1, 5, 8, 2};13 int n = sizeof(nums) / sizeof(nums[0]);14 printf("Index of 5: %d\n", linear_search(nums, n, 5));15 printf("Index of 4: %d\n", linear_search(nums, n, 4));16 return 0;17}Code Linear Search bằng Pseudocode
1DECLARE nums : ARRAY[1:7] OF INTEGER2DECLARE n : INTEGER3n ← 74nums[1] ← 75nums[2] ← 36nums[3] ← 97nums[4] ← 18nums[5] ← 59nums[6] ← 810nums[7] ← 211
12FUNCTION linearSearch(target : INTEGER) RETURNS INTEGER13 DECLARE i : INTEGER14 // Scan left to right until the target appears15 FOR i ← 1 TO n16 IF nums[i] = target THEN17 RETURN i18 ENDIF19 NEXT i20 RETURN -121ENDFUNCTION22
23OUTPUT "Index of 5 is ", linearSearch(5)24OUTPUT "Index of 4 is ", linearSearch(4)Câu hỏi thường gặp về tìm kiếm tuyến tính
Độ phức tạp thời gian của tìm kiếm tuyến tính là bao nhiêu?
O(n) trong trường hợp trung bình và xấu nhất (quá trình quét có thể phải đi qua mọi phần tử) và O(1) trong trường hợp tốt nhất, khi phần tử đầu tiên là giá trị cần tìm. Thuật toán dùng O(1) bộ nhớ phụ.Tìm kiếm tuyến tính có cần dữ liệu đã sắp xếp không?
Không, đó là ưu điểm chính của nó. Tìm kiếm tuyến tính chạy được trên dữ liệu hoàn toàn chưa sắp xếp vì nó so sánh bằng với từng phần tử; thứ tự không quan trọng. Ngược lại, tìm kiếm nhị phân chỉ chạy được trên mảng đã sắp xếp.
Khi nào tìm kiếm tuyến tính tốt hơn tìm kiếm nhị phân?
O(n log n)), khi tập dữ liệu rất nhỏ, hoặc khi bạn chỉ truy cập được tuần tự, như một luồng dữ liệu hay danh sách liên kết. Với việc tra cứu nhiều lần trên mảng đã sắp xếp, tìm kiếm nhị phân thắng.Tìm kiếm tuyến tính có giống tìm kiếm tuần tự không?
Có, hai tên gọi mô tả cùng một thuật toán: quét lần lượt các phần tử cho đến khi tìm thấy giá trị cần tìm hoặc hết tập dữ liệu.
Trung bình tìm kiếm tuyến tính thực hiện bao nhiêu lần so sánh?
n/2 lần so sánh; nếu không có, cần đúng n lần. Mức tăng tuyến tính đó chính là lý do thuật toán được gọi là tìm kiếm tuyến tính.