Hướng dẫn is there a binary search function in python? - có chức năng tìm kiếm nhị phân trong python không?
Mặc dù không có thuật toán tìm kiếm nhị phân rõ ràng trong Python, nhưng có một mô -đun - 1 - được thiết kế để tìm điểm chèn cho một phần tử trong danh sách được sắp xếp bằng tìm kiếm nhị phân. Điều này có thể được "lừa" để thực hiện tìm kiếm nhị phân. Ưu điểm lớn nhất của điều này là lợi thế tương tự mà hầu hết các mã thư viện có - nó hoạt động cao, được thử nghiệm tốt và chỉ hoạt động (đặc biệt tìm kiếm nhị phân có thể khá khó thực hiện thành công - đặc biệt nếu các trường hợp cạnh không được xem xét cẩn thận). Show
Các loại cơ bảnĐối với các loại cơ bản như chuỗi hoặc INT, điều đó khá dễ dàng - tất cả những gì bạn cần là mô -đun 1 và danh sách được sắp xếp:
Bạn cũng có thể sử dụng điều này để tìm bản sao:
Rõ ràng bạn chỉ có thể trả lại chỉ mục chứ không phải giá trị ở chỉ mục đó nếu muốn. Các đối tượngĐối với các loại hoặc đối tượng tùy chỉnh, mọi thứ khó khăn hơn một chút: bạn phải đảm bảo thực hiện các phương pháp so sánh phong phú để có được chia đôi để so sánh chính xác.
Điều này sẽ hoạt động trong ít nhất Python 2.7 -> 3.3 Xem bây giờ hướng dẫn này có một khóa học video liên quan được tạo bởi nhóm Python thực sự. Xem nó cùng với hướng dẫn bằng văn bản để hiểu sâu hơn về sự hiểu biết của bạn: Tạo một tìm kiếm nhị phân trong Python This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Creating a Binary Search in Python Làm thế nào để bạn sử dụng tìm kiếm nhị phân trong Python? is a classic algorithm in computer science. It often comes up in programming contests and technical interviews. Implementing binary search turns out to be a challenging task, even when you understand the concept. Unless you’re curious or have a specific assignment, you should always leverage existing libraries to do a binary search in Python or any other language. So sánh x với phần tử giữa ..
Với tất cả kiến thức này, bạn sẽ làm rung chuyển cuộc phỏng vấn lập trình của bạn! Cho dù thuật toán tìm kiếm nhị phân là một giải pháp tối ưu cho một vấn đề cụ thể, bạn có các công cụ để tự mình tìm ra nó. Bạn không cần một bằng cấp khoa học máy tính để làm như vậy.intermediate programmer with an interest in algorithms and data structures. At the very least, you should be familiar with Python’s built-in data types, such as lists and tuples. In addition, some familiarity with recursion, classes, data classes, and lambdas will help you better understand the concepts you’ll see in this tutorial. Bạn có thể lấy tất cả các mã mà bạn đã thấy trong hướng dẫn này tại liên kết dưới đây: Xem bây giờ hướng dẫn này có một khóa học video liên quan được tạo bởi nhóm Python thực sự. Xem nó cùng với hướng dẫn bằng văn bản để hiểu sâu hơn về sự hiểu biết của bạn: Tạo một tìm kiếm nhị phân trong PythonLàm thế nào để bạn sử dụng tìm kiếm nhị phân trong Python? So sánh x với phần tử giữa ..
Nếu x khớp với phần tử giữa, chúng ta sẽ trả về chỉ số giữa .. Khác nếu x lớn hơn phần tử giữa, thì x chỉ có thể nằm ở nửa bên phải Subarray sau phần tử giữa. Vì vậy, chúng tôi tái diễn cho nửa đúng ..Khác (x nhỏ hơn) tái diễn cho nửa bên trái ..
Chỉ số () sử dụng tìm kiếm nhị phân?header with the column names in the first line, followed by data records in each of the subsequent lines. Each record contains a unique identifier, a full name, birth year, and a few other attributes. These are all delimited with a tab character. Các chỉ mục cơ sở dữ liệu sử dụng B-cây, khái quát hóa cây nhị phân. Không giống như sử dụng tìm kiếm nhị phân, mặc dù ý tưởng chung về "chia và chinh phục" trong cả hai trường hợp. Đọc các giá trị phân tách tabCó một vài cách để phân tích tệp TSV. Ví dụ: bạn có thể đọc nó bằng gấu trúc, sử dụng một ứng dụng chuyên dụng hoặc tận dụng một vài công cụ dòng lệnh. Tuy nhiên, nó khuyên bạn nên sử dụng tập lệnh Python không rắc rối có trong mã mẫu. Cuối cùng, bạn muốn kết thúc với hai tệp văn bản theo ý của bạn:
Một người sẽ chứa một danh sách các tên thu được bằng cách cắt cột thứ hai khỏi tệp TSV gốc:
Cái thứ hai sẽ là phiên bản sắp xếp của cái này. Khi cả hai tệp đã sẵn sàng, bạn có thể tải chúng vào Python bằng chức năng này:
Mã này trả về một danh sách các tên được lấy từ tệp đã cho. Lưu ý rằng việc gọi 7 trên chuỗi kết quả sẽ loại bỏ ký tự dòng mới ra khỏi mỗi dòng. Thay vào đó, bạn có thể gọi 8, nhưng điều đó sẽ giữ cho các dòng mới không mong muốn.Đo thời gian thực hiệnĐể đánh giá hiệu suất của một thuật toán cụ thể, bạn có thể đo thời gian thực hiện của nó so với bộ dữ liệu IMDB. Điều này thường được thực hiện với sự trợ giúp của các mô-đun 9 hoặc 0 tích hợp, rất hữu ích cho việc định thời gian một khối mã.Bạn cũng có thể xác định một người trang trí tùy chỉnh theo thời gian một chức năng nếu bạn muốn. Mã mẫu được cung cấp sử dụng 1, được giới thiệu trong Python 3.7, bởi vì nó cung cấp độ chính xác cao trong nano giây.Hiểu thuật toán tìm kiếmTìm kiếm có mặt khắp nơi và nằm ở trung tâm của khoa học máy tính. Bạn có thể đã thực hiện một số tìm kiếm trên web ngày hôm nay, nhưng bạn đã bao giờ tự hỏi việc tìm kiếm thực sự có nghĩa là gì?searching really means? Thuật toán tìm kiếm có nhiều hình thức khác nhau. Ví dụ: bạn có thể:
Trong hướng dẫn này, bạn sẽ tìm hiểu về việc tìm kiếm một yếu tố trong danh sách các mục được sắp xếp, như một danh bạ điện thoại. Khi bạn tìm kiếm một yếu tố như vậy, bạn có thể hỏi một trong những câu hỏi sau:
Câu trả lời cho câu hỏi đầu tiên cho bạn biết liệu một yếu tố có mặt trong bộ sưu tập hay không. Nó luôn giữ đúng hoặc sai. Câu trả lời thứ hai là vị trí của một phần tử trong bộ sưu tập, có thể không có sẵn nếu phần tử đó bị thiếu. Cuối cùng, câu trả lời thứ ba là chính yếu tố, hoặc thiếu nó.present in the collection. It always holds either true or false. The second answer is the location of an element within the collection, which may be unavailable if that element was missing. Finally, the third answer is the element itself, or a lack of it. Trong trường hợp phổ biến nhất, bạn sẽ tìm kiếm theo giá trị, so sánh các yếu tố trong bộ sưu tập với cái chính xác bạn cung cấp làm tài liệu tham khảo. Nói cách khác, tiêu chí tìm kiếm của bạn là toàn bộ yếu tố, chẳng hạn như số, chuỗi hoặc một đối tượng giống như một người. Ngay cả sự khác biệt nhỏ nhất giữa hai yếu tố so sánh cũng giành được kết quả trong một trận đấu.searching by value, which compares elements in the collection against the exact one you provide as a reference. In other words, your search criteria are the entire element, such as a number, a string, or an object like a person. Even the tiniest difference between the two compared elements won’t result in a match. Mặt khác, bạn có thể có nhiều tiêu chí tìm kiếm hơn bằng cách chọn một số thuộc tính của một yếu tố, chẳng hạn như một người tên cuối cùng. Điều này được gọi là tìm kiếm bởi khóa vì bạn chọn một hoặc nhiều thuộc tính để so sánh. Trước khi bạn đi sâu vào tìm kiếm nhị phân ở Python, hãy để xem nhanh các thuật toán tìm kiếm khác để có được một bức tranh lớn hơn và hiểu cách chúng hoạt động.searching by key because you pick one or more attributes to compare. Before you dive into binary search in Python, let’s take a quick look at other search algorithms to get a bigger picture and understand how they work. Tìm kiếm ngẫu nhiênLàm thế nào bạn có thể tìm kiếm thứ gì đó trong ba lô của bạn? Bạn có thể chỉ cần đào tay vào đó, chọn một vật phẩm một cách ngẫu nhiên và xem nó có phải là thứ bạn muốn không. Nếu bạn không gặp may, thì bạn đặt vật phẩm trở lại, rửa sạch và lặp lại. Ví dụ này là một cách tốt để hiểu tìm kiếm ngẫu nhiên, đây là một trong những thuật toán tìm kiếm ít hiệu quả nhất. Sự kém hiệu quả của phương pháp này bắt nguồn từ thực tế là bạn đang có nguy cơ chọn điều tương tự nhiều lần.random search, which is one of the least efficient search algorithms. The inefficiency of this approach stems from the fact that you’re running the risk of picking the same wrong thing multiple times. Nguyên tắc cơ bản của thuật toán này có thể được thể hiện với đoạn mã Python sau:
Các vòng lặp hàm cho đến khi một số phần tử được chọn ngẫu nhiên khớp với giá trị được đưa ra dưới dạng đầu vào. Tuy nhiên, điều này rất hữu ích vì hàm trả về 2 ngầm hoặc cùng một giá trị mà nó đã nhận được trong một tham số. Bạn có thể tìm thấy việc triển khai đầy đủ trong mã mẫu có sẵn để tải xuống tại liên kết bên dưới:Đối với các bộ dữ liệu bằng kính hiển vi, thuật toán tìm kiếm ngẫu nhiên dường như đang thực hiện công việc của mình nhanh chóng: >>>
Tuy nhiên, hãy tưởng tượng phải tìm kiếm như vậy thông qua hàng triệu yếu tố! Tại đây, một bản tóm tắt nhanh chóng của một bài kiểm tra hiệu suất đã được thực hiện dựa trên bộ dữ liệu IMDB:
Các yếu tố duy nhất tại các vị trí bộ nhớ khác nhau được chọn cụ thể để tránh sai lệch. Mỗi thuật ngữ được tìm kiếm mười lần để tính đến tính ngẫu nhiên của thuật toán và các yếu tố khác như thu thập rác hoặc quy trình hệ thống chạy trong nền. Thuật toán có hiệu suất không xác định. Mặc dù thời gian trung bình để tìm một yếu tố không phụ thuộc vào nơi ở của nó, thời gian tốt nhất và tồi tệ nhất là hai đến ba bậc độ lớn. Nó cũng bị hành vi không nhất quán. Cân nhắc có một bộ sưu tập các yếu tố chứa một số bản sao. Bởi vì thuật toán chọn các yếu tố một cách ngẫu nhiên, nên nó chắc chắn sẽ trả lại các bản sao khác nhau khi chạy tiếp theo.non-deterministic performance. While the average time to find an element doesn’t depend on its whereabouts, the best and worst times are two to three orders of magnitude apart. It also suffers from inconsistent behavior. Consider having a collection of elements containing some duplicates. Because the algorithm picks elements at random, it’ll inevitably return different copies upon subsequent runs. Làm thế nào bạn có thể cải thiện về điều này? Một cách để giải quyết cả hai vấn đề cùng một lúc là sử dụng tìm kiếm tuyến tính.linear search. Tìm kiếm tuyến tínhKhi bạn quyết định những gì cần có cho bữa trưa, bạn có thể nhìn xung quanh thực đơn một cách hỗn loạn cho đến khi một cái gì đó bắt mắt bạn. Ngoài ra, bạn có thể thực hiện một cách tiếp cận có hệ thống hơn bằng cách quét menu từ trên xuống dưới và xem xét kỹ lưỡng mọi mục trong một chuỗi. Đó là tìm kiếm tuyến tính một cách ngắn gọn. Để thực hiện nó trong Python, bạn có thể 9 các yếu tố để theo dõi chỉ số phần tử hiện tại:sequence. That’s linear search in a nutshell. To implement it in Python, you could
9 elements to keep track of the current element’s index:
Các vòng lặp chức năng trên một tập hợp các phần tử theo thứ tự được xác định trước và nhất quán. Nó dừng lại khi phần tử được tìm thấy, hoặc khi không có nhiều yếu tố để kiểm tra. Chiến lược này đảm bảo rằng không có yếu tố nào được truy cập nhiều lần vì bạn đã đi qua chúng theo thứ tự bằng 00.Hãy để xem các cảnh sát tìm kiếm tuyến tính với bộ dữ liệu IMDB bạn đã sử dụng tốt như thế nào trước đây:
5 15 16Có hầu như không có bất kỳ phương sai nào trong thời gian tra cứu của một yếu tố riêng lẻ. Thời gian trung bình gần như giống như tốt nhất và tồi tệ nhất. Vì các yếu tố luôn được duyệt theo cùng một thứ tự, số lượng so sánh cần thiết để tìm cùng một yếu tố không thay đổi.linear function, which is where the name of the algorithm comes from. You can assume that, on average, the time required to find any element using a linear search will be proportional to the number of all elements in the collection. They don’t scale well as the amount of data to search increases. Tuy nhiên, thời gian tra cứu tăng lên với chỉ số ngày càng tăng của một yếu tố trong bộ sưu tập. Phần tử càng xa từ đầu danh sách, càng nhiều so sánh phải chạy. Trong trường hợp xấu nhất, khi thiếu phần tử, toàn bộ bộ sưu tập phải được kiểm tra để đưa ra câu trả lời xác định.preprocessing the data. In such a case, the benefits of preprocessing wouldn’t pay back its cost. Khi bạn chiếu dữ liệu thử nghiệm lên một lô và kết nối các dấu chấm, thì bạn sẽ ngay lập tức thấy mối quan hệ giữa vị trí phần tử và thời gian cần tìm nó: Tất cả các mẫu nằm trên một đường thẳng và có thể được mô tả bởi một hàm tuyến tính, đó là nơi tên của thuật toán đến từ. Bạn có thể giả định rằng, trung bình, thời gian cần thiết để tìm bất kỳ yếu tố nào sử dụng tìm kiếm tuyến tính sẽ tỷ lệ thuận với số lượng của tất cả các phần tử trong bộ sưu tập. Họ không có quy mô tốt như số lượng dữ liệu để tìm kiếm tăng. 0Ví dụ, máy quét sinh trắc học có sẵn tại một số sân bay sẽ nhận ra hành khách trong vài giây, nếu họ được thực hiện bằng cách sử dụng tìm kiếm tuyến tính. Mặt khác, thuật toán tìm kiếm tuyến tính có thể là một lựa chọn tốt cho các bộ dữ liệu nhỏ hơn, bởi vì nó không yêu cầu tiền xử lý dữ liệu. Trong trường hợp như vậy, lợi ích của việc tiền xử lý sẽ trả lại chi phí của nó. Tất cả các mẫu nằm trên một đường thẳng và có thể được mô tả bởi một hàm tuyến tính, đó là nơi tên của thuật toán đến từ. Bạn có thể giả định rằng, trung bình, thời gian cần thiết để tìm bất kỳ yếu tố nào sử dụng tìm kiếm tuyến tính sẽ tỷ lệ thuận với số lượng của tất cả các phần tử trong bộ sưu tập. Họ không có quy mô tốt như số lượng dữ liệu để tìm kiếm tăng. 1Ví dụ, máy quét sinh trắc học có sẵn tại một số sân bay sẽ nhận ra hành khách trong vài giây, nếu họ được thực hiện bằng cách sử dụng tìm kiếm tuyến tính. Mặt khác, thuật toán tìm kiếm tuyến tính có thể là một lựa chọn tốt cho các bộ dữ liệu nhỏ hơn, bởi vì nó không yêu cầu tiền xử lý dữ liệu. Trong trường hợp như vậy, lợi ích của việc tiền xử lý sẽ trả lại chi phí của nó. Python đã được vận chuyển với tìm kiếm tuyến tính, vì vậy, không có điểm nào trong việc tự viết nó. Ví dụ, cấu trúc dữ liệu 17 hiển thị một phương thức sẽ trả về chỉ mục của một phần tử hoặc nêu ra một ngoại lệ khác:Tất cả các mẫu nằm trên một đường thẳng và có thể được mô tả bởi một hàm tuyến tính, đó là nơi tên của thuật toán đến từ. Bạn có thể giả định rằng, trung bình, thời gian cần thiết để tìm bất kỳ yếu tố nào sử dụng tìm kiếm tuyến tính sẽ tỷ lệ thuận với số lượng của tất cả các phần tử trong bộ sưu tập. Họ không có quy mô tốt như số lượng dữ liệu để tìm kiếm tăng. 2Ví dụ, máy quét sinh trắc học có sẵn tại một số sân bay sẽ nhận ra hành khách trong vài giây, nếu họ được thực hiện bằng cách sử dụng tìm kiếm tuyến tính. Mặt khác, thuật toán tìm kiếm tuyến tính có thể là một lựa chọn tốt cho các bộ dữ liệu nhỏ hơn, bởi vì nó không yêu cầu tiền xử lý dữ liệu. Trong trường hợp như vậy, lợi ích của việc tiền xử lý sẽ trả lại chi phí của nó. Python đã được vận chuyển với tìm kiếm tuyến tính, vì vậy, không có điểm nào trong việc tự viết nó. Ví dụ, cấu trúc dữ liệu 17 hiển thị một phương thức sẽ trả về chỉ mục của một phần tử hoặc nêu ra một ngoại lệ khác:Tôi nhớ mình đã nghĩ cho bản thân mình vào thời điểm đó rằng người đã viết phần mềm đó rõ ràng không biết về thuật toán tìm kiếm nhị phân!binary search algorithm! Tìm kiếm nhị phânTừ nhị phân thường được liên kết với số 2. Trong bối cảnh này, nó đề cập đến việc chia một tập hợp các phần tử thành hai nửa và vứt bỏ một trong số chúng ở mỗi bước của thuật toán. Điều này có thể làm giảm đáng kể số lượng so sánh cần thiết để tìm một yếu tố. Nhưng có một yếu tố đánh bắt trong bộ sưu tập phải được sắp xếp trước.binary is generally associated with the number 2. In this context, it refers to dividing a collection of elements into two halves and throwing away one of them at each step of the algorithm. This can dramatically reduce the number of comparisons required to find an element. But there’s a catch—elements in the collection must be sorted first. Ý tưởng đằng sau nó giống với các bước để tìm một trang trong một cuốn sách. Lúc đầu, bạn thường mở cuốn sách đến một trang hoàn toàn ngẫu nhiên hoặc ít nhất là một trang gần với nơi bạn nghĩ rằng trang mong muốn của bạn có thể. Thỉnh thoảng, bạn sẽ may mắn tìm thấy trang đó trong lần thử đầu tiên. Tuy nhiên, nếu số trang quá thấp, thì bạn biết trang phải ở bên phải. Nếu bạn vượt quá mức thử tiếp theo và số trang hiện tại cao hơn trang mà bạn đang tìm kiếm, thì bạn biết chắc chắn rằng nó phải ở đâu đó ở giữa. Bạn lặp lại quy trình, nhưng thay vì chọn một trang một cách ngẫu nhiên, bạn kiểm tra trang nằm ngay giữa phạm vi mới đó. Điều này giảm thiểu số lượng thử. Một cách tiếp cận tương tự có thể được sử dụng trong trò chơi đoán số. Nếu bạn đã nghe nói về trò chơi đó, thì bạn có thể tìm kiếm nó trên internet để có được rất nhiều ví dụ được thực hiện trong Python.middle of that new range. This minimizes the number of tries. A similar approach can be used in the number guessing game. If you haven’t heard of that game, then you can look it up on the Internet to get a plethora of examples implemented in Python. Các số trang hạn chế phạm vi của các trang để tìm kiếm qua được gọi là giới hạn dưới và giới hạn trên. Trong tìm kiếm nhị phân, bạn thường bắt đầu với trang đầu tiên là giới hạn dưới và trang cuối cùng là giới hạn trên. Bạn phải cập nhật cả hai giới hạn khi bạn đi. Ví dụ: nếu trang bạn chuyển sang thấp hơn trang mà bạn đang tìm kiếm, thì đó là giới hạn dưới mới của bạn.lower bound and the upper bound. In binary search, you commonly start with the first page as the lower bound and the last page as the upper bound. You must update both bounds as you go. For example, if the page you turn to is lower than the one you’re looking for, then that’s your new lower bound. Hãy nói rằng bạn đang tìm kiếm một quả dâu trong một bộ sưu tập các loại trái cây được sắp xếp theo thứ tự tăng dần theo kích thước: Trong lần thử đầu tiên, phần tử ở giữa xảy ra là một quả chanh. Vì nó lớn hơn một quả dâu tây, bạn có thể loại bỏ tất cả các yếu tố ở bên phải, bao gồm cả chanh. Bạn sẽ di chuyển ràng buộc trên đến một vị trí mới và cập nhật chỉ số giữa: Bây giờ, bạn đã rời đi chỉ với một nửa số trái cây mà bạn bắt đầu. Yếu tố trung gian hiện tại thực sự là quả dâu tây mà bạn đang tìm kiếm, kết luận tìm kiếm. Nếu đó không phải là người, thì bạn chỉ cần cập nhật giới hạn cho đến khi họ vượt qua nhau. Ví dụ, tìm kiếm một mận còn thiếu, sẽ đi giữa dâu tây và kiwi, sẽ kết thúc với kết quả sau: Lưu ý rằng có nhiều so sánh phải được thực hiện để tìm ra yếu tố mong muốn. Đó là sự kỳ diệu của tìm kiếm nhị phân. Ngay cả khi bạn đang xử lý một triệu yếu tố, bạn cũng chỉ yêu cầu nhiều nhất một số kiểm tra. Con số này đã giành được vượt quá cơ sở logarit hai trong tổng số phần tử do giảm một nửa. Nói cách khác, số lượng các yếu tố còn lại được giảm một nửa ở mỗi bước.logarithm base two of the total number of elements due to halving. In other words, the number of remaining elements is reduced by half at each step. Điều này là có thể bởi vì các yếu tố đã được sắp xếp theo kích thước. Tuy nhiên, nếu bạn muốn tìm trái cây bằng một chìa khóa khác, chẳng hạn như một màu, thì bạn phải sắp xếp toàn bộ bộ sưu tập một lần nữa. Để tránh chi phí đắt tiền của việc phân loại, bạn có thể cố gắng tính toán các chế độ xem khác nhau của cùng một bộ sưu tập trước. Điều này có phần giống với việc tạo một chỉ mục cơ sở dữ liệu.database index. Xem xét những gì xảy ra nếu bạn thêm, xóa hoặc cập nhật một phần tử trong bộ sưu tập. Để tìm kiếm nhị phân để tiếp tục hoạt động, bạn cần phải duy trì thứ tự sắp xếp thích hợp. Điều này có thể được thực hiện với mô -đun 1 mà bạn sẽ đọc trong phần sắp tới.Bạn sẽ thấy cách thực hiện thuật toán tìm kiếm nhị phân trong Python sau này trong hướng dẫn này. Hiện tại, hãy để đối mặt với nó với bộ dữ liệu IMDB. Lưu ý rằng có những người khác nhau để tìm kiếm hơn trước. Điều đó bởi vì bộ dữ liệu phải được sắp xếp để tìm kiếm nhị phân, sắp xếp lại các yếu tố. Các yếu tố mới được đặt gần đúng với các chỉ số như trước đây, để giữ cho các phép đo có thể so sánh được:
Các câu trả lời gần như tức thời. Trong trường hợp trung bình, chỉ mất một vài micro giây để tìm kiếm nhị phân để tìm một yếu tố trong số chín triệu! Ngoài ra, số lượng so sánh cho các phần tử được chọn vẫn gần như không đổi, trùng với công thức sau: Tìm hầu hết các yếu tố sẽ yêu cầu số lượng so sánh cao nhất, có thể được lấy từ logarit có kích thước của bộ sưu tập. Ngược lại, có một yếu tố ở giữa có thể được tìm thấy trong lần thử đầu tiên với một so sánh. Tìm kiếm nhị phân là một ví dụ tuyệt vời về kỹ thuật phân chia và chinh phục, phân chia một vấn đề thành một loạt các vấn đề nhỏ hơn cùng loại. Các giải pháp riêng lẻ sau đó được kết hợp để hình thành câu trả lời cuối cùng. Một ví dụ nổi tiếng khác về kỹ thuật này là thuật toán Quicksort.divide-and-conquer technique, which partitions one problem into a bunch of smaller problems of the same kind. The individual solutions are then combined to form the final answer. Another well-known example of this technique is the Quicksort algorithm. Không giống như các thuật toán tìm kiếm khác, tìm kiếm nhị phân có thể được sử dụng ngoài việc chỉ tìm kiếm. Ví dụ, nó cho phép đặt thử nghiệm thành viên, tìm giá trị lớn nhất hoặc nhỏ nhất, tìm người hàng xóm gần nhất của giá trị mục tiêu, thực hiện các truy vấn phạm vi và hơn thế nữa. Nếu tốc độ là ưu tiên hàng đầu, thì tìm kiếm nhị phân không phải lúc nào cũng là lựa chọn tốt nhất. Thậm chí có các thuật toán nhanh hơn có thể tận dụng các cấu trúc dữ liệu dựa trên băm. Tuy nhiên, các thuật toán đó đòi hỏi rất nhiều bộ nhớ bổ sung, trong khi tìm kiếm nhị phân cung cấp một sự đánh đổi không gian tốt. Tìm kiếm dựa trên bămĐể tìm kiếm nhanh hơn, bạn cần thu hẹp không gian vấn đề. Tìm kiếm nhị phân đạt được mục tiêu đó bằng cách giảm một nửa số lượng ứng cử viên ở mỗi bước. Điều đó có nghĩa là ngay cả khi bạn có một triệu yếu tố, phải mất nhiều nhất hai mươi so sánh để xác định xem phần tử có mặt hay không, với điều kiện là tất cả các yếu tố được sắp xếp.problem space. Binary search achieves that goal by halving the number of candidates at each step. That means that even if you have one million elements, it takes at most twenty comparisons to determine if the element is present, provided that all elements are sorted. Cách nhanh nhất để tìm kiếm là biết nơi để tìm những gì bạn đang tìm kiếm. Nếu bạn biết vị trí bộ nhớ chính xác của một phần tử, thì bạn sẽ truy cập trực tiếp vào nó mà không cần tìm kiếm ngay từ đầu. Ánh xạ một phần tử hoặc (phổ biến hơn) một trong các phím của nó vào vị trí phần tử trong bộ nhớ được gọi là băm.hashing. Bạn có thể nghĩ rằng băm không phải là tìm kiếm phần tử cụ thể, mà thay vào đó tính toán chỉ mục dựa trên chính phần tử. Đó là công việc của một hàm băm, cần giữ các thuộc tính toán học nhất định. Một hàm băm tốt nên:hash function, which needs to hold certain mathematical properties. A good hash function should:
Đồng thời, nó không nên quá tốn kém về mặt tính toán, nếu không thì chi phí của nó sẽ vượt xa lợi nhuận. Chức năng băm cũng được sử dụng để xác minh tính toàn vẹn dữ liệu cũng như trong mật mã. Cấu trúc dữ liệu sử dụng khái niệm này để ánh xạ các phím thành các giá trị được gọi là bản đồ, bảng băm, từ điển hoặc mảng kết hợp.map, a hash table, a dictionary, or an associative array. Một cách khác để trực quan hóa băm là tưởng tượng cái gọi là xô của các yếu tố tương tự được nhóm lại dưới các khóa tương ứng của chúng. Ví dụ: bạn có thể thu hoạch trái cây thành các thùng khác nhau dựa trên màu sắc:buckets of similar elements grouped under their respective keys. For example, you may be harvesting fruits into different buckets based on color: Dừa và trái cây kiwi đi đến xô có nhãn màu nâu, trong khi một quả táo kết thúc trong một cái xô với nhãn màu đỏ, v.v. Điều này cho phép bạn liếc qua một phần của các yếu tố một cách nhanh chóng. Lý tưởng nhất, bạn muốn chỉ có một quả trong mỗi thùng. Nếu không, bạn có được những gì mà người Viking gọi là va chạm, dẫn đến công việc làm thêm.collision, which leads to extra work. Hãy để Lừa đặt tên từ bộ dữ liệu IMDB vào từ điển, để mỗi tên trở thành một khóa và giá trị tương ứng trở thành chỉ mục của nó: >>> 3Sau khi tải tên văn bản vào một danh sách phẳng, bạn có thể 9 nó bên trong một sự hiểu biết từ điển để tạo ánh xạ. Bây giờ, việc kiểm tra sự hiện diện của phần tử cũng như nhận chỉ số của nó là đơn giản:>>> 4Sau khi tải tên văn bản vào một danh sách phẳng, bạn có thể 9 nó bên trong một sự hiểu biết từ điển để tạo ánh xạ. Bây giờ, việc kiểm tra sự hiện diện của phần tử cũng như nhận chỉ số của nó là đơn giản:Nhờ chức năng băm được sử dụng đằng sau hậu trường, bạn không phải thực hiện bất kỳ tìm kiếm nào!
33Alicia Monica 7hashable, and their hash values can’t change over time. You can check if a particular data type is hashable in Python by calling 46 on it:>>> 5Sau khi tải tên văn bản vào một danh sách phẳng, bạn có thể 9 nó bên trong một sự hiểu biết từ điển để tạo ánh xạ. Bây giờ, việc kiểm tra sự hiện diện của phần tử cũng như nhận chỉ số của nó là đơn giản:immutable because their hash value often depends on some attributes of the key. If a mutable collection was hashable and could be used as a key, then its hash value would be different every time the contents changed. Consider what would happen if a particular fruit changed color due to
ripening. You’d be looking for it in the wrong bucket!Hàm băm có nhiều cách sử dụng khác. Ví dụ, nó được sử dụng trong mật mã để tránh lưu trữ mật khẩu ở dạng văn bản thuần túy, cũng như để xác minh tính toàn vẹn dữ liệu. Sử dụng mô -đun import random def find(elements, value): while True: random_element = random.choice(elements) if random_element == value: return random_element 1Tìm kiếm nhị phân trong Python có thể được thực hiện bằng mô-đun 1 tích hợp, cũng giúp bảo tồn danh sách theo thứ tự được sắp xếp. Nó dựa trên phương pháp chia đôi để tìm rễ của các chức năng. Mô -đun này đi kèm với sáu chức năng được chia thành hai loại:
Các chức năng này cho phép bạn tìm một chỉ mục của một phần tử hoặc thêm một phần tử mới ở đúng vị trí. Những người trong hàng đầu tiên chỉ là bí danh cho 56 và 57, tương ứng. Trong thực tế, bạn chỉ xử lý bốn chức năng.Không có gì khó chịu, hãy để Lừa xem mô -đun 1 hoạt động.Tìm một yếu tốĐể tìm chỉ mục của một phần tử hiện có trong danh sách được sắp xếp, bạn muốn 54:>>> 6Đầu ra cho bạn biết rằng một quả chuối là loại trái cây thứ hai trong danh sách vì nó được tìm thấy tại Index 62. Tuy nhiên, nếu thiếu phần tử, thì bạn vẫn có được vị trí dự kiến:
>>> 7Đầu ra cho bạn biết rằng một quả chuối là loại trái cây thứ hai trong danh sách vì nó được tìm thấy tại Index 62. Tuy nhiên, nếu thiếu phần tử, thì bạn vẫn có được vị trí dự kiến:
Là giá trị của phần tử là một phần tử mong muốn? 8Điều này có thể được dịch sang một hàm phổ quát để tìm các yếu tố theo giá trị: Khi có một trận đấu, hàm sẽ trả về chỉ mục phần tử tương ứng. Nếu không, nó sẽ trả lại 2 ngầm. 9Để tìm kiếm theo khóa, bạn phải duy trì một danh sách các khóa riêng. Vì điều này phải chịu thêm một chi phí, nên nó có giá trị để tính toán các phím lên phía trước và tái sử dụng chúng càng nhiều càng tốt. Bạn có thể xác định một lớp trợ giúp để có thể tìm kiếm bằng các khóa khác nhau mà không cần giới thiệu nhiều sao chép mã: Khóa là một hàm được truyền dưới dạng tham số đầu tiên cho 64. Khi bạn có nó, bạn lập một danh sách các cặp giá trị khóa để có thể lấy một phần tử từ khóa của nó sau đó. Đại diện cho các cặp với các bộ dữ liệu đảm bảo rằng phần tử đầu tiên của mỗi cặp sẽ được sắp xếp. Trong bước tiếp theo, bạn trích xuất các khóa để tạo một danh sách phẳng mà phù hợp với việc triển khai Python tìm kiếm nhị phân của bạn. 0Sau đó, có phương pháp thực tế để tìm các yếu tố theo khóa: Mã này chia đôi danh sách các khóa được sắp xếp để lấy chỉ mục của một phần tử theo khóa. Nếu một khóa như vậy tồn tại, thì chỉ mục của nó có thể được sử dụng để lấy cặp tương ứng từ danh sách được tính toán trước đó các cặp giá trị khóa. Yếu tố thứ hai của cặp đó là giá trị mong muốn. >>> 1Đầu ra cho bạn biết rằng một quả chuối là loại trái cây thứ hai trong danh sách vì nó được tìm thấy tại Index 62. Tuy nhiên, nếu thiếu phần tử, thì bạn vẫn có được vị trí dự kiến:>>> 2Đầu ra cho bạn biết rằng một quả chuối là loại trái cây thứ hai trong danh sách vì nó được tìm thấy tại Index 62. Tuy nhiên, nếu thiếu phần tử, thì bạn vẫn có được vị trí dự kiến:>>> 3Đầu ra cho bạn biết rằng một quả chuối là loại trái cây thứ hai trong danh sách vì nó được tìm thấy tại Index 62. Tuy nhiên, nếu thiếu phần tử, thì bạn vẫn có được vị trí dự kiến:Mặc dù những loại trái cây này không có trong danh sách, bạn có thể có ý tưởng về nơi đặt chúng. Ví dụ, một quả mơ nên đến giữa táo và chuối, trong khi dưa hấu sẽ trở thành yếu tố cuối cùng. Bạn sẽ biết nếu một phần tử được tìm thấy bằng cách đánh giá hai điều kiện:Là chỉ mục trong kích thước của danh sách? >>> 4Đầu ra cho bạn biết rằng một quả chuối là loại trái cây thứ hai trong danh sách vì nó được tìm thấy tại Index 62. Tuy nhiên, nếu thiếu phần tử, thì bạn vẫn có được vị trí dự kiến:duplicates in your list. But even then, it won’t become apparent as long as
those duplicates are simple values. Adding another banana to the left will have the same effect as adding it to the right.Mặc dù những loại trái cây này không có trong danh sách, bạn có thể có ý tưởng về nơi đặt chúng. Ví dụ, một quả mơ nên đến giữa táo và chuối, trong khi dưa hấu sẽ trở thành yếu tố cuối cùng. Bạn sẽ biết nếu một phần tử được tìm thấy bằng cách đánh giá hai điều kiện:unique identities despite having equal values. Let’s define a 71 type using the @dataclass decorator,
which was introduced in Python 3.7: 5Là chỉ mục trong kích thước của danh sách? >>> 6Đầu ra cho bạn biết rằng một quả chuối là loại trái cây thứ hai trong danh sách vì nó được tìm thấy tại Index 62. Tuy nhiên, nếu thiếu phần tử, thì bạn vẫn có được vị trí dự kiến:>>> 7Các biến 75 và 76 thực sự là các đối tượng khác nhau.Lưu ý rằng các trường hợp của một lớp dữ liệu aren có thể so sánh theo mặc định, điều này ngăn bạn sử dụng thuật toán chia đôi trên chúng: >>> 8Python không biết đặt hàng 77 và 78, bởi vì chúng là đối tượng của một lớp tùy chỉnh. Theo truyền thống, bạn đã thực hiện phương pháp ma thuật 79 trong lớp của bạn, viết tắt của ít hơn, để nói với thông dịch viên cách so sánh các yếu tố đó. Tuy nhiên, người trang trí 80 chấp nhận một vài lá cờ Boolean tùy chọn. Một trong số đó là 81, dẫn đến việc tạo ra các phương thức ma thuật tự động để so sánh khi được đặt thành 82:less than, to tell the interpreter how to compare such elements. However, the 80 decorator accepts a few optional Boolean flags. One of them is 81, which results in an automatic generation of the magic methods for comparison when set to 82: 9Đổi lại, điều này cho phép bạn so sánh hai người và quyết định cái nào đến trước: >>> 0Cuối cùng, bạn có thể tận dụng các thuộc tính 72 và 73 để quan sát nơi các chức năng khác nhau chèn người mới vào danh sách:>>> 1Các số trong ngoặc đơn sau các tên biểu thị thứ tự chèn. Ban đầu, chỉ có một 85, người có số 62. Sau đó, bạn đã thêm bản sao của nó vào bên trái, và sau đó một cái nữa ở bên phải.Thực hiện tìm kiếm nhị phân trong PythonHãy nhớ rằng có lẽ bạn không nên thực hiện thuật toán trừ khi bạn có lý do mạnh mẽ. Bạn có thể tiết kiệm thời gian và giành chiến thắng cần phải phát minh lại bánh xe. Cơ hội là mã thư viện đã trưởng thành, đã được người dùng thực kiểm tra trong môi trường sản xuất và có chức năng rộng rãi được cung cấp bởi nhiều người đóng góp. Điều đó nói rằng, có những lúc nó có ý nghĩa khi cuộn tay áo lên và tự làm điều đó. Công ty của bạn có thể có một chính sách cấm một số thư viện nguồn mở do các vấn đề cấp phép hoặc bảo mật. Có lẽ bạn có thể đủ khả năng phụ thuộc khác do các ràng buộc băng thông mạng hoặc mạng. Cuối cùng, tự viết mã có thể là một công cụ học tập tuyệt vời! Bạn có thể thực hiện hầu hết các thuật toán theo hai cách:
Tuy nhiên, có những trường hợp ngoại lệ cho quy tắc đó. Một ví dụ đáng chú ý là hàm Ackermann, chỉ có thể được thể hiện dưới dạng đệ quy. Trước khi bạn đi xa hơn, hãy chắc chắn rằng bạn có một nắm bắt tốt về thuật toán tìm kiếm nhị phân. Bạn có thể tham khảo một phần trước của hướng dẫn này để được bồi dưỡng nhanh. Lặp đi lặp lạiĐệ quysearch elements by value and return their index: 2Tuy nhiên, có những trường hợp ngoại lệ cho quy tắc đó. Một ví dụ đáng chú ý là hàm Ackermann, chỉ có thể được thể hiện dưới dạng đệ quy. Trước khi bạn đi xa hơn, hãy chắc chắn rằng bạn có một nắm bắt tốt về thuật toán tìm kiếm nhị phân. Bạn có thể tham khảo một phần trước của hướng dẫn này để được bồi dưỡng nhanh. 3Phiên bản lặp của thuật toán liên quan đến một vòng lặp, sẽ lặp lại một số bước cho đến khi điều kiện dừng được đáp ứng. Hãy bắt đầu bằng cách thực hiện một chức năng sẽ tìm kiếm các yếu tố theo giá trị và trả về chỉ mục của chúng: 4Bạn sẽ sử dụng lại chức năng này sau này.integer division helps to handle both an odd and even number of elements in the bounded range by flooring the result. Depending on how you’re going to update the boundaries and define the stopping condition, you could also use a ceiling function. Giả sử rằng tất cả các yếu tố được sắp xếp, bạn có thể đặt các ranh giới dưới và trên ở hai đầu đối diện của chuỗi: 5Bây giờ, bạn muốn xác định phần tử giữa để xem nó có giá trị mong muốn không. Tính toán chỉ số giữa có thể được thực hiện bằng cách lấy trung bình của cả hai ranh giới: Lưu ý cách phân chia số nguyên giúp xử lý cả số phần tử và số lượng các phần tử trong phạm vi giới hạn bằng cách đưa ra kết quả. Tùy thuộc vào cách bạn sẽ cập nhật các ranh giới và xác định điều kiện dừng, bạn cũng có thể sử dụng chức năng trần. 6Tiếp theo, bạn hoàn thành hoặc chia chuỗi thành hai và tiếp tục tìm kiếm trong một nửa kết quả: Nếu phần tử ở giữa là một trận đấu, thì bạn sẽ trả về chỉ mục của nó. Nếu không, nếu nó quá nhỏ, thì bạn cần di chuyển ranh giới dưới. Nếu nó quá lớn, thì bạn cần di chuyển ranh giới trên xuống. boils down to looking at an object’s attributes instead of its literal value. A key could be the number of characters in a fruit’s name, for example. You can adapt 88 to accept and use a 89 parameter: 7Để tiếp tục, bạn phải đặt hầu hết các bước trong một vòng lặp, điều này sẽ dừng lại khi ranh giới dưới đây vượt qua bước trên: >>> 8Nói cách khác, bạn muốn lặp lại miễn là ranh giới dưới nằm dưới hoặc bằng với phần trên. Mặt khác, không có khớp và chức năng trả về 2 ngầm.Tìm kiếm bởi chính tập trung vào việc nhìn vào một thuộc tính đối tượng thay vì giá trị theo nghĩa đen của nó. Một chìa khóa có thể là số lượng ký tự trong một tên trái cây, chẳng hạn. Bạn có thể điều chỉnh 88 để chấp nhận và sử dụng tham số 89: 9Ngoài ra, bạn có thể xác định chức năng nhận dạng nội tuyến với biểu thức Lambda ẩn danh: 0 88 chỉ trả lời một câu hỏi. Vẫn còn hai người khác, đó là người ở đó? và nó là gì?" Để trả lời hai điều này, bạn có thể xây dựng trên đầu nó: 1Với ba chức năng này, bạn có thể nói hầu hết mọi thứ về một yếu tố. Tuy nhiên, bạn vẫn chưa giải quyết các bản sao trong việc thực hiện của bạn. Điều gì sẽ xảy ra nếu bạn có một bộ sưu tập người, và một số trong số họ đã chia sẻ một tên hoặc họ chung? Ví dụ, có thể có một gia đình 96 hoặc một vài người đi theo tên của 85 trong số những người:duplicates in your implementation. What if you had a collection of people, and
some of them shared a common name or surname? For example, there might be a 96 family or a few guys going by the name of 85 among the people: 2Để mô hình hóa loại 71, bạn có thể sửa đổi lớp dữ liệu được xác định trước đó: 3Lưu ý rằng việc sử dụng thuộc tính 81 để cho phép tạo các phương thức ma thuật tự động để so sánh các trường hợp của lớp với tất cả các trường. Ngoài ra, bạn có thể thích tận dụng lợi thế của 00, có cú pháp ngắn hơn: 4Cả hai định nghĩa đều ổn và có thể hoán đổi cho nhau. Mỗi người có thuộc tính 72 và 02. Để sắp xếp và tìm kiếm theo một trong số chúng, bạn có thể xác định thuận tiện chức năng khóa với 03 có sẵn trong mô-đun 04 tích hợp:>>> 5Lưu ý cách mọi người được sắp xếp theo họ theo thứ tự tăng dần. Có 05 và 06, nhưng tìm kiếm nhị phân cho họ 96 hiện chỉ cung cấp cho bạn một kết quả tùy ý:>>> 6Lưu ý cách mọi người được sắp xếp theo họ theo thứ tự tăng dần. Có 05 và 06, nhưng tìm kiếm nhị phân cho họ 96 hiện chỉ cung cấp cho bạn một kết quả tùy ý:leftmost instance of a duplicate element, you want to determine if
there’s such an element at all: 7Để bắt chước các tính năng của mô -đun 1 được hiển thị trước đó, bạn có thể viết phiên bản 54 và 56 của riêng mình. Trước khi tìm thấy phiên bản ngoài cùng bên trái của một yếu tố trùng lặp, bạn muốn xác định xem có phải là một yếu tố như vậy không: 8Nếu một số chỉ mục đã được tìm thấy, thì bạn có thể nhìn sang bên trái và tiếp tục di chuyển cho đến khi bạn bắt gặp một yếu tố có khóa khác hoặc không có nhiều yếu tố nữa: Khi bạn đi qua phần tử ngoài cùng bên trái, bạn cần di chuyển chỉ mục trở lại một vị trí sang bên phải.rightmost instance is quite similar, but you need to flip the conditions: 9Tìm trường hợp ngoài cùng bên phải là khá giống nhau, nhưng bạn cần phải lật các điều kiện:all occurrences of duplicate items: 0Thay vì đi bên trái, bây giờ bạn sẽ đi bên phải cho đến khi kết thúc danh sách. Sử dụng cả hai chức năng cho phép bạn tìm thấy tất cả các mục xuất hiện của các mục trùng lặp: Hàm này luôn trả về một bộ. Nếu phần tử được tìm thấy, thì bộ sẽ trống. Nếu phần tử là duy nhất, thì tập hợp sẽ được tạo thành chỉ một chỉ mục. Nếu không, sẽ có nhiều chỉ số trong tập hợp. 1Để kết thúc, bạn có thể xác định các chức năng trừu tượng hơn nữa để hoàn thành Thư viện Python tìm kiếm nhị phân của mình:
19Mã hoàn chỉnh của thư viện Python tìm kiếm nhị phân này có thể được tìm thấy tại liên kết bên dưới:Đệ quyrecursive version of 11, which tells you if an element was found.Để đơn giản, bạn sẽ chỉ xem xét phiên bản đệ quy của 11, cho bạn biết nếu một phần tử được tìm thấy. 2Cách tiếp cận đơn giản nhất là lấy phiên bản lặp lại của tìm kiếm nhị phân và sử dụng toán tử cắt lát để cắt danh sách:copies of element references, which can have noticeable memory and computational overhead. Thay vì lặp lại, bạn kiểm tra điều kiện một lần và đôi khi gọi cùng một hàm trong danh sách nhỏ hơn. Điều gì có thể sai với điều đó? Chà, hóa ra việc cắt lát tạo ra các bản sao của các tài liệu tham khảo phần tử, có thể có bộ nhớ và chi phí tính toán đáng chú ý. 3Để tránh sao chép, bạn có thể sử dụng lại cùng một danh sách nhưng chuyển các ranh giới khác nhau vào chức năng bất cứ khi nào cần thiết: >>> 4Lưu ý cách mọi người được sắp xếp theo họ theo thứ tự tăng dần. Có 05 và 06, nhưng tìm kiếm nhị phân cho họ 96 hiện chỉ cung cấp cho bạn một kết quả tùy ý: 5Để bắt chước các tính năng của mô -đun 1 được hiển thị trước đó, bạn có thể viết phiên bản 54 và 56 của riêng mình. Trước khi tìm thấy phiên bản ngoài cùng bên trái của một yếu tố trùng lặp, bạn muốn xác định xem có phải là một yếu tố như vậy không: 6Nếu một số chỉ mục đã được tìm thấy, thì bạn có thể nhìn sang bên trái và tiếp tục di chuyển cho đến khi bạn bắt gặp một yếu tố có khóa khác hoặc không có nhiều yếu tố nữa:LEGB rule, which tells the interpreter to look for symbols in the following order:
Điều này cho phép các biến được xác định trong phạm vi bên ngoài được truy cập từ trong các khối mã lồng nhau. Sự lựa chọn giữa một lần lặp lại và thực hiện đệ quy thường là kết quả ròng của các cân nhắc về hiệu suất, sự tiện lợi, cũng như sở thích cá nhân. Tuy nhiên, cũng có những rủi ro nhất định liên quan đến đệ quy, đó là một trong những chủ đề của phần tiếp theo. Bao gồm các chi tiết khó khănTại đây, những gì tác giả của nghệ thuật lập trình máy tính nói về việc thực hiện thuật toán tìm kiếm nhị phân:
Nếu điều đó không ngăn cản bạn đủ từ ý tưởng tự viết thuật toán, thì có lẽ điều này sẽ xảy ra. Thư viện tiêu chuẩn trong Java đã có một lỗi tinh tế trong việc thực hiện tìm kiếm nhị phân, vẫn chưa được khám phá trong một thập kỷ! Nhưng bản thân lỗi theo dõi nguồn gốc của nó sớm hơn thế nhiều. Danh sách sau đây không đầy đủ, nhưng đồng thời, nó không nói về những sai lầm phổ biến như quên sắp xếp danh sách. Tràn số nguyênĐây là lỗi Java vừa được đề cập. Nếu bạn nhớ lại, thuật toán Python tìm kiếm nhị phân kiểm tra phần tử giữa của phạm vi giới hạn trong một bộ sưu tập được sắp xếp. Nhưng làm thế nào là phần tử trung gian đó được chọn chính xác? Thông thường, bạn lấy trung bình của ranh giới thấp hơn và trên để tìm chỉ số giữa: 7Phương pháp tính toán trung bình này hoạt động tốt trong phần lớn các trường hợp. Tuy nhiên, một khi việc thu thập các phần tử trở nên đủ lớn, tổng của cả hai ranh giới won won phù hợp với kiểu dữ liệu số nguyên. Nó sẽ lớn hơn giá trị tối đa được phép cho các số nguyên. Một số ngôn ngữ lập trình có thể gây ra lỗi trong các tình huống như vậy, điều này sẽ ngay lập tức dừng thực thi chương trình. Thật không may, điều đó không phải lúc nào cũng như vậy. Ví dụ, Java âm thầm bỏ qua vấn đề này, để giá trị lật xung quanh và trở thành một số dường như ngẫu nhiên. Bạn chỉ biết về vấn đề này miễn là số kết quả xảy ra là âm, ném một 24.Ở đây, một ví dụ thể hiện hành vi này trong JShell, giống như một thông dịch tương tác cho Java: 8Một cách an toàn hơn để tìm chỉ số giữa có thể tính toán phần bù trước và sau đó thêm nó vào ranh giới thấp hơn: 9Ngay cả khi cả hai giá trị được tối đa, tổng trong công thức trên sẽ không bao giờ được. Có một vài cách nữa, nhưng tin tốt là bạn không cần phải lo lắng về bất kỳ cách nào trong số này, bởi vì Python không có lỗi tràn số nguyên. Không có giới hạn trên về cách các số nguyên lớn có thể là ngoài bộ nhớ của bạn: >>> 0Tuy nhiên, có một cái bắt. Khi bạn gọi các chức năng từ thư viện, mã đó có thể phải tuân theo các ràng buộc ngôn ngữ C và vẫn gây ra tràn. Có rất nhiều thư viện dựa trên ngôn ngữ C trong Python. Bạn thậm chí có thể xây dựng mô-đun mở rộng C của riêng mình hoặc tải một thư viện được liên kết động vào Python bằng cách sử dụng 25.Stack OverflowVề mặt lý thuyết, vấn đề tràn của ngăn xếp có thể liên quan đến việc thực hiện đệ quy của tìm kiếm nhị phân. Hầu hết các ngôn ngữ lập trình áp đặt giới hạn về số lượng các cuộc gọi chức năng lồng nhau. Mỗi cuộc gọi được liên kết với một địa chỉ trả lại được lưu trữ trên một ngăn xếp. Trong Python, giới hạn mặc định là một vài nghìn cấp của các cuộc gọi như vậy:stack overflow problem may, theoretically, concern the recursive implementation of binary search. Most programming languages impose a limit on the number of nested function calls. Each call is associated with a return address stored on a stack. In Python, the default limit is a few thousand levels of such calls: >>> 1Tuy nhiên, có một cái bắt. Khi bạn gọi các chức năng từ thư viện, mã đó có thể phải tuân theo các ràng buộc ngôn ngữ C và vẫn gây ra tràn. Có rất nhiều thư viện dựa trên ngôn ngữ C trong Python. Bạn thậm chí có thể xây dựng mô-đun mở rộng C của riêng mình hoặc tải một thư viện được liên kết động vào Python bằng cách sử dụng 25.Stack Overflowinfinite recursion error to arise if the stopping condition is stated incorrectly due to a bug. In such a case, the infinite recursion will eventually cause a stack overflow. Về mặt lý thuyết, vấn đề tràn của ngăn xếp có thể liên quan đến việc thực hiện đệ quy của tìm kiếm nhị phân. Hầu hết các ngôn ngữ lập trình áp đặt giới hạn về số lượng các cuộc gọi chức năng lồng nhau. Mỗi cuộc gọi được liên kết với một địa chỉ trả lại được lưu trữ trên một ngăn xếp. Trong Python, giới hạn mặc định là một vài nghìn cấp của các cuộc gọi như vậy: >>> 2Tuy nhiên, có một cái bắt. Khi bạn gọi các chức năng từ thư viện, mã đó có thể phải tuân theo các ràng buộc ngôn ngữ C và vẫn gây ra tràn. Có rất nhiều thư viện dựa trên ngôn ngữ C trong Python. Bạn thậm chí có thể xây dựng mô-đun mở rộng C của riêng mình hoặc tải một thư viện được liên kết động vào Python bằng cách sử dụng 25.Stack OverflowVề mặt lý thuyết, vấn đề tràn của ngăn xếp có thể liên quan đến việc thực hiện đệ quy của tìm kiếm nhị phân. Hầu hết các ngôn ngữ lập trình áp đặt giới hạn về số lượng các cuộc gọi chức năng lồng nhau. Mỗi cuộc gọi được liên kết với một địa chỉ trả lại được lưu trữ trên một ngăn xếp. Trong Python, giới hạn mặc định là một vài nghìn cấp của các cuộc gọi như vậy: >>> 3Có hai quả chuối trong danh sách. Lúc đầu, cuộc gọi đến 88 trả về bên trái. Tuy nhiên, việc thêm một phần tử hoàn toàn không liên quan ở cuối danh sách làm cho cùng một cuộc gọi cung cấp cho bạn một 27 khác.Nguyên tắc tương tự, được gọi là tính ổn định của thuật toán, áp dụng cho các thuật toán sắp xếp. Một số ổn định, có nghĩa là họ không thay đổi vị trí tương đối của các yếu tố tương đương. Những người khác don lồng làm cho các đảm bảo như vậy. Nếu bạn cần sắp xếp các yếu tố theo nhiều tiêu chí, thì bạn phải luôn bắt đầu từ chìa khóa ít quan trọng nhất để giữ lại sự ổn định.algorithm stability, applies to sorting algorithms. Some are stable, meaning they don’t change the relative positions of equivalent elements. Others don’t make such guarantees. If you ever need to sort elements by multiple criteria, then you should always start from the least significant key to retain stability. Làm tròn điểm nổiCho đến nay, bạn chỉ tìm kiếm trái cây hoặc con người, nhưng những con số thì sao? Họ không nên khác nhau, phải không? Hãy cùng làm một danh sách các số điểm nổi ở mức tăng 28 bằng cách sử dụng danh sách hiểu biết:>>> 4Danh sách phải chứa các số một phần mười, hai phần mười và ba phần mười. Đáng ngạc nhiên, chỉ có hai trong số ba số đó có thể được tìm thấy: >>> 5Đây không phải là một vấn đề liên quan nghiêm trọng đến tìm kiếm nhị phân trong Python, vì tìm kiếm tuyến tính tích hợp phù hợp với nó: >>> 6Nó thậm chí không phải là một vấn đề liên quan đến Python mà là cách các số điểm nổi được thể hiện trong bộ nhớ máy tính. Điều này được xác định bởi tiêu chuẩn IEEE 754 cho số học nổi. Không đi sâu vào chi tiết, một số số thập phân don don có một đại diện hữu hạn ở dạng nhị phân. Do bộ nhớ hạn chế, những con số đó được làm tròn, gây ra lỗi làm tròn điểm nổi.floating-point rounding error. Nếu bạn cần phải làm việc với các số điểm nổi, thì bạn nên thay thế khớp chính xác bằng một so sánh gần đúng. Hãy cùng xem xét hai biến với các giá trị hơi khác nhau:approximate comparison. Let’s consider two variables with slightly different values: >>> 7So sánh thường xuyên cho kết quả âm, mặc dù cả hai giá trị gần như giống hệt nhau. May mắn thay, Python đi kèm với một chức năng sẽ kiểm tra xem hai giá trị có gần nhau trong một số khu phố nhỏ không: >>> 8Khu phố đó, đó là khoảng cách tối đa giữa các giá trị, có thể được điều chỉnh nếu cần: >>> 9Bạn có thể sử dụng chức năng đó để thực hiện tìm kiếm nhị phân trong Python theo cách sau: 0Mặt khác, việc triển khai tìm kiếm nhị phân trong Python chỉ dành riêng cho các số điểm nổi. Bạn không thể sử dụng nó để tìm kiếm bất cứ thứ gì khác mà không gặp lỗi. Phân tích độ phức tạp không gian thời gian của tìm kiếm nhị phânPhần sau đây sẽ không chứa mã và một số khái niệm toán học. Trong điện toán, bạn có thể tối ưu hóa hiệu suất của khá nhiều thuật toán với chi phí sử dụng bộ nhớ tăng. Chẳng hạn, bạn đã thấy rằng một tìm kiếm dựa trên băm của bộ dữ liệu IMDB yêu cầu thêm 0,5 GB bộ nhớ để đạt được tốc độ vô song. Ngược lại, để lưu băng thông, bạn đã nén một luồng video trước khi gửi nó qua mạng, tăng số lượng công việc phải làm. Hiện tượng này được gọi là sự đánh đổi không gian thời gian và rất hữu ích trong việc đánh giá độ phức tạp của thuật toán.space-time tradeoff and is useful in evaluating an algorithm’s complexity. Độ phức tạp không gian thời gianĐộ phức tạp tính toán là một thước đo tương đối về số lượng tài nguyên mà một thuật toán cần phải thực hiện công việc của mình. Các tài nguyên bao gồm thời gian tính toán cũng như lượng bộ nhớ mà nó sử dụng. So sánh sự phức tạp của các thuật toán khác nhau cho phép bạn đưa ra quyết định sáng suốt về cái nào tốt hơn trong một tình huống nhất định.computation time as well as the amount of memory it uses. Comparing the complexity of various algorithms allows you to make an informed decision about which is better in a given situation. Bạn đã xem xét một vài thuật toán tìm kiếm và hiệu suất trung bình của chúng so với một bộ dữ liệu lớn. Nó rõ ràng từ các phép đo rằng một tìm kiếm nhị phân nhanh hơn một tìm kiếm tuyến tính. Bạn thậm chí có thể nói bằng yếu tố nào. Tuy nhiên, nếu bạn thực hiện các phép đo tương tự trong một môi trường khác, bạn có thể nhận được một chút hoặc có lẽ hoàn toàn khác nhau. Có những yếu tố vô hình khi chơi có thể ảnh hưởng đến bài kiểm tra của bạn. Bên cạnh đó, các phép đo như vậy aren luôn luôn khả thi. Vì vậy, làm thế nào bạn có thể so sánh sự phức tạp về thời gian một cách nhanh chóng và khách quan? Bước đầu tiên là chia thuật toán thành các phần nhỏ hơn và tìm một phần đang làm nhiều công việc nhất. Nó có khả năng sẽ là một hoạt động cơ bản được gọi là rất nhiều và luôn mất khoảng thời gian để chạy. Đối với các thuật toán tìm kiếm, một hoạt động như vậy có thể là so sánh của hai yếu tố.elementary operation that gets called a lot and consistently takes about the same time to run. For search algorithms, such an operation might be the comparison of two elements. Đã thiết lập điều đó, bây giờ bạn có thể phân tích thuật toán. Để tìm sự phức tạp về thời gian, bạn muốn mô tả mối quan hệ giữa số lượng các hoạt động cơ bản được thực hiện so với kích thước của đầu vào. Chính thức, một mối quan hệ như vậy là một chức năng toán học. Tuy nhiên, bạn không quan tâm đến việc tìm kiếm công thức đại số chính xác của nó mà là ước tính hình dạng tổng thể của nó.relationship between the number of elementary operations executed versus the size of the input. Formally, such a relationship is a mathematical function. However, you’re not interested in looking for its exact algebraic formula but rather estimating its overall shape. Có một vài loại chức năng nổi tiếng mà hầu hết các thuật toán đều phù hợp. Một khi bạn phân loại một thuật toán theo một trong số chúng, bạn có thể đặt nó theo thang điểm: Các lớp học phổ biến về độ phức tạp thời gianCác lớp này cho bạn biết số lượng hoạt động cơ bản tăng theo kích thước ngày càng tăng của đầu vào. Họ là, từ trái sang phải:
Điều này có thể cung cấp cho bạn một ý tưởng về hiệu suất của thuật toán mà bạn đang xem xét. Một độ phức tạp không đổi, bất kể kích thước đầu vào, là thứ mong muốn nhất. Một độ phức tạp logarit vẫn còn khá tốt, cho thấy một kỹ thuật phân chia và chinh phục đang sử dụng. Càng ở phía bên phải trên thang đo này, sự phức tạp của thuật toán càng kém, bởi vì nó có nhiều việc phải làm hơn. Khi bạn nói về độ phức tạp về thời gian, ý nghĩa của bạn thường là sự phức tạp tiệm cận, mô tả hành vi trong các bộ dữ liệu rất lớn. Điều này đơn giản hóa công thức chức năng bằng cách loại bỏ tất cả các thuật ngữ và hệ số nhưng một điều khoản phát triển với tốc độ nhanh nhất (ví dụ: n bình phương).asymptotic complexity, which describes the behavior under very large data sets. This simplifies the function formula by eliminating all terms and coefficients but the one that grows at the fastest rate (for example, n squared). Tuy nhiên, một hàm duy nhất không cung cấp đủ thông tin để so sánh chính xác hai thuật toán. Độ phức tạp thời gian có thể thay đổi tùy thuộc vào khối lượng dữ liệu. Ví dụ, thuật toán tìm kiếm nhị phân giống như một động cơ tăng áp, tạo ra áp lực trước khi nó sẵn sàng cung cấp năng lượng. Mặt khác, thuật toán tìm kiếm tuyến tính nhanh chóng ngay từ đầu nhưng nhanh chóng đạt đến sức mạnh cao nhất của nó và cuối cùng mất cuộc đua: Về tốc độ, thuật toán tìm kiếm nhị phân bắt đầu vượt qua tìm kiếm tuyến tính khi có một số phần tử nhất định trong bộ sưu tập. Đối với các bộ sưu tập nhỏ hơn, một tìm kiếm tuyến tính có thể là một lựa chọn tốt hơn. Có một vài ký hiệu toán học về độ phức tạp tiệm cận, được sử dụng để so sánh các thuật toán. Cho đến nay, phổ biến nhất là ký hiệu O lớn.Big O notation. Ký hiệu O lớnKý hiệu O lớn đại diện cho trường hợp xấu nhất về sự phức tạp tiệm cận. Mặc dù điều này nghe có vẻ khá đáng sợ, nhưng bạn không cần phải biết định nghĩa chính thức. Theo trực giác, nó là một thước đo rất thô về tốc độ tăng trưởng ở đuôi của hàm mô tả sự phức tạp. Bạn phát âm nó là một thứ lớn của OH OH của một cái gì đó:Big O notation represents the worst-case scenario of asymptotic complexity. Although this might sound rather intimidating, you don’t need to know the formal definition. Intuitively, it’s a very rough measure of the rate of growth at the tail of the function that describes the complexity. You pronounce it as “big oh” of something: Đó là một thứ gì đó khác thường là một chức năng của kích thước dữ liệu hoặc chỉ là một chữ số, một trong số đó là không đổi. Ví dụ, thuật toán tìm kiếm tuyến tính có độ phức tạp về thời gian là 29, trong khi tìm kiếm dựa trên băm có độ phức tạp ____230.Trong cuộc sống thực, ký hiệu O lớn được sử dụng ít chính thức hơn là cả trên và giới hạn dưới. Điều này rất hữu ích cho việc phân loại và so sánh các thuật toán mà không phải lo lắng về các công thức chức năng chính xác. Sự phức tạp của tìm kiếm nhị phânBạn sẽ ước tính độ phức tạp thời gian tiệm cận của tìm kiếm nhị phân bằng cách xác định số lượng so sánh trong kịch bản trường hợp xấu nhất khi một yếu tố bị thiếu là một hàm có kích thước đầu vào. Bạn có thể tiếp cận vấn đề này theo ba cách khác nhau:
Phương pháp dạng bảng là về việc thu thập dữ liệu thực nghiệm, đặt nó vào một bảng và cố gắng đoán công thức bằng cách các giá trị lấy mẫu nhãn cầu:tabular method is about collecting empirical data, putting it in a table, and trying to guess the formula by eyeballing sampled values:
Số lượng so sánh tăng lên khi bạn tăng số lượng các yếu tố trong bộ sưu tập, nhưng tốc độ tăng trưởng chậm hơn so với khi nó là hàm tuyến tính. Đó là một dấu hiệu của một thuật toán tốt có thể mở rộng quy mô với dữ liệu. Nếu điều đó không giúp bạn, bạn có thể thử phương thức đồ họa, giúp trực quan hóa dữ liệu được lấy mẫu bằng cách vẽ biểu đồ:graphical method, which visualizes the sampled data by drawing a graph: Các điểm dữ liệu dường như phủ lên với một đường cong, nhưng bạn không có đủ thông tin để cung cấp câu trả lời kết luận. Nó có thể là một đa thức, có biểu đồ bật lên và xuống cho các đầu vào lớn hơn. Thực hiện phương pháp phân tích, bạn có thể chọn một số mối quan hệ và tìm kiếm các mẫu. Ví dụ: bạn có thể nghiên cứu cách số lượng các yếu tố thu hẹp trong mỗi bước của thuật toán:analytical approach, you can choose some relationship and look for patterns. For example, you might study how the number of elements shrinks in each step of the algorithm:
n/4 lần thứ 3 n/8 Sự kết luậnBây giờ bạn đã biết thuật toán tìm kiếm nhị phân từ trong ra ngoài. Bạn có thể tự thực hiện nó một cách hoàn hảo, hoặc tận dụng thư viện tiêu chuẩn trong Python. Sau khi khai thác khái niệm về độ phức tạp không gian thời gian, bạn có thể chọn thuật toán tìm kiếm tốt nhất cho tình huống đã cho. Bây giờ bạn có thể:
Với tất cả kiến thức này, bạn sẽ làm rung chuyển cuộc phỏng vấn lập trình của bạn! Cho dù thuật toán tìm kiếm nhị phân là một giải pháp tối ưu cho một vấn đề cụ thể, bạn có các công cụ để tự mình tìm ra nó. Bạn không cần một bằng cấp khoa học máy tính để làm như vậy.programming interview! Whether the binary search algorithm is an optimal solution to a particular problem, you have the tools to figure it out on your own. You don’t need a computer science degree to do so. Bạn có thể lấy tất cả các mã mà bạn đã thấy trong hướng dẫn này tại liên kết dưới đây: Xem bây giờ hướng dẫn này có một khóa học video liên quan được tạo bởi nhóm Python thực sự. Xem nó cùng với hướng dẫn bằng văn bản để hiểu sâu hơn về sự hiểu biết của bạn: Tạo một tìm kiếm nhị phân trong Python This tutorial has a related video course created by the Real Python team. Watch it together with the written tutorial to deepen your understanding: Creating a Binary Search in Python Làm thế nào để bạn sử dụng tìm kiếm nhị phân trong Python?Algorithm.. So sánh x với phần tử giữa .. Nếu x khớp với phần tử giữa, chúng ta sẽ trả về chỉ số giữa .. Khác nếu x lớn hơn phần tử giữa, thì x chỉ có thể nằm ở nửa bên phải Subarray sau phần tử giữa.Vì vậy, chúng tôi tái diễn cho nửa đúng .. Khác (x nhỏ hơn) tái diễn cho nửa bên trái .. Chỉ số () sử dụng tìm kiếm nhị phân?Các chỉ mục cơ sở dữ liệu sử dụng B-cây, khái quát hóa cây nhị phân. Không giống như sử dụng tìm kiếm nhị phân, mặc dù ý tưởng chung về "chia và chinh phục" trong cả hai trường hợp. That's not the same as using a binary search, although the general idea of "divide and conquer" applies in both cases. |