×

Cài đặt thuật toán Union-Find (Disjoint Set) trong lập trình

Quản lý và xử lý các tập hợp con rời rạc là một vấn đề phổ biến trong nhiều lĩnh vực của khoa học máy tính, như đồ thị học, phân tích kết nối mạng, và nhiều ứng dụng khác. Thuật toán Union-Find, hay còn được gọi là Disjoint Set, là một công cụ mạnh mẽ trong việc giải quyết vấn đề này. Hãy cùng khám phá cách cài đặt và sử dụng thuật toán này trong lập trình.

Tổng quan về thuật toán Union-Find

Thuật toán Union-Find gồm hai thao tác chính trên các tập hợp con rời rạc:

  1. Find: Xác định tập hợp mà một phần tử thuộc về.
  2. Union: Hợp nhất hai tập hợp lại với nhau.

Cấu trúc dữ liệu này giúp duy trì và kiểm soát một hệ thống các tập hợp không giao nhau, tối ưu hóa các thao tác tìm kiếm và hợp nhất bằng cách sử dụng hai kỹ thuật là "path compression" và "union by rank".

Các bước cài đặt

Khởi tạo

Để bắt đầu, ta cần một mảng parent[] để lưu trữ đại diện (hoặc đỉnh gốc) của mỗi tập hợp, và một mảng rank[] để lưu trữ thứ bậc (chiều cao) của cây đại diện cho tập hợp đó.

def make_set(n):
    parent = [i for i in range(n)]
    rank = [0] * n
    return parent, rank

Tìm cây đại diện (Find)

Hàm find giúp xác định đại diện của tập hợp chứa phần tử x.

def find(parent, x):
    if parent[x] != x:
        parent[x] = find(parent, parent[x])  # Path compression
    return parent[x]

Hợp nhất hai tập hợp (Union)

Hàm union kết hợp hai tập hợp chứa các phần tử xy.

def union(parent, rank, x, y):
    root_x = find(parent, x)
    root_y = find(parent, y)
    
    if root_x != root_y:
        if rank[root_x] > rank[root_y]:
            parent[root_y] = root_x
        elif rank[root_x] < rank[root_y]:
            parent[root_x] = root_y
        else:
            parent[root_y] = root_x
            rank[root_x] += 1

Ứng dụng trong lập trình

Sau khi cài đặt xong các hàm make_set, findunion, chúng ta có thể dễ dàng sử dụng chúng trong các bài toán yêu cầu quản lý các tập hợp con rời rạc.

if __name__ == "__main__":
    # Khởi tạo với 5 phần tử (0 đến 4)
    parent, rank = make_set(5)
    
    # Hợp nhất các tập hợp lại
    union(parent, rank, 0, 1)
    union(parent, rank, 2, 3)
    union(parent, rank, 1, 4)
    
    # Kiểm tra đại diện của các phần tử
    print(find(parent, 4))  # Output: 0, vì 4 liên kết với 0 qua 1
    print(find(parent, 3))  # Output: 2, vì 3 liên kết với 2
    print(find(parent, 0))  # Output: 0, gốc của tập hợp chứa 0

Kết luận

Thuật toán Union-Find là một công cụ hữu ích trong việc quản lý các tập hợp con rời rạc. Nhờ vào các kỹ thuật tối ưu như "path compression" và "union by rank", các thao tác tìm kiếm và hợp nhất trở nên rất hiệu quả. Cài đặt và hiểu rõ về thuật toán này giúp lập trình viên giải quyết nhiều vấn đề phức tạp trong thực tế, từ đồ thị học cho tới quản lý tài nguyên hệ thống.

Comments