Sắp xếp chèn nhị phân là một biến thể hiệu quả hơn của Sắp xếp chèn. Trong hướng dẫn này, chúng ta sẽ sắp xếp một mảng với sự trợ giúp của sắp xếp chèn nhị phân
Sắp xếp chèn nhị phân - Giới thiệu cơ bản
Trong sắp xếp chèn nhị phân, tìm kiếm nhị phân được sử dụng để xác định vị trí chính xác để chèn mục đã chọn. Về cơ bản, nó làm giảm số lượng so sánh từ phương pháp sắp xếp chèn thông thường. Chúng ta phải xác định đúng vị trí của phần tử đang được xem xét trong Sắp xếp Chèn. Số lượng so sánh sẽ giảm nếu chúng ta sử dụng Tìm kiếm nhị phân cho chức năng tìm kiếm này. Do đó, Sắp xếp chèn nhị phân sử dụng tìm kiếm nhị phân trong mỗi lần lặp lại để xác định vị trí chính xác để chèn mục đã chọn
thuật toán
Đến bây giờ, chúng ta đã hiểu sơ bộ về cách thực hiện sắp xếp cơ số. Để hiểu rõ hơn, hãy đi sâu vào thuật toán, sau đó là mã
- Tạo hàm binary_insertionSort chấp nhận danh sách làm đầu vào
- Tạo một vòng lặp với biến vòng lặp i đếm từ 1 đến độ dài của danh sách – 1 trong hàm
- Đặt tạm thời thành giá trị của phần tử tại chỉ mục i
- Gọi nhị phân_search
- Đặt pos++ giá trị trả về của lệnh gọi trên
- Từ chỉ mục pos + 1 đến i chuyển tất cả các mục về một nơi
- đặt alist[pos] thành tạm thời
- Để tìm một khóa trong danh sách giữa các chỉ mục bắt đầu và kết thúc – bao gồm 1 – một hàm sử dụng tìm kiếm nhị phân
- Nếu không tìm thấy khóa, chỉ mục của phần tử nhỏ nhất nhỏ hơn khóa được trả về
- Nếu khóa nhỏ hơn phần tử đầu tiên, nó sẽ trả về -1
- Mảng hiện đã được sắp xếp
- In mảng
Chương trình sắp xếp chèn nhị phân
Mã nguồn cho chương trình Python thực hiện sắp xếp chèn nhị phân được cung cấp bên dưới. Đầu ra của chương trình được hiển thị bên dưới. Trong chương trình này, người dùng được yêu cầu nhập danh sách và sau đó, dạng sắp xếp của danh sách được nhắc bởi trình biên dịch
def binary_insertionsort[array]:
for i in range[1, len[array]]:
temp = array[i]
pos = binary_search[array, temp, 0, i] + 1
for k in range[i, pos, -1]:
array[k] = array[k - 1]
array[pos] = temp
def binary_search[array, key, strt, end]:
if end - strt key:
return binary_search[array, key, strt, middle]
else:
return middle
#driver code
array = input['Enter the array numbers: '].split[]
array = [int[a] for a in array]
binary_insertionsort[array]
print['The Sorted array is: ', end='']
print[array]
Nhập số mảng. 5 4 3 98 76 97
Mảng được sắp xếp là. [3, 4, 5, 76, 97, 98]
Phần kết luận
Trong hướng dẫn này, chúng tôi đã thực hiện phương thức Sắp xếp chèn nhị phân trong chương trình python để sắp xếp một mảng. Độ phức tạp thời gian của sắp xếp chèn nhị phân là O[log n] và độ phức tạp không gian là O[1]
Mô-đun này cung cấp hỗ trợ để duy trì danh sách theo thứ tự được sắp xếp mà không cần phải sắp xếp danh sách sau mỗi lần chèn. Đối với danh sách dài các mục có thao tác so sánh tốn kém, đây có thể là một cải tiến so với cách tiếp cận phổ biến hơn. Mô-đun được gọi vì nó sử dụng thuật toán chia đôi cơ bản để thực hiện công việc của mình. Mã nguồn có thể hữu ích nhất như một ví dụ hoạt động của thuật toán [các điều kiện biên đã đúng. ]
Các chức năng sau đây được cung cấp
chia đôi. bisect_left[a , x , lo=0 , hi=len[a] , * , key=Không có]Xác định vị trí điểm chèn cho x trong a để duy trì thứ tự đã sắp xếp. Các tham số lo và hi có thể được sử dụng để chỉ định một tập hợp con của danh sách cần được xem xét; . Nếu x đã có trong a, điểm chèn sẽ ở trước [ở bên trái] bất kỳ mục nhập hiện có nào. Giá trị trả về phù hợp để sử dụng làm tham số đầu tiên cho list.insert[]
giả định rằng a đã được sắp xếp
Điểm chèn được trả về i chia mảng a thành hai nửa sao cho all[val = x for val in a[i : hi]]
cho bên phải
key chỉ định một trong một đối số được sử dụng để trích xuất khóa so sánh từ mỗi phần tử trong mảng. Để hỗ trợ tìm kiếm các bản ghi phức tạp, hàm key không được áp dụng cho giá trị x
Nếu khóa là None
, các phần tử được so sánh trực tiếp mà không cần gọi hàm can thiệp
Đã thay đổi trong phiên bản 3. 10. Đã thêm tham số chính.
chia đôi. bisect_right[a , x , lo=0 , hi=len[a] , * , phím=Không có]chia đôi. chia đôi[a , x , lo=0 , hi=len[a] , * , key=Không có]Tương tự như , nhưng trả về một điểm chèn xuất hiện sau [ở bên phải] bất kỳ mục nhập hiện có nào của x trong một
Điểm chèn trả về i chia mảng a thành hai nửa sao cho
>>> def grade[score, breakpoints=[60, 70, 80, 90], grades='FDCBA']: .. i = bisect[breakpoints, score] .. return grades[i] ... >>> [grade[score] for score in [33, 99, 77, 70, 89, 90, 100]] ['F', 'A', 'C', 'C', 'B', 'A', 'A']1 cho bên trái và
>>> def grade[score, breakpoints=[60, 70, 80, 90], grades='FDCBA']: .. i = bisect[breakpoints, score] .. return grades[i] ... >>> [grade[score] for score in [33, 99, 77, 70, 89, 90, 100]] ['F', 'A', 'C', 'C', 'B', 'A', 'A']2 cho bên phải
key chỉ định một trong một đối số được sử dụng để trích xuất khóa so sánh từ mỗi phần tử trong mảng. Để hỗ trợ tìm kiếm các bản ghi phức tạp, hàm key không được áp dụng cho giá trị x
Nếu khóa là None
, các phần tử được so sánh trực tiếp mà không cần gọi hàm can thiệp
Đã thay đổi trong phiên bản 3. 10. Đã thêm tham số chính.
chia đôi. insort_left[a , x , lo=0 , hi=len[a] , * , key=Không có]Chèn x vào một thứ tự được sắp xếp
Chức năng này chạy đầu tiên để xác định vị trí một điểm chèn. Tiếp theo, nó chạy phương thức
>>> def grade[score, breakpoints=[60, 70, 80, 90], grades='FDCBA']: .. i = bisect[breakpoints, score] .. return grades[i] ... >>> [grade[score] for score in [33, 99, 77, 70, 89, 90, 100]] ['F', 'A', 'C', 'C', 'B', 'A', 'A']5 trên a để chèn x vào vị trí thích hợp để duy trì thứ tự sắp xếp
Để hỗ trợ chèn bản ghi vào bảng, hàm khóa [nếu có] được áp dụng cho x cho bước tìm kiếm nhưng không áp dụng cho bước chèn
Hãy nhớ rằng tìm kiếm
>>> def grade[score, breakpoints=[60, 70, 80, 90], grades='FDCBA']: .. i = bisect[breakpoints, score] .. return grades[i] ... >>> [grade[score] for score in [33, 99, 77, 70, 89, 90, 100]] ['F', 'A', 'C', 'C', 'B', 'A', 'A']6 bị chi phối bởi bước chèn chậm O[n]
Đã thay đổi trong phiên bản 3. 10. Đã thêm tham số chính.
chia đôi. insort_right[a , x , lo=0 , hi=len[a] , * , phím=Không có]chia đôi. sắp xếp[a , x , lo=0 , hi=len[a] , * , key=Không có]Tương tự như , nhưng chèn x vào sau bất kỳ mục nhập hiện có nào của x
Chức năng này chạy đầu tiên để xác định vị trí một điểm chèn. Tiếp theo, nó chạy phương thức
>>> def grade[score, breakpoints=[60, 70, 80, 90], grades='FDCBA']: .. i = bisect[breakpoints, score] .. return grades[i] ... >>> [grade[score] for score in [33, 99, 77, 70, 89, 90, 100]] ['F', 'A', 'C', 'C', 'B', 'A', 'A']5 trên a để chèn x vào vị trí thích hợp để duy trì thứ tự sắp xếp
Để hỗ trợ chèn bản ghi vào bảng, hàm khóa [nếu có] được áp dụng cho x cho bước tìm kiếm nhưng không áp dụng cho bước chèn
Hãy nhớ rằng tìm kiếm
>>> def grade[score, breakpoints=[60, 70, 80, 90], grades='FDCBA']: .. i = bisect[breakpoints, score] .. return grades[i] ... >>> [grade[score] for score in [33, 99, 77, 70, 89, 90, 100]] ['F', 'A', 'C', 'C', 'B', 'A', 'A']6 bị chi phối bởi bước chèn chậm O[n]
Đã thay đổi trong phiên bản 3. 10. Đã thêm tham số chính.
Ghi chú hiệu suất
Khi viết mã nhạy cảm với thời gian bằng cách sử dụng bisect[] và insort[], hãy ghi nhớ những suy nghĩ này
Chia đôi có hiệu quả để tìm kiếm phạm vi giá trị. Để định vị các giá trị cụ thể, từ điển hiệu quả hơn
Các hàm insort[] là
>>> from collections import namedtuple >>> from operator import attrgetter >>> from bisect import bisect, insort >>> from pprint import pprint >>> Movie = namedtuple['Movie', ['name', 'released', 'director']] >>> movies = [ .. Movie['Jaws', 1975, 'Speilberg'], .. Movie['Titanic', 1997, 'Cameron'], .. Movie['The Birds', 1963, 'Hitchcock'], .. Movie['Aliens', 1986, 'Scott'] .. ] >>> # Find the first movie released after 1960 >>> by_year = attrgetter['released'] >>> movies.sort[key=by_year] >>> movies[bisect[movies, 1960, key=by_year]] Movie[name='The Birds', released=1963, director='Hitchcock'] >>> # Insert a movie while maintaining sort order >>> romance = Movie['Love Story', 1970, 'Hiller'] >>> insort[movies, romance, key=by_year] >>> pprint[movies] [Movie[name='The Birds', released=1963, director='Hitchcock'], Movie[name='Love Story', released=1970, director='Hiller'], Movie[name='Jaws', released=1975, director='Speilberg'], Movie[name='Aliens', released=1986, director='Scott'], Movie[name='Titanic', released=1997, director='Cameron']]
1 vì bước tìm kiếm logarit bị chi phối bởi bước chèn thời gian tuyến tínhCác chức năng tìm kiếm là không trạng thái và loại bỏ các kết quả của chức năng chính sau khi chúng được sử dụng. Do đó, nếu các hàm tìm kiếm được sử dụng trong một vòng lặp, thì hàm chính có thể được gọi đi gọi lại trên cùng một phần tử mảng. Nếu chức năng chính không nhanh, hãy xem xét gói chức năng đó để tránh tính toán trùng lặp. Ngoài ra, hãy xem xét việc tìm kiếm một dãy các khóa được tính toán trước để định vị điểm chèn [như minh họa trong phần ví dụ bên dưới]
Xem thêm
Bộ sưu tập được sắp xếp là một mô-đun hiệu suất cao sử dụng chia đôi cho các bộ sưu tập dữ liệu được sắp xếp được quản lý
Công thức SortedCollection sử dụng bisect để xây dựng một lớp bộ sưu tập đầy đủ tính năng với các phương thức tìm kiếm đơn giản và hỗ trợ cho hàm khóa. Các phím được tính toán trước để lưu các cuộc gọi không cần thiết đến chức năng của phím trong quá trình tìm kiếm
Tìm kiếm danh sách được sắp xếp
Các chức năng trên rất hữu ích để tìm điểm chèn nhưng có thể phức tạp hoặc khó sử dụng cho các tác vụ tìm kiếm thông thường. Năm chức năng sau đây cho thấy cách chuyển đổi chúng thành tra cứu tiêu chuẩn cho danh sách được sắp xếp
________số 8_______
ví dụ
Hàm này có thể hữu ích cho việc tra cứu bảng số. Ví dụ này sử dụng để tra cứu điểm chữ cái cho điểm bài kiểm tra [giả sử] dựa trên một tập hợp các điểm ngắt số theo thứ tự. 90 trở lên là 'A', 80 đến 89 là 'B', v.v.
>>> def grade[score, breakpoints=[60, 70, 80, 90], grades='FDCBA']: .. i = bisect[breakpoints, score] .. return grades[i] ... >>> [grade[score] for score in [33, 99, 77, 70, 89, 90, 100]] ['F', 'A', 'C', 'C', 'B', 'A', 'A']
Các chức năng và cũng hoạt động với danh sách các bộ dữ liệu. Đối số chính có thể dùng để trích xuất trường được sử dụng để sắp xếp thứ tự các bản ghi trong bảng
>>> from collections import namedtuple >>> from operator import attrgetter >>> from bisect import bisect, insort >>> from pprint import pprint >>> Movie = namedtuple['Movie', ['name', 'released', 'director']] >>> movies = [ .. Movie['Jaws', 1975, 'Speilberg'], .. Movie['Titanic', 1997, 'Cameron'], .. Movie['The Birds', 1963, 'Hitchcock'], .. Movie['Aliens', 1986, 'Scott'] .. ] >>> # Find the first movie released after 1960 >>> by_year = attrgetter['released'] >>> movies.sort[key=by_year] >>> movies[bisect[movies, 1960, key=by_year]] Movie[name='The Birds', released=1963, director='Hitchcock'] >>> # Insert a movie while maintaining sort order >>> romance = Movie['Love Story', 1970, 'Hiller'] >>> insort[movies, romance, key=by_year] >>> pprint[movies] [Movie[name='The Birds', released=1963, director='Hitchcock'], Movie[name='Love Story', released=1970, director='Hiller'], Movie[name='Jaws', released=1975, director='Speilberg'], Movie[name='Aliens', released=1986, director='Scott'], Movie[name='Titanic', released=1997, director='Cameron']]
Nếu chức năng khóa đắt tiền, có thể tránh các cuộc gọi chức năng lặp lại bằng cách tìm kiếm danh sách các khóa được tính toán trước để tìm chỉ mục của bản ghi