Menu
×

Được chứng nhận

Ghi lại kiến ​​thức của bạn

Đăng nhập Đăng ký

Tạo Tài khoản Example.com.vn miễn phí để cải thiện trải nghiệm học tập của bạn

Người tìm đường và việc học của tôi

Theo dõi tiến độ học tập của bạn tại Example.com.vn và thu thập phần thưởng

Nâng cấp

Trở thành người dùng PLUS và mở khóa các tính năng mạnh mẽ (không có quảng cáo, lưu trữ, hỗ trợ, ..)

Bắt đầu từ đâu

Bạn không chắc chắn muốn bắt đầu từ đâu? Đi theo con đường được hướng dẫn của chúng tôi

Trình chỉnh sửa mã (Dùng thử)

Với trình chỉnh sửa mã trực tuyến của chúng tôi, bạn có thể chỉnh sửa mã và xem kết quả trong trình duyệt của mình

Video

Tìm hiểu những điều cơ bản về HTML qua video hướng dẫn thú vị và hấp dẫn

Mẫu

Chúng tôi đã tạo một loạt mẫu trang web đáp ứng mà bạn có thể sử dụng - miễn phí!

Web hosting

Lưu trữ trang web của riêng bạn và chia sẻ nó với mọi người với Example.com.vn Spaces

Tạo một máy chủ

Tạo máy chủ của riêng bạn bằng Python, PHP, React.js, Node.js, Java, C#, v.v.

Làm thế nào để

Bộ sưu tập lớn các đoạn mã cho HTML, CSS và JavaScript

Khung CSS

Xây dựng các trang web nhanh và phản hồi bằng cách sử dụng khung W3.CSS miễn phí của chúng tôi

Thống kê trình duyệt

Đọc xu hướng dài hạn của việc sử dụng trình duyệt

Tốc độ gõ

Kiểm tra tốc độ đánh máy của bạn

Đào tạo AWS

Tìm hiểu dịch vụ web của Amazon

Bộ chọn màu

Sử dụng công cụ chọn màu của chúng tôi để tìm các màu RGB, HEX và HSL khác nhau. Bánh xe màu hình tròn thể hiện sự chuyển màu trong quang phổ

Trò chơi mã

Trò chơi mã hóa W3Schools! Giúp linh miêu thu thập nón thông Logo Lynx

Đặt mục tiêu

Nhận hành trình học tập được cá nhân hóa dựa trên các kỹ năng và mục tiêu hiện tại của bạn

Bản tin

Tham gia bản tin của chúng tôi và có quyền truy cập vào nội dung độc quyền mỗi tháng

Việc làm

Thuê những tài năng công nghệ hàng đầu. Hợp lý hóa quy trình tuyển dụng của bạn để có đội ngũ phù hợp hoàn hảo

Lớp học

Hãy liên hệ để sử dụng Example.com.vn Plus và các chứng chỉ với tư cách là một tổ chức giáo dục

×
HTML CSS JAVASCRIPT SQL PYTHON JAVA PHP CÁCH W3.CSS C C++ C# BOOTSTRAP REACT MYSQL JQUERY EXCEL XML DJANGO NUMPY PANDAS NODEJS R TYPESCRIPT ANGULAR GIT POSTGRESQL MONGODB ASP AI GO KOTLIN SASS VUE DSA GEN AI SCIPY AWS AN NINH MẠNG DỮ LIỆU KHOA HỌC

Hướng dẫn DSA

DSA TRANG CHỦ DSA Giới thiệu Thuật toán đơn giản DSA

Mảng

Mảng DSA Sắp xếp bong bóng DSA Sắp xếp lựa chọn DSA Sắp xếp chèn DSA Sắp xếp nhanh DSA Sắp xếp đếm DSA Sắp xếp cơ số DSA Sắp xếp hợp nhất DSA Tìm kiếm tuyến tính DSA Tìm kiếm nhị phân DSA

Danh sách liên kết

Danh sách liên kết DSA Danh sách liên kết DSA trong bộ nhớ Danh sách liên kết DSA Các loại Danh sách liên kết Hoạt động

Ngăn xếp & hàng đợi

Ngăn xếp DSA Hàng đợi DSA

Bảng băm

Bảng băm DSA Bộ hàm băm DSA Bản đồ hàm băm DSA

Cây

Cây DSA Cây nhị phân DSA DSA Traversal đặt hàng trước DSA Traversal theo thứ tự DSA Traversal DSA sau thực hiện mảng DSA Cây tìm kiếm nhị phân DSA Cây AVL DSA

Đồ thị

Đồ thị DSA Thực hiện đồ thị Đồ thị DSA Phát hiện chu trình DSA truyền tải

Con đường ngắn nhất

Đường đi ngắn nhất DSA DSA Bellman-Ford của DSA Dijkstra

Cây bao trùm tối thiểu

Cây khung tối thiểu DSA Prim's DSA Kruskal's

Lưu lượng cực đại

DSA Lưu lượng tối đa DSA Ford-Fulkerson DSA Edmonds-Karp

Độ phức tạp thời gian

Giới thiệu Sắp xếp bong bóng Lựa chọn Sắp xếp Chèn Sắp xếp Sắp xếp nhanh Đếm Sắp xếp Cơ số Sắp xếp Hợp nhất Sắp xếp Tìm kiếm tuyến tính Tìm kiếm nhị phân

Tham chiếu DSA

Thuật toán Euclide DSA Thuật toán tham lam DSA Ghi nhớ DSA DSA Người bán hàng du lịch

Ví dụ về DSA

Ví dụ về DSA Bài tập DSA Câu hỏi DSA Chứng chỉ DSA

Cây tìm kiếm nhị phân DSA

Cây tìm kiếm nhị phân là Cây nhị phân trong đó nút con bên trái của mỗi nút có giá trị thấp hơn và nút con bên phải của mỗi nút có giá trị cao hơn.

Ưu điểm rõ ràng của Cây tìm kiếm nhị phân là các hoạt động như tìm kiếm, xóa và chèn được thực hiện nhanh chóng mà không cần phải thay đổi giá trị trong bộ nhớ.

Cây tìm kiếm nhị phân

Cây tìm kiếm nhị phân (BST) là một loại cấu trúc dữ liệu Cây nhị phân , trong đó các thuộc tính sau phải đúng với bất kỳ nút "X" nào trong cây:

  • Nút con bên trái của nút X và tất cả các nút con cháu của nó (con, nút con, v.v.) có giá trị thấp hơn giá trị của X.
  • Con bên phải và tất cả con cháu của nó có giá trị cao hơn giá trị của X.
  • Cây con trái và phải cũng phải là Cây tìm kiếm nhị phân.

Các thuộc tính này giúp tìm kiếm, thêm và xóa các giá trị nhanh hơn cây nhị phân thông thường.

Để làm cho điều này dễ hiểu và dễ thực hiện nhất có thể, hãy giả sử rằng tất cả các giá trị trong Cây tìm kiếm nhị phân là duy nhất.

Sử dụng Cây tìm kiếm nhị phân bên dưới để hiểu rõ hơn về các khái niệm này và thuật ngữ liên quan.

13 7 15 3 số 8 14 19 18

Kích thước của cây là số nút trong đó (\(n\)).

Cây con bắt đầu bằng một trong các nút trong cây làm gốc cục bộ và bao gồm nút đó và tất cả các nút con của nó.

Con cháu của một nút là tất cả các nút con của nút đó và tất cả các nút con của chúng, v.v. Chỉ cần bắt đầu với một nút và con cháu sẽ là tất cả các nút được kết nối bên dưới nút đó.

Chiều cao của nút là số cạnh tối đa giữa nút đó và nút lá.

Nút kế tiếp theo thứ tự của nút là nút xuất hiện sau nút đó nếu chúng ta thực hiện truyền tải theo thứ tự. Việc truyền tải BST theo thứ tự ở trên sẽ dẫn đến nút 13 đến trước nút 14 và do đó, nút kế thừa của nút 13 là nút 14.


Truyền tải cây tìm kiếm nhị phân

Chỉ để xác nhận rằng chúng tôi thực sự có cấu trúc dữ liệu Cây tìm kiếm nhị phân trước mặt, chúng tôi có thể kiểm tra xem các thuộc tính ở đầu trang này có đúng hay không. Vì vậy, đối với mỗi nút trong hình trên, hãy kiểm tra xem tất cả các giá trị ở bên trái của nút có thấp hơn và tất cả các giá trị ở bên phải có cao hơn không.

Một cách khác để kiểm tra xem Cây nhị phân có phải là BST hay không là thực hiện duyệt theo thứ tự (như chúng tôi đã làm ở trang trước) và kiểm tra xem danh sách giá trị kết quả có theo thứ tự tăng dần hay không.

Mã bên dưới là cách triển khai Cây tìm kiếm nhị phân trong hình trên, với tính năng truyền tải.

Ví dụ

Trăn:

 class TreeNode:
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None

def inOrderTraversal(node):
    if node is None:
        return
    inOrderTraversal(node.left)
    print(node.data, end=", ")
    inOrderTraversal(node.right)

root = TreeNode(13)
node7 = TreeNode(7)
node15 = TreeNode(15)
node3 = TreeNode(3)
node8 = TreeNode(8)
node14 = TreeNode(14)
node19 = TreeNode(19)
node18 = TreeNode(18)

root.left = node7
root.right = node15

node7.left = node3
node7.right = node8

node15.left = node14
node15.right = node19

node19.left = node18

# Traverse
inOrderTraversal(root)
Chạy ví dụ »

Như chúng ta có thể thấy bằng cách chạy ví dụ mã ở trên, việc duyệt theo thứ tự sẽ tạo ra một danh sách các số theo thứ tự tăng dần (tăng dần), có nghĩa là Cây nhị phân này là Cây tìm kiếm nhị phân.


Tìm kiếm giá trị trong BST

Tìm kiếm một giá trị trong BST rất giống với cách chúng tôi tìm thấy một giá trị bằng cách sử dụng Tìm kiếm nhị phân trên một mảng.

Để Tìm kiếm nhị phân hoạt động, mảng phải được sắp xếp sẵn và việc tìm kiếm một giá trị trong mảng có thể được thực hiện rất nhanh.

Tương tự, việc tìm kiếm một giá trị trong BST cũng có thể được thực hiện rất nhanh nhờ cách đặt các nút.

Làm thế nào nó hoạt động:

  1. Bắt đầu tại nút gốc.
  2. Nếu đây là giá trị chúng tôi đang tìm kiếm, hãy quay lại.
  3. Nếu giá trị chúng ta đang tìm kiếm cao hơn, hãy tiếp tục tìm kiếm ở cây con bên phải.
  4. Nếu giá trị chúng ta đang tìm kiếm thấp hơn, hãy tiếp tục tìm kiếm ở cây con bên trái.
  5. Nếu cây con mà chúng ta muốn tìm kiếm không tồn tại, tùy thuộc vào ngôn ngữ lập trình, hãy trả về None hoặc NULL hoặc một cái gì đó tương tự để chỉ ra rằng giá trị không nằm trong BST.

Sử dụng hoạt ảnh bên dưới để xem cách chúng tôi tìm kiếm một giá trị trong Cây tìm kiếm nhị phân.

Nhấp vào Tìm kiếm.

13 7 15 3 số 8 14 19 18

Thuật toán trên có thể được thực hiện như thế này:

Ví dụ

Trăn:

 def search(node, target):
    if node is None:
        return None 
    elif node.data == target:
        return node
    elif target < node.data:
        return search(node.left, target)
    else:
        return search(node.right, target)
Chạy ví dụ »

Độ phức tạp về thời gian để tìm kiếm BST cho một giá trị là \(O(h)\), trong đó \(h\) là chiều cao của cây.

Ví dụ: đối với BST có hầu hết các nút ở phía bên phải, chiều cao của cây sẽ trở nên lớn hơn mức cần thiết và việc tìm kiếm trong trường hợp xấu nhất sẽ mất nhiều thời gian hơn. Những cây như vậy được gọi là không cân bằng.

13 7 15 3 số 8 14 19 18
BST cân bằng
7 13 3 15 số 8 19 14 18
BST không cân bằng

Cả hai Cây tìm kiếm nhị phân ở trên đều có cùng một nút và việc duyệt theo thứ tự của cả hai cây đều cho chúng ta cùng một kết quả nhưng chiều cao rất khác nhau. Việc tìm kiếm cây không cân bằng ở trên mất nhiều thời gian hơn vì nó cao hơn.

Chúng ta sẽ sử dụng trang tiếp theo để mô tả một loại Cây nhị phân được gọi là Cây AVL. Cây AVL có khả năng tự cân bằng, nghĩa là chiều cao của cây được giữ ở mức tối thiểu để các thao tác như tìm kiếm, chèn và xóa mất ít thời gian hơn.


Chèn một nút vào BST

Chèn một nút vào BST tương tự như tìm kiếm một giá trị.

Làm thế nào nó hoạt động:

  1. Bắt đầu tại nút gốc.
  2. So sánh từng nút:
    • Giá trị có thấp hơn không? Quẹo trái.
    • Giá trị có cao hơn không? Đi bên phải.
  3. Tiếp tục so sánh các nút với giá trị mới cho đến khi không còn bên phải hoặc bên trái để so sánh. Đó là nơi nút mới được chèn vào.

Việc chèn các nút như mô tả ở trên có nghĩa là nút được chèn sẽ luôn trở thành nút lá mới.

Sử dụng mô phỏng bên dưới để xem các nút mới được chèn như thế nào.

Nhấp vào Chèn.

13 7 15 3 số 8 14 19 18 10

Tất cả các nút trong BST là duy nhất, vì vậy trong trường hợp chúng tôi tìm thấy giá trị giống với giá trị chúng tôi muốn chèn, chúng tôi sẽ không làm gì cả.

Đây là cách chèn nút trong BST có thể được thực hiện:

Ví dụ

Trăn:

 def insert(node, data):
    if node is None:
        return TreeNode(data)
    else:
        if data < node.data:
            node.left = insert(node.left, data)
        elif data > node.data:
            node.right = insert(node.right, data)
    return node
Chạy ví dụ »

Tìm giá trị thấp nhất trong cây con BST

Phần tiếp theo sẽ giải thích cách chúng ta có thể xóa một nút trong BST, nhưng để làm được điều đó, chúng ta cần một hàm tìm giá trị thấp nhất trong cây con của nút đó.

Làm thế nào nó hoạt động:

  1. Bắt đầu tại nút gốc của cây con.
  2. Đi sang trái càng xa càng tốt.
  3. Nút bạn kết thúc là nút có giá trị thấp nhất trong cây con BST đó.

Trong hình bên dưới, nếu chúng ta bắt đầu ở nút 13 và tiếp tục đi sang trái, chúng ta sẽ đến nút 3, đây là giá trị thấp nhất, phải không?

Và nếu chúng ta bắt đầu ở nút 15 và tiếp tục đi sang trái, chúng ta sẽ đến nút 14, đây là giá trị thấp nhất trong cây con của nút 15.

13 7 15 3 số 8 14 19 18

Đây là cách hàm tìm giá trị thấp nhất trong cây con của nút BST trông như thế nào:

Ví dụ

Trăn:

 def minValueNode(node):
    current = node
    while current.left is not None:
        current = current.left
    return current
Chạy ví dụ »

Chúng ta sẽ sử dụng hàm minValueNode() này trong phần bên dưới để tìm nút kế thừa theo thứ tự của nút và sử dụng hàm đó để xóa nút.


Xóa một nút trong BST

Để xóa một nút, trước tiên hàm của chúng ta phải tìm kiếm BST để tìm nó.

Sau khi tìm thấy nút, có ba trường hợp khác nhau trong đó việc xóa nút phải được thực hiện khác nhau.

Làm thế nào nó hoạt động:

  1. Nếu nút là nút lá, hãy loại bỏ nó bằng cách loại bỏ liên kết đến nó.
  2. Nếu nút chỉ có một nút con, hãy kết nối nút cha của nút bạn muốn xóa với nút con đó.
  3. Nếu nút có cả nút con phải và nút con trái: Tìm nút kế thừa theo thứ tự của nút, thay đổi giá trị với nút đó rồi xóa nó.

Ở bước 3 ở trên, nút kế tiếp mà chúng tôi tìm thấy sẽ luôn là nút lá và vì đó là nút xuất hiện ngay sau nút mà chúng tôi muốn xóa nên chúng tôi có thể hoán đổi giá trị với nút đó và xóa nó.

Sử dụng hình ảnh động bên dưới để xem các nút khác nhau bị xóa như thế nào.

13 7 15 3 số 8 14 14 19 18

Nút 8 là nút lá (trường hợp 1) nên sau khi tìm thấy, chúng ta có thể xóa nó đi.

Nút 19 chỉ có một nút con (trường hợp 2). Để xóa nút 19, nút cha 15 được kết nối trực tiếp với nút 18 và sau đó có thể xóa nút 19.

Nút 13 có hai nút con (trường hợp 3). Chúng ta tìm nút kế thừa, nút xuất hiện ngay sau trong quá trình truyền tải theo thứ tự, bằng cách tìm nút thấp nhất trong cây con bên phải của nút 13, tức là nút 14. Giá trị 14 được đưa vào nút 13 và sau đó chúng ta có thể xóa nút 14.

Đây là cách BST có thể được triển khai với chức năng xóa nút:

Ví dụ

Trăn:

 def delete(node, data):
    if not node:
        return None

    if data < node.data:
        node.left = delete(node.left, data)
    elif data > node.data:
        node.right = delete(node.right, data)
    else:
        # Node with only one child or no child
        if not node.left:
            temp = node.right
            node = None
            return temp
        elif not node.right:
            temp = node.left
            node = None
            return temp

        # Node with two children, get the in-order successor
        node.data = minValueNode(node.right).data
        node.right = delete(node.right, node.data)

    return node
Chạy ví dụ »

Dòng 1 : Đối số node ở đây giúp hàm có thể tự gọi đệ quy trên các cây con ngày càng nhỏ hơn trong quá trình tìm kiếm nút có data mà chúng ta muốn xóa.

Dòng 2-8 : Đây là tìm kiếm nút có data chính xác mà chúng tôi muốn xóa.

Dòng 9-22 : Nút chúng ta muốn xóa đã được tìm thấy. Có ba trường hợp như vậy:

  1. Trường hợp 1 : Nút không có nút con (nút lá). None được trả về và giá trị đó trở thành giá trị bên trái hoặc bên phải mới của nút cha bằng cách đệ quy (dòng 6 hoặc 8).
  2. Trường hợp 2 : Nút có nút con trái hoặc nút con phải. Nút con trái hoặc phải đó trở thành nút con trái hoặc phải mới của cha mẹ thông qua đệ quy (dòng 7 hoặc 9).
  3. Trường hợp 3 : Nút có cả nút con trái và nút con phải. Người kế nhiệm theo thứ tự được tìm thấy bằng hàm minValueNode() . Chúng tôi giữ giá trị của nút kế tiếp bằng cách đặt nó làm giá trị của nút mà chúng tôi muốn xóa và sau đó chúng tôi có thể xóa nút kế tiếp.

Dòng 24 : node được trả về để duy trì chức năng đệ quy.


BST so với các cấu trúc dữ liệu khác

Cây tìm kiếm nhị phân tận dụng tốt nhất hai cấu trúc dữ liệu khác: Mảng và Danh sách liên kết.

Data Structure Searching for a value Delete / Insert leads to shifting in memory
Sorted Array \(\boldsymbol{O(\log n)}\) Yes
Linked List \(O(n)\) No
Binary Search Tree \(\boldsymbol{O(\log n)}\) No

Tìm kiếm BST cũng nhanh như Tìm kiếm nhị phân trên một mảng, với cùng độ phức tạp về thời gian \(O(\log n)\).

Và việc xóa và chèn các giá trị mới có thể được thực hiện mà không cần dịch chuyển các phần tử trong bộ nhớ, giống như với Danh sách được liên kết.


Cân bằng BST và độ phức tạp thời gian

Trên Cây tìm kiếm nhị phân, các thao tác như chèn nút mới, xóa nút hoặc tìm kiếm nút thực chất là \(O(h)\). Điều đó có nghĩa là cây càng cao (\(h\)) thì thao tác sẽ càng mất nhiều thời gian.

Lý do chúng tôi viết rằng việc tìm kiếm giá trị \(O(\log n)\) trong bảng trên là vì điều đó đúng nếu cây "cân bằng", như trong hình bên dưới.

13 7 15 3 số 8 14 19 18
BST cân bằng

Chúng ta gọi cây này là cân bằng vì có số lượng nút ở bên trái và bên phải của cây gần như bằng nhau.

Cách chính xác để biết rằng Cây nhị phân được cân bằng là chiều cao của cây con bên trái và bên phải của bất kỳ nút nào chỉ khác nhau một. Trong hình ảnh trên, cây con bên trái của nút gốc có chiều cao \(h=2\) và cây con bên phải có chiều cao \(h=3\).

Đối với BST cân bằng, với số lượng lớn nút (lớn \(n\)), chúng tôi nhận được chiều cao \(h \approx \log_2 n\) và do đó, độ phức tạp về thời gian để tìm kiếm, xóa hoặc chèn nút có thể là được viết là \(O(h) = O(\log n)\).

Tuy nhiên, trong trường hợp BST hoàn toàn không cân bằng, như trong hình bên dưới, chiều cao của cây xấp xỉ bằng số nút, \(h \approx n\) và chúng ta có độ phức tạp về thời gian \(O(h ) = O(n)\) để tìm kiếm, xóa hoặc chèn nút.

7 13 3 15 số 8 19 14 18
BST không cân bằng

Vì vậy, để tối ưu hóa các hoạt động trên BST, chiều cao phải được giảm thiểu và để làm được điều đó, cây phải được cân bằng.

Và việc giữ cho Cây tìm kiếm nhị phân được cân bằng chính xác là những gì Cây AVL làm, đó là cấu trúc dữ liệu được giải thích ở trang tiếp theo.


Bài tập DSA

Kiểm tra bản thân bằng các bài tập

Bài tập:

Chèn một nút có giá trị 6 vào Cây tìm kiếm nhị phân này:

Chèn một nút vào Cây tìm kiếm nhị phân

Nút mới được chèn vào đâu?

Nút có giá trị 6 
trở thành nút con bên phải
của nút có giá trị .

Bắt đầu bài tập



×

Liên hệ bán hàng

Nếu bạn muốn sử dụng dịch vụ của Example.com.vn với tư cách là một tổ chức giáo dục, nhóm hoặc doanh nghiệp, hãy gửi email cho chúng tôi:
[email được bảo vệ]

Báo cáo lỗi

Nếu bạn muốn báo cáo lỗi hoặc nếu bạn muốn đưa ra đề xuất, hãy gửi email cho chúng tôi:
[email được bảo vệ]

Example.com.vn được tối ưu hóa cho việc học tập và đào tạo. Các ví dụ có thể được đơn giản hóa để cải thiện khả năng đọc và học. Các hướng dẫn, tài liệu tham khảo và ví dụ liên tục được xem xét để tránh sai sót, nhưng chúng tôi không thể đảm bảo tính chính xác hoàn toàn của mọi nội dung. Khi sử dụng W3Schools, bạn đồng ý đã đọc và chấp nhận các điều khoản sử dụng , chính sách cookie và quyền riêng tư của chúng tôi.

Bản quyền 1999-2024 của Refsnes Data. Đã đăng ký Bản quyền. Example.com.vn được cung cấp bởi W3.CSS .