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 -

import random

def find(elements, value):
    while True:
        random_element = random.choice(elements)
        if random_element == value:
            return random_element
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

import random

def find(elements, value):
    while True:
        random_element = random.choice(elements)
        if random_element == value:
            return random_element
1 và danh sách được sắp xếp:

>>> import bisect
>>> names = ['bender', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> bisect.bisect_left(names, 'fry')
1
>>> keyword = 'fry'
>>> x = bisect.bisect_left(names, keyword)
>>> names[x] == keyword
True
>>> keyword = 'arnie'
>>> x = bisect.bisect_left(names, keyword)
>>> names[x] == keyword
False

Bạn cũng có thể sử dụng điều này để tìm bản sao:

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']

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.

>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']

Đ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 ..

  • 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
    
    1 để thực hiện tìm kiếm nhị phân trong Python
    import random
    
    def find(elements, value):
        while True:
            random_element = random.choice(elements)
            if random_element == value:
                return random_element
    
    1
    module to do a binary search in Python
  • Thực hiện tìm kiếm nhị phân trong Python đệ quy và lặp lạirecursively and iteratively
  • Nhận biết và sửa chữa các lỗi trong triển khai Python tìm kiếm nhị phândefects in a binary search Python implementation
  • Phân tích độ phức tạp không gian thời gian của thuật toán tìm kiếm nhị phântime-space complexity of the binary search algorithm
  • Tìm kiếm thậm chí nhanh hơn tìm kiếm nhị phânfaster than binary search

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 Python

Là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 ..

$ python download_imdb.py
Fetching data from IMDb...
Created "names.txt" and "sorted_names.txt"

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 ..

nconst     primaryName      birthYear  deathYear  (...)
nm0000001  Fred Astaire     1899       1987       (...)
nm0000002  Lauren Bacall    1924       2014       (...)
nm0000003  Brigitte Bardot  1934       \N         (...)
nm0000004  John Belushi     1949       1982       (...)

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 tab

Có 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:

  1. import random
    
    def find(elements, value):
        while True:
            random_element = random.choice(elements)
            if random_element == value:
                return random_element
    
    5
  2. import random
    
    def find(elements, value):
        while True:
            random_element = random.choice(elements)
            if random_element == value:
                return random_element
    
    6

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:

Fred Astaire
Lauren Bacall
Brigitte Bardot
John Belushi
Ingmar Bergman
...

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:

def load_names(path):
    with open(path) as text_file:
        return text_file.read().splitlines()

names = load_names('names.txt')
sorted_names = load_names('sorted_names.txt')

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

import random

def find(elements, value):
    while True:
        random_element = random.choice(elements)
        if random_element == value:
            return random_element
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
import random

def find(elements, value):
    while True:
        random_element = random.choice(elements)
        if random_element == value:
            return random_element
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

import random

def find(elements, value):
    while True:
        random_element = random.choice(elements)
        if random_element == value:
            return random_element
9 hoặc
>>> from search.random import *  # Sample code to download
>>> fruits = ['orange', 'plum', 'banana', 'apple']
>>> contains(fruits, 'banana')
True
>>> find_index(fruits, 'banana')
2
>>> find(fruits, key=len, value=4)
'plum'
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

>>> from search.random import *  # Sample code to download
>>> fruits = ['orange', 'plum', 'banana', 'apple']
>>> contains(fruits, 'banana')
True
>>> find_index(fruits, 'banana')
2
>>> find(fruits, key=len, value=4)
'plum'
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ếm

Tì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ể:

  • Thực hiện tìm kiếm toàn văn
  • Phù hợp với chuỗi với tìm kiếm mờ
  • Tìm đường dẫn ngắn nhất trong biểu đồ
  • Truy vấn một cơ sở dữ liệu
  • Tìm kiếm giá trị tối thiểu hoặc tối đa

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 hỏiCâu trả lời
Nó có ở đó không?Đúng
No ở đâu?Trên trang thứ 42
Đó là cái nào?Một người tên John Doe

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ên

Là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:

import random

def find(elements, value):
    while True:
        random_element = random.choice(elements)
        if random_element == value:
            return random_element

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ề

>>> from search.random import *  # Sample code to download
>>> fruits = ['orange', 'plum', 'banana', 'apple']
>>> contains(fruits, 'banana')
True
>>> find_index(fruits, 'banana')
2
>>> find(fruits, key=len, value=4)
'plum'
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:

>>>

>>> from search.random import *  # Sample code to download
>>> fruits = ['orange', 'plum', 'banana', 'apple']
>>> contains(fruits, 'banana')
True
>>> find_index(fruits, 'banana')
2
>>> find(fruits, key=len, value=4)
'plum'

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:

Thuật ngữ tìm kiếmChỉ số phần tửThời điểm tốt nhấtThời gian trung bìnhThời gian tồi tệ nhất
fred Astaire
>>> from search.random import *  # Sample code to download
>>> fruits = ['orange', 'plum', 'banana', 'apple']
>>> contains(fruits, 'banana')
True
>>> find_index(fruits, 'banana')
2
>>> find(fruits, key=len, value=4)
'plum'
3
>>> from search.random import *  # Sample code to download
>>> fruits = ['orange', 'plum', 'banana', 'apple']
>>> contains(fruits, 'banana')
True
>>> find_index(fruits, 'banana')
2
>>> find(fruits, key=len, value=4)
'plum'
4
>>> from search.random import *  # Sample code to download
>>> fruits = ['orange', 'plum', 'banana', 'apple']
>>> contains(fruits, 'banana')
True
>>> find_index(fruits, 'banana')
2
>>> find(fruits, key=len, value=4)
'plum'
5
>>> from search.random import *  # Sample code to download
>>> fruits = ['orange', 'plum', 'banana', 'apple']
>>> contains(fruits, 'banana')
True
>>> find_index(fruits, 'banana')
2
>>> find(fruits, key=len, value=4)
'plum'
6
Alicia Monica
>>> from search.random import *  # Sample code to download
>>> fruits = ['orange', 'plum', 'banana', 'apple']
>>> contains(fruits, 'banana')
True
>>> find_index(fruits, 'banana')
2
>>> find(fruits, key=len, value=4)
'plum'
7
>>> from search.random import *  # Sample code to download
>>> fruits = ['orange', 'plum', 'banana', 'apple']
>>> contains(fruits, 'banana')
True
>>> find_index(fruits, 'banana')
2
>>> find(fruits, key=len, value=4)
'plum'
8
>>> from search.random import *  # Sample code to download
>>> fruits = ['orange', 'plum', 'banana', 'apple']
>>> contains(fruits, 'banana')
True
>>> find_index(fruits, 'banana')
2
>>> find(fruits, key=len, value=4)
'plum'
9
def find_index(elements, value):
    for index, element in enumerate(elements):
        if element == value:
            return index
0
Baoyin liu
def find_index(elements, value):
    for index, element in enumerate(elements):
        if element == value:
            return index
1
def find_index(elements, value):
    for index, element in enumerate(elements):
        if element == value:
            return index
2
def find_index(elements, value):
    for index, element in enumerate(elements):
        if element == value:
            return index
3
def find_index(elements, value):
    for index, element in enumerate(elements):
        if element == value:
            return index
4
còn thiếu
def find_index(elements, value):
    for index, element in enumerate(elements):
        if element == value:
            return index
5
def find_index(elements, value):
    for index, element in enumerate(elements):
        if element == value:
            return index
6
def find_index(elements, value):
    for index, element in enumerate(elements):
        if element == value:
            return index
7
def find_index(elements, value):
    for index, element in enumerate(elements):
        if element == value:
            return index
8

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ính

Khi 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ể

def find_index(elements, value):
    for index, element in enumerate(elements):
        if element == value:
            return index
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
def find_index(elements, value):
    for index, element in enumerate(elements):
        if element == value:
            return index
9 elements to keep track of the current element’s index:

def find_index(elements, value):
    for index, element in enumerate(elements):
        if element == value:
            return 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

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
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:

Thuật ngữ tìm kiếmChỉ số phần tửThời điểm tốt nhấtThời gian trung bìnhThời gian tồi tệ nhất
fred Astaire
>>> from search.random import *  # Sample code to download
>>> fruits = ['orange', 'plum', 'banana', 'apple']
>>> contains(fruits, 'banana')
True
>>> find_index(fruits, 'banana')
2
>>> find(fruits, key=len, value=4)
'plum'
3
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
02
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
03
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
04
Alicia Monica
>>> from search.random import *  # Sample code to download
>>> fruits = ['orange', 'plum', 'banana', 'apple']
>>> contains(fruits, 'banana')
True
>>> find_index(fruits, 'banana')
2
>>> find(fruits, key=len, value=4)
'plum'
7
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
06
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
07
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
08
Baoyin liu
def find_index(elements, value):
    for index, element in enumerate(elements):
        if element == value:
            return index
1
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
10
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
11
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
12
còn thiếu
def find_index(elements, value):
    for index, element in enumerate(elements):
        if element == value:
            return index
5
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
11
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
12
còn thiếu

def find_index(elements, value):
    for index, element in enumerate(elements):
        if element == value:
            return index
5

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
15

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
16

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?

Có 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.

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
0

Ví 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.

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
1

Ví 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

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
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.

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
2

Ví 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

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
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ân

Từ 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:

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?

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:

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?

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:

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?

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

import random

def find(elements, value):
    while True:
        random_element = random.choice(elements)
        if random_element == value:
            return random_element
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:

Thuật ngữ tìm kiếmChỉ số phần tửThời gian trung bìnhSo sánh
(…) Berendse
>>> from search.random import *  # Sample code to download
>>> fruits = ['orange', 'plum', 'banana', 'apple']
>>> contains(fruits, 'banana')
True
>>> find_index(fruits, 'banana')
2
>>> find(fruits, key=len, value=4)
'plum'
3
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
22
23
Jonathan Samuangte
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
23
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
24
24
Yorgos Rahmatoulin
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
25
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
26
23
còn thiếu
def find_index(elements, value):
    for index, element in enumerate(elements):
        if element == value:
            return index
5
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
28
23

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:

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?

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:

  • Lấy đầu vào tùy ý và biến nó thành đầu ra có kích thước cố định.
  • Có phân phối giá trị đồng đều để giảm thiểu va chạm băm.hash collisions.
  • Tạo ra kết quả xác định.
  • Là một chức năng một chiều.
  • Khuếch đại thay đổi đầu vào để đạt được hiệu ứng tuyết lở.

Đồ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:

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?

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ó:

>>>

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
3

Sau khi tải tên văn bản vào một danh sách phẳng, bạn có thể

def find_index(elements, value):
    for index, element in enumerate(elements):
        if element == value:
            return index
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:

>>>

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
4

Sau khi tải tên văn bản vào một danh sách phẳng, bạn có thể

def find_index(elements, value):
    for index, element in enumerate(elements):
        if element == value:
            return index
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!

Tại đây, cách thức thuật toán tìm kiếm dựa trên băm thực hiện đối với bộ dữ liệu IMDB:Thuật ngữ tìm kiếmChỉ số phần tửThời điểm tốt nhấtThời gian trung bình
Thời gian tồi tệ nhấtfred Astaire
>>> from search.random import *  # Sample code to download
>>> fruits = ['orange', 'plum', 'banana', 'apple']
>>> contains(fruits, 'banana')
True
>>> find_index(fruits, 'banana')
2
>>> find(fruits, key=len, value=4)
'plum'
3
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
31
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
32
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
33
Alicia Monica
>>> from search.random import *  # Sample code to download
>>> fruits = ['orange', 'plum', 'banana', 'apple']
>>> contains(fruits, 'banana')
True
>>> find_index(fruits, 'banana')
2
>>> find(fruits, key=len, value=4)
'plum'
7
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
31
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
32
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
33
Alicia Monica
>>> from search.random import *  # Sample code to download
>>> fruits = ['orange', 'plum', 'banana', 'apple']
>>> contains(fruits, 'banana')
True
>>> find_index(fruits, 'banana')
2
>>> find(fruits, key=len, value=4)
'plum'
7
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
31
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
32
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
33
Alicia Monica
>>> from search.random import *  # Sample code to download
>>> fruits = ['orange', 'plum', 'banana', 'apple']
>>> contains(fruits, 'banana')
True
>>> find_index(fruits, 'banana')
2
>>> find(fruits, key=len, value=4)
'plum'
7
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
31
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
32

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
33

Alicia Monica

>>> from search.random import *  # Sample code to download
>>> fruits = ['orange', 'plum', 'banana', 'apple']
>>> contains(fruits, 'banana')
True
>>> find_index(fruits, 'banana')
2
>>> find(fruits, key=len, value=4)
'plum'
7hashable, and their hash values can’t change over time. You can check if a particular data type is hashable in Python by calling
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
46 on it:

>>>

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
5

Sau khi tải tên văn bản vào một danh sách phẳng, bạn có thể

def find_index(elements, value):
    for index, element in enumerate(elements):
        if element == value:
            return index
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 1

Tìm kiếm nhị phân trong Python có thể được thực hiện bằng mô-đun

import random

def find(elements, value):
    while True:
        random_element = random.choice(elements)
        if random_element == value:
            return random_element
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:

Tìm chỉ mụcPhần tử chèn
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
52
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
53
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
54
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
55
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
56
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
57

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

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
56 và
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
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

import random

def find(elements, value):
    while True:
        random_element = random.choice(elements)
        if random_element == value:
            return random_element
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

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
54:

>>>

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
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

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
62. Tuy nhiên, nếu thiếu phần tử, thì bạn vẫn có được vị trí dự kiến:

>>>

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
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

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
62. Tuy nhiên, nếu thiếu phần tử, thì bạn vẫn có được vị trí dự kiến:

  1. 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:index within the size of the list?

  2. Là chỉ mục trong kích thước của danh sách?value of the element the desired one?

Là giá trị của phần tử là một phần tử mong muốn?

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
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

>>> from search.random import *  # Sample code to download
>>> fruits = ['orange', 'plum', 'banana', 'apple']
>>> contains(fruits, 'banana')
True
>>> find_index(fruits, 'banana')
2
>>> find(fruits, key=len, value=4)
'plum'
2 ngầm.

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
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

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
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.

>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
0

Sau đó, 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.

>>>

>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
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

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
62. Tuy nhiên, nếu thiếu phần tử, thì bạn vẫn có được vị trí dự kiến:

>>>

>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
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

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
62. Tuy nhiên, nếu thiếu phần tử, thì bạn vẫn có được vị trí dự kiến:

>>>

>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
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

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
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?

>>>

>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
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

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
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

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
71 type using the @dataclass decorator, which was introduced in Python 3.7:

>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
5

Là chỉ mục trong kích thước của danh sách?

>>>

>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
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

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
62. Tuy nhiên, nếu thiếu phần tử, thì bạn vẫn có được vị trí dự kiến:

>>>

>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
7

Các biến

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
75 và
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
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:

>>>

>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
8

Python không biết đặt hàng

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
77 và
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
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
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
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í
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
80 chấp nhận một vài lá cờ Boolean tùy chọn. Một trong số đó là
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
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
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
82:less than, to tell the interpreter how to compare such elements. However, the
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
80 decorator accepts a few optional Boolean flags. One of them is
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
81, which results in an automatic generation of the magic methods for comparison when set to
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
82:

>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
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:

>>>

$ python download_imdb.py
Fetching data from IMDb...
Created "names.txt" and "sorted_names.txt"
0

Cuối cùng, bạn có thể tận dụng các thuộc tính

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
72 và
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
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:

>>>

$ python download_imdb.py
Fetching data from IMDb...
Created "names.txt" and "sorted_names.txt"
1

Các số trong ngoặc đơn sau các tên biểu thị thứ tự chèn. Ban đầu, chỉ có một

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
85, người có số
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
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 Python

Hã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:

  1. Lặp đi lặp lại
  2. Đệ quy

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:

$ python download_imdb.py
Fetching data from IMDb...
Created "names.txt" and "sorted_names.txt"
2

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.

$ python download_imdb.py
Fetching data from IMDb...
Created "names.txt" and "sorted_names.txt"
3

Phiê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:

$ python download_imdb.py
Fetching data from IMDb...
Created "names.txt" and "sorted_names.txt"
4

Bạ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:

$ python download_imdb.py
Fetching data from IMDb...
Created "names.txt" and "sorted_names.txt"
5

Bâ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.

$ python download_imdb.py
Fetching data from IMDb...
Created "names.txt" and "sorted_names.txt"
6

Tiế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

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
88 to accept and use a
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
89 parameter:

$ python download_imdb.py
Fetching data from IMDb...
Created "names.txt" and "sorted_names.txt"
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:

>>>

$ python download_imdb.py
Fetching data from IMDb...
Created "names.txt" and "sorted_names.txt"
8

Nó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ề

>>> from search.random import *  # Sample code to download
>>> fruits = ['orange', 'plum', 'banana', 'apple']
>>> contains(fruits, 'banana')
True
>>> find_index(fruits, 'banana')
2
>>> find(fruits, key=len, value=4)
'plum'
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

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
88 để chấp nhận và sử dụng tham số
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
89:

$ python download_imdb.py
Fetching data from IMDb...
Created "names.txt" and "sorted_names.txt"
9

Ngoà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:

nconst     primaryName      birthYear  deathYear  (...)
nm0000001  Fred Astaire     1899       1987       (...)
nm0000002  Lauren Bacall    1924       2014       (...)
nm0000003  Brigitte Bardot  1934       \N         (...)
nm0000004  John Belushi     1949       1982       (...)
0

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
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ó:

nconst     primaryName      birthYear  deathYear  (...)
nm0000001  Fred Astaire     1899       1987       (...)
nm0000002  Lauren Bacall    1924       2014       (...)
nm0000003  Brigitte Bardot  1934       \N         (...)
nm0000004  John Belushi     1949       1982       (...)
1

Vớ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

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
96 hoặc một vài người đi theo tên của
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
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
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
96 family or a few guys going by the name of
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
85 among the people:

nconst     primaryName      birthYear  deathYear  (...)
nm0000001  Fred Astaire     1899       1987       (...)
nm0000002  Lauren Bacall    1924       2014       (...)
nm0000003  Brigitte Bardot  1934       \N         (...)
nm0000004  John Belushi     1949       1982       (...)
2

Để mô hình hóa loại

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
71, bạn có thể sửa đổi lớp dữ liệu được xác định trước đó:

nconst     primaryName      birthYear  deathYear  (...)
nm0000001  Fred Astaire     1899       1987       (...)
nm0000002  Lauren Bacall    1924       2014       (...)
nm0000003  Brigitte Bardot  1934       \N         (...)
nm0000004  John Belushi     1949       1982       (...)
3

Lưu ý rằng việc sử dụng thuộc tính

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
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
>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
00, có cú pháp ngắn hơn:

nconst     primaryName      birthYear  deathYear  (...)
nm0000001  Fred Astaire     1899       1987       (...)
nm0000002  Lauren Bacall    1924       2014       (...)
nm0000003  Brigitte Bardot  1934       \N         (...)
nm0000004  John Belushi     1949       1982       (...)
4

Cả hai định nghĩa đều ổn và có thể hoán đổi cho nhau. Mỗi người có thuộc tính

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
72 và
>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
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
>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
03 có sẵn trong mô-đun
>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
04 tích hợp:

>>>

nconst     primaryName      birthYear  deathYear  (...)
nm0000001  Fred Astaire     1899       1987       (...)
nm0000002  Lauren Bacall    1924       2014       (...)
nm0000003  Brigitte Bardot  1934       \N         (...)
nm0000004  John Belushi     1949       1982       (...)
5

Lưu ý cách mọi người được sắp xếp theo họ theo thứ tự tăng dần. Có

>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
05 và
>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
06, nhưng tìm kiếm nhị phân cho họ
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
96 hiện chỉ cung cấp cho bạn một kết quả tùy ý:

>>>

nconst     primaryName      birthYear  deathYear  (...)
nm0000001  Fred Astaire     1899       1987       (...)
nm0000002  Lauren Bacall    1924       2014       (...)
nm0000003  Brigitte Bardot  1934       \N         (...)
nm0000004  John Belushi     1949       1982       (...)
6

Lưu ý cách mọi người được sắp xếp theo họ theo thứ tự tăng dần. Có

>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
05 và
>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
06, nhưng tìm kiếm nhị phân cho họ
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
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:

nconst     primaryName      birthYear  deathYear  (...)
nm0000001  Fred Astaire     1899       1987       (...)
nm0000002  Lauren Bacall    1924       2014       (...)
nm0000003  Brigitte Bardot  1934       \N         (...)
nm0000004  John Belushi     1949       1982       (...)
7

Để bắt chước các tính năng của mô -đun

import random

def find(elements, value):
    while True:
        random_element = random.choice(elements)
        if random_element == value:
            return random_element
1 được hiển thị trước đó, bạn có thể viết phiên bản
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
54 và
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
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:

nconst     primaryName      birthYear  deathYear  (...)
nm0000001  Fred Astaire     1899       1987       (...)
nm0000002  Lauren Bacall    1924       2014       (...)
nm0000003  Brigitte Bardot  1934       \N         (...)
nm0000004  John Belushi     1949       1982       (...)
8

Nế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:

nconst     primaryName      birthYear  deathYear  (...)
nm0000001  Fred Astaire     1899       1987       (...)
nm0000002  Lauren Bacall    1924       2014       (...)
nm0000003  Brigitte Bardot  1934       \N         (...)
nm0000004  John Belushi     1949       1982       (...)
9

Tì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:

Fred Astaire
Lauren Bacall
Brigitte Bardot
John Belushi
Ingmar Bergman
...
0

Thay 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.

Fred Astaire
Lauren Bacall
Brigitte Bardot
John Belushi
Ingmar Bergman
...
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:

Điều này không chỉ cho phép bạn xác định chính xác vị trí của các yếu tố trong danh sách, mà còn để truy xuất các yếu tố đó. Bạn có thể hỏi những câu hỏi rất cụ thể:Nó có ở đó không?No ở đâu?
Nó là gì?
>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
11
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
88
>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
13
>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
14
>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
15
>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
16
>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
17
>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
18

>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
19

Mã 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

>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
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

>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
11, cho bạn biết nếu một phần tử được tìm thấy.

Fred Astaire
Lauren Bacall
Brigitte Bardot
John Belushi
Ingmar Bergman
...
2

Cá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ú ý.

Fred Astaire
Lauren Bacall
Brigitte Bardot
John Belushi
Ingmar Bergman
...
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:

>>>

Fred Astaire
Lauren Bacall
Brigitte Bardot
John Belushi
Ingmar Bergman
...
4

Lưu ý cách mọi người được sắp xếp theo họ theo thứ tự tăng dần. Có

>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
05 và
>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
06, nhưng tìm kiếm nhị phân cho họ
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
96 hiện chỉ cung cấp cho bạn một kết quả tùy ý:

Fred Astaire
Lauren Bacall
Brigitte Bardot
John Belushi
Ingmar Bergman
...
5

Để bắt chước các tính năng của mô -đun

import random

def find(elements, value):
    while True:
        random_element = random.choice(elements)
        if random_element == value:
            return random_element
1 được hiển thị trước đó, bạn có thể viết phiên bản
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
54 và
...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
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:

Fred Astaire
Lauren Bacall
Brigitte Bardot
John Belushi
Ingmar Bergman
...
6

Nế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:

  1. 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. scope
  2. Tì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: scope
  3. Phạm vi toàn cầu scope
  4. Biểu tượng tích hợp symbols

Đ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ăn

Tạ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:

Mặc dù ý tưởng cơ bản của tìm kiếm nhị phân tương đối đơn giản, nhưng các chi tiết có thể rất khó khăn và nhiều lập trình viên giỏi đã làm sai trong vài lần đầu tiên họ thử.

- Donald Knuth

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:

Fred Astaire
Lauren Bacall
Brigitte Bardot
John Belushi
Ingmar Bergman
...
7

Phươ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

>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
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:

Fred Astaire
Lauren Bacall
Brigitte Bardot
John Belushi
Ingmar Bergman
...
8

Mộ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:

Fred Astaire
Lauren Bacall
Brigitte Bardot
John Belushi
Ingmar Bergman
...
9

Ngay 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:

>>>

def load_names(path):
    with open(path) as text_file:
        return text_file.read().splitlines()

names = load_names('names.txt')
sorted_names = load_names('sorted_names.txt')
0

Tuy 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

>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
25.

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: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:

>>>

def load_names(path):
    with open(path) as text_file:
        return text_file.read().splitlines()

names = load_names('names.txt')
sorted_names = load_names('sorted_names.txt')
1

Tuy 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

>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
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:

>>>

def load_names(path):
    with open(path) as text_file:
        return text_file.read().splitlines()

names = load_names('names.txt')
sorted_names = load_names('sorted_names.txt')
2

Tuy 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

>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
25.

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:

>>>

def load_names(path):
    with open(path) as text_file:
        return text_file.read().splitlines()

names = load_names('names.txt')
sorted_names = load_names('sorted_names.txt')
3

Có hai quả chuối trong danh sách. Lúc đầu, cuộc gọi đến

...
>>> names = ['bender', 'fry', 'fry', 'fry', 'leela', 'nibbler', 'zoidberg']
>>> keyword = 'fry'
>>> leftIndex = bisect.bisect_left(names, keyword)
>>> rightIndex = bisect.bisect_right(names, keyword)
>>> names[leftIndex:rightIndex]
['fry', 'fry', 'fry']
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
>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
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ổi

Cho đế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

>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
28 bằng cách sử dụng danh sách hiểu biết:

>>>

def load_names(path):
    with open(path) as text_file:
        return text_file.read().splitlines()

names = load_names('names.txt')
sorted_names = load_names('sorted_names.txt')
4

Danh 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:

>>>

def load_names(path):
    with open(path) as text_file:
        return text_file.read().splitlines()

names = load_names('names.txt')
sorted_names = load_names('sorted_names.txt')
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ó:

>>>

def load_names(path):
    with open(path) as text_file:
        return text_file.read().splitlines()

names = load_names('names.txt')
sorted_names = load_names('sorted_names.txt')
6

Nó 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:

>>>

def load_names(path):
    with open(path) as text_file:
        return text_file.read().splitlines()

names = load_names('names.txt')
sorted_names = load_names('sorted_names.txt')
7

So 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:

>>>

def load_names(path):
    with open(path) as text_file:
        return text_file.read().splitlines()

names = load_names('names.txt')
sorted_names = load_names('sorted_names.txt')
8

Khu 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:

>>>

def load_names(path):
    with open(path) as text_file:
        return text_file.read().splitlines()

names = load_names('names.txt')
sorted_names = load_names('sorted_names.txt')
9

Bạ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:

import random

def find(elements, value):
    while True:
        random_element = random.choice(elements)
        if random_element == value:
            return random_element
0

Mặ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ân

Phầ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:

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?
Các lớp học phổ biến về độ phức tạp thời gian

Cá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:

  • Không thay đổi
  • Logarit
  • Tuyến tính
  • Quasilinear
  • Bậc hai
  • số mũ
  • yếu tố

Đ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:

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?

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ớn

Ký 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:

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?

Đó 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à

>>> import bisect
>>> class Tag(object):  # a simple wrapper around strings
...     def __init__(self, tag):
...         self.tag = tag
...     def __lt__(self, other):
...         return self.tag < other.tag
...     def __gt__(self, other):
...         return self.tag > other.tag
...
>>> tags = [Tag('bender'), Tag('fry'), Tag('leela'), Tag('nibbler'), Tag('zoidbe
rg')]
>>> key = Tag('fry')
>>> leftIndex = bisect.bisect_left(tags, key)
>>> rightIndex = bisect.bisect_right(tags, key)
>>> print([tag.tag for tag in tags[leftIndex:rightIndex]])
['fry']
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ân

Bạ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:

  1. Bảng
  2. Đồ họa
  3. Phân tích

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 các yếu tốSố lượng so sánh
0 0
1 1
2 2
3 2
4 3
5 3
6 3
7 3
8 4

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:

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?

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:

So sánhSố lượng các yếu tố
Số lượng so sánhSố 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 đồ: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:So sánh
-N
Thứ nhấtThứ nhất
n/2lần 2

n/4

lần thứ 3

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?

n/8

Sự kết luận

Bâ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ể:

  • 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
    
    1 để thực hiện tìm kiếm nhị phân trong Python
    import random
    
    def find(elements, value):
        while True:
            random_element = random.choice(elements)
            if random_element == value:
                return random_element
    
    1
    module to do a binary search in Python
  • Thực hiện tìm kiếm nhị phân trong Python đệ quy và lặp lạirecursively and iteratively
  • Nhận biết và sửa chữa các lỗi trong triển khai Python tìm kiếm nhị phândefects in a binary search Python implementation
  • Phân tích độ phức tạp không gian thời gian của thuật toán tìm kiếm nhị phântime-space complexity of the binary search algorithm
  • Tìm kiếm thậm chí nhanh hơn tìm kiếm nhị phânfaster than binary search

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.