Các Thuật Toán Tìm Kiếm Trong C++

Trong hầu hết các hệ quản lý dữ liệu, việc tìm kiếm là một hoạt động quan trọng để khai thác các thông tin khác nhau. Khi xây dựng một hệ quản lý thông tin trên máy tính, việc nắm vững các thuật toán tìm kiếm và sắp xếp dữ liệu là rất quan trọng. Hãy cùng tìm hiểu về các thuật toán tìm kiếm phổ biến trong ngôn ngữ lập trình C++.

1. Thuật Toán Tìm Kiếm Là Gì

Tìm kiếm là quá trình tìm một phần tử trong một tập hợp dựa vào một miêu tả nào đó. Đối với ví dụ tìm đồng 10k trong một đống tiền từ 10k đến 100k, đó gọi là tìm kiếm.

Trong trường hợp tập hợp đã được sắp xếp, việc tìm kiếm sẽ nhanh hơn. Ví dụ, nếu đống tiền từ 10k đến 100k đã được sắp xếp theo thứ tự tăng dần hoặc giảm dần, việc tìm tờ 10k sẽ dễ dàng hơn. Tuy nhiên, nếu đống tiền là một tập hợp không có thứ tự, việc tìm kiếm sẽ mất nhiều thời gian hơn.

Thuật toán tìm kiếm được sử dụng để tìm kiếm một phần tử trong danh sách cho trước theo một tiêu chí nhất định. Hai thuật toán tìm kiếm phổ biến là tìm kiếm tuyến tính và tìm kiếm nhị phân.

  • Thuật Toán Tìm Kiếm Tuyến Tính: Thuật toán này được sử dụng để tìm kiếm trong một tập hợp chưa được sắp xếp, giống với đống tiền chưa được sắp xếp ở ví dụ trên. Thuật toán tìm kiếm tuyến tính là một phương pháp tìm kiếm một phần tử cho trước trong một danh sách bằng cách duyệt lần lượt từng phần tử của danh sách đó cho đến khi tìm thấy giá trị mong muốn hoặc đã duyệt qua toàn bộ danh sách.

Ví dụ: Tìm kiếm phần tử x trong mảng []

Input: A[] = {10, 20, 80, 30, 60, 50, 110, 100, 130, 170} x = 110;
Output: Element x is present at position 6

Input: A[] = {10, 20, 80, 30, 60, 50, 110, 100, 130, 170} x = 175;
Output: Element x is not present in A[].

    Mã giả:

    Phiên bản lặp không tự nhiên
    - Đi qua từng phần tử trong danh sách:
        - Nếu phần tử đó có giá trị mong muốn, kết thúc tìm kiếm và trả về vị trí của phần tử.
    - Trả về 'Δ'

    Nếu danh sách được lưu trữ dưới dạng mảng, vị trí của phần tử mà ta tìm kiếm có thể là chỉ số của nó trong mảng, còn giá trị Δ có thể là chỉ số nằm trước phần tử đầu tiên (0 hoặc -1 tùy vào danh sách).

    Nếu danh sách được lưu trữ dưới dạng danh sách liên kết, vị trí của phần tử được trả về có thể là địa chỉ của nó, còn giá trị Δ có thể là giá trị null.

    Phiên bản đệ quy
    - Nếu danh sách rỗng, trả về Λ;
    - Ngược lại
        - Nếu phần tử đầu tiên trong danh sách có giá trị mong muốn
            - Trả về vị trí của nó.
        - Ngược lại
            - Tiếp tục tìm kiếm giá trị trong phần còn lại của danh sách và trả về kết quả.

    Sử dụng phần tử cầm canh
    - Thêm phần tử cần tìm và cuối danh sách như một phần tử cầm canh (sentinel):
    - Gán A[n + 1] = x.
    - Gán i = 1.
    - Lặp lại quy trình sau:
        - Nếu A[i] = x,
            - Kết thúc vòng lặp.
        - Gán i = i + 1.
    - Trả về i.

    Việc thêm phần tử cầm canh giúp giảm số lần so sánh chỉ mục hiện tại i với số phần tử n ở mỗi vòng lặp. Tuy nhiên, điều này chỉ áp dụng khi vị trí cuối cùng của danh sách tồn tại nhưng chưa được sử dụng.

    Viết thuật toán tìm kiếm tuyến tính với ngôn ngữ lập trình C, C++, Java, Python3

    Tìm kiếm tuyến tính với C++:

    ```cpp
    #include
    using namespace std;
    int search(int arr[], int n, int x)
    {
        int i;
        for (i = 0; i < n; i++)
            if (arr[i] == x)
                return i;
        return -1;
    }
    int main(void)
    {
        int arr[] = { 2, 3, 4, 10, 40 };
        int x = 10;
        int n = sizeof(arr) / sizeof(arr[0]);
        int result = search(arr, n, x);
        (result == -1) ? cout<<"Element is not present in array"
                    : cout<<"Element is present at index " <
    int search(int arr[], int n, int x)
    {
        int i;
        for (i = 0; i < n; i++)
            if (arr[i] == x)
                return i;
        return -1;
    }
    int main(void)
    {
        int arr[] = { 2, 3, 4, 10, 40 };
        int x = 10;
        int n = sizeof(arr) / sizeof(arr[0]);
        int result = search(arr, n, x);
        (result == -1)
            ? printf("Element is not present in array")
            : printf("Element is present at index %d", result);
        return 0;
    }
    ```

    Tìm kiếm tuyến tính với Python3:

    ```python
    def search(arr, n, x):
        for i in range (0, n):
            if (arr[i] == x):
                return i;
        return -1;
    # Driver Code
    arr = [ 2, 3, 4, 10, 40 ];
    x = 10;
    n = len(arr);
    result = search(arr, n, x)
    if(result == -1):
        print("Element is not present in array")
    else:
        print("Element is present at index", result);
    ```

    Tìm kiếm tuyến tính với Java:

    ```java
    class GFG
    {
        // This function returns index of element x in arr[]
        static int search(int arr[], int x)
        {
            int n = arr.length;
            for(int i = 0; i < n; i++)
            {
                if(arr[i] == x)
                    return i;
            }
            return -1;
        }
        public static void main(String args[])
        {
            int arr[] = { 2, 3, 4, 10, 40 };
            int x = 10;
            int result = search(arr, x);
            if(result == -1)
                System.out.print("Element is not present in array");
            else
                System.out.print("Element is present at index " + result);
        }
    }
    ```

    Tìm kiếm tuyến tính với PHP:

    ```php
    
    ```

    Tìm kiếm tuyến tính với C#:

    ```csharp
    using System;
    class GFG
    {
        public static int search(int[] arr, int x)
        {
            int n = arr.Length;
            for(int i = 0; i < n; i++)
            {
                if(arr[i] == x)
                    return i;
            }
            return -1;
        }
        public static void Main()
        {
            int[] arr = { 2, 3, 4, 10, 40 };
            int x = 10;
            int result = search(arr, x);
            if(result == -1)
                Console.WriteLine("Element is not present in array");
            else
                Console.WriteLine("Element is present at index "+ result);
        }
    }
    ```

    Chạy thử và xem kết quả:

    ```
    Element is present at index 3
    ```

2. Các Thuật Toán Tìm Kiếm Trong C++

Trong bài viết này, chúng ta sẽ giới thiệu đến các thuật toán tìm kiếm phổ biến nhất trong C++. Hãy bắt đầu tìm hiểu về các thuật toán tìm kiếm này.

2.1. Thuật Toán Tìm Kiếm Tuyến Tính

Thuật toán tìm kiếm tuyến tính (linear search) hay còn gọi là thuật toán tìm kiếm tuần tự (Sequential search) là một phương pháp tìm kiếm một phần tử cho trước trong một danh sách bằng cách duyệt lần lượt từng phần tử của danh sách đó cho đến lúc tìm thấy giá trị mong muốn hay đã duyệt qua toàn bộ danh sách.

Thuật toán tìm kiếm tuyến tính là một giải thuật rất đơn giản khi hiện thực. Giải thuật này tỏ ra khá hiệu quả khi cần tìm kiếm phần tử trên một danh sách đủ nhỏ hoặc một danh sách chưa sắp thứ tự đơn giản. Trong trường hợp cần tìm kiếm nhiều lần, dữ liệu thường được xử lý một lần trước khi tìm kiếm: có thể được sắp xếp theo thứ tự, hoặc được xây dựng theo một cấu trúc dữ liệu đặc trưng cho giải thuật hiệu quả hơn,…

Bài toán: Cho một mảng mảng [] gồm n phần tử, hãy viết hàm để tìm kiếm một phần tử x đã cho trong mảng [].

Tìm kiếm tuyến tính trong C++:

#include
using namespace std;
int search(int arr[], int n, int x)
{
    int i;
    for (i = 0; i < n; i++)
        if (arr[i] == x)
            return i;
    return -1;
}
int main(void)
{
    int arr[] = { 2, 3, 4, 10, 40 };
    int x = 10;
    int n = sizeof(arr) / sizeof(arr[0]);
    int result = search(arr, n, x);
    (result == -1) ? cout<<"Element is not present in array"
                : cout<<"Element is present at index " <

Tìm kiếm tuyến tính trong C:

#include 
int search(int arr[], int n, int x)
{
    int i;
    for (i = 0; i < n; i++)
        if (arr[i] == x)
            return i;
    return -1;
}
int main(void)
{
    int arr[] = { 2, 3, 4, 10, 40 };
    int x = 10;
    int n = sizeof(arr) / sizeof(arr[0]);
    int result = search(arr, n, x);
    (result == -1)
        ? printf("Element is not present in array")
        : printf("Element is present at index %d", result);
    return 0;
}

Tìm kiếm tuyến tính trong Python3:

def search(arr, n, x):
    for i in range (0, n):
        if (arr[i] == x):
            return i;
    return -1;
# Driver Code
arr = [ 2, 3, 4, 10, 40 ];
x = 10;
n = len(arr);
result = search(arr, n, x)
if(result == -1):
    print("Element is not present in array")
else:
    print("Element is present at index", result);

Tìm kiếm tuyến tính trong Java:

class GFG
{
    // This function returns index of element x in arr[]
    static int search(int arr[], int x)
    {
        int n = arr.length;
        for(int i = 0; i < n; i++)
        {
            if(arr[i] == x)
                return i;
        }
        return -1;
    }
    public static void main(String args[])
    {
        int arr[] = { 2, 3, 4, 10, 40 };
        int x = 10;
        int result = search(arr, x);
        if(result == -1)
            System.out.print("Element is not present in array");
        else
            System.out.print("Element is present at index " + result);
    }
}

Tìm kiếm tuyến tính trong PHP:

Tìm kiếm tuyến tính trong C#:

using System;
class GFG
{
    public static int search(int[] arr, int x)
    {
        int n = arr.Length;
        for(int i = 0; i < n; i++)
        {
            if(arr[i] == x)
                return i;
        }
        return -1;
    }
    public static void Main()
    {
        int[] arr = { 2, 3, 4, 10, 40 };
        int x = 10;
        int result = search(arr, x);
        if(result == -1)
            Console.WriteLine("Element is not present in array");
        else
            Console.WriteLine("Element is present at index "+ result);
    }
}

Chạy thử và xem kết quả:

Element is present at index 3

2.2. Thuật Toán Tìm Kiếm Nhị Phân

Thuật toán tìm kiếm nhị phân là một trong các thuật toán sắp xếp được sử dụng rất nhiều trong thực tế. Tìm kiếm là một phần không thể thiếu của mọi ứng dụng, website hay phần mềm. Tính năng tìm kiếm cho phép người sử dụng nhanh chóng truy vấn và tìm kiếm các bản ghi theo mong muốn. Và một công cụ tìm kiếm nổi tiếng nhất hàng ngày chúng ta vẫn thường sử dụng đó là Google search.

Bài viết ngày hôm nay Techacademy sẽ giới thiệu cho độc giả một thuật toán tìm kiếm tối ưu áp dụng đối với trường hợp dữ liệu đã được sắp xếp.

Phát biểu thuật toán tìm kiếm nhị phân(Binary search)

Cho một mảng đã sắp xếp arr[] có n phần tử, viết một hàm tìm kiếm trả về chỉ số của phần tử có giá trị x trong arr[].

Giải thuật đơn giản nhất cho bài toán này là sử dụng linear search(tìm kiếm tuyến tính). Tức là bạn sẽ phải đi qua từng phần tử của mảng để đối chiếu với x cần tìm. Thuật toán này trong trường hợp xấu nhất cho độ phức tạp là O(n). Mình cũng sẽ minh họa code của thuật toán này dưới đây.

Đây là code C/C++ sử dụng linear search.

#include
using namespace std;
int search(int arr[], int n, int x)
{
    int i;
    for (i = 0; i < n; i++)
        if (arr[i] == x)
            return i;
    return -1;
}
int main(void)
{
    int arr[] = { 2, 3, 4, 10, 40 };
    int x = 10;
    int n = sizeof(arr) / sizeof(arr[0]);
    int result = search(arr, n, x);
    (result == -1) ? cout<<"Element is not present in array"
                : cout<<"Element is present at index " <

Đây là code C sử dụng linear search.

#include 
int search(int arr[], int n, int x)
{
    int i;
    for (i = 0; i < n; i++)
        if (arr[i] == x)
            return i;
    return -1;
}
int main(void)
{
    int arr[] = { 2, 3, 4, 10, 40 };
    int x = 10;
    int n = sizeof(arr) / sizeof(arr[0]);
    int result = search(arr, n, x);
    (result == -1) ? printf("Element is not present in array")
                : printf("Element is present at index %d", result);
    return 0;
}

Đây là code Python3 sử dụng linear search.

def search(arr, n, x):
    for i in range (0, n):
        if (arr[i] == x):
            return i;
    return -1;
# Driver Code
arr = [ 2, 3, 4, 10, 40 ];
x = 10;
n = len(arr);
result = search(arr, n, x)
if(result == -1):
    print("Element is not present in array")
else:
    print("Element is present at index", result);

Đây là code Java sử dụng linear search.

class GFG
{
    // This function returns index of element x in arr[]
    static int search(int arr[], int x)
    {
        int n = arr.length;
        for(int i = 0; i < n; i++)
        {
            if(arr[i] == x)
                return i;
        }
        return -1;
    }
    public static void main(String args[])
    {
        int arr[] = { 2, 3, 4, 10, 40 };
        int x = 10;
        int result = search(arr, x);
        if(result == -1)
            System.out.print("Element is not present in array");
        else
            System.out.print("Element is present at index " + result);
    }
}

Đây là code PHP sử dụng linear search.

2.3. Thuật Toán Tìm Kiếm Nội Suy

Thuật toán tìm kiếm nội suy là một sự cải tiến của tìm kiếm nhị phân Binary Search. Nó có xu hướng tiến gần đến vị trí, giá trị tìm kiếm. Do đó tốc độ tìm kiếm được tối ưu rất cao và nhanh hơn nhiều so với Binary Search.

Cách thức hoạt động của nó dựa trên Binary Search, nhưng có sự cải tiến hơn. Đó chính là nó tìm ra phần tử gần với giá trị tìm kiếm nhất và bắt đầu từ đó để tìm.

Ví dụ:

Chúng ta có danh sách các sinh viên trong một lớp. Nếu chúng ta muốn tìm một bạn tên Tiến, thì chúng ta sẽ ưu tiên việc tìm kiếm từ cuối danh sách. Chứ không nên tìm kiếm từ đầu danh sách vì điều đó rất mất thời gian.

Với Interpolation Search nó sẽ linh hoạt hơn rất nhiều trong lúc tìm kiếm

Giả xử chúng ta có:

  • Left, right là hai vị trí đầu và cuối.
  • T là tập.
  • X là giá trị cần tìm.

Giải thích thuật toán

Bước 1:

  • Chúng ta sẽ sử dụng công thức tìm phần tử chính giữa của tập theo cách tìm kiếm Binary Search: Search = left + (right – left) * 1/2
  • Trong công thức trên chúng ta sẽ thay giá trị 1/2 bằng biểu thức sau: (X – T[left]) / (T[right] – T[left])
  • Sau khi thay biểu thức vào công thức sẽ được công thức mới như sau: Search = left + (X- T[left]) * (right – left) / (T[right] – T[left])

Bước 2:

  • Bây giờ chúng ta sẽ kiểm tra T[Search] nếu bằng X thì Search chính là vị trí cần tìm.
  • Nếu Search < X thì tăng left lên một đơn vị rồi quay lại bước
FEATURED TOPIC