Вставить элемент в отсортированный список в Python

Я создаю класс, в котором один из методов вставляет новый элемент в отсортированный список. Элемент вставляется в исправленное (отсортированное) положение в отсортированном списке. Однако мне не разрешено использовать какие-либо встроенные функции или методы списка, кроме [], [:], + и len. Это та часть, которая действительно сбивает меня с толку.

Как лучше всего это сделать?


person Will S    schedule 06.11.2011    source источник
comment
Домашнее задание? Вероятно, вы начали бы с поиска в Интернете, как вставить элементы в отсортированный список.   -  person Felix Kling    schedule 06.11.2011
comment
Мне не разрешено использовать и встроенные функции списка, хотя   -  person Will S    schedule 06.11.2011
comment
@FelixKling, ОП, заявил, что запрещение .insert() это то, что сбивает с толку ОП. Маловероятно, что при любом количестве поисков можно найти кого-то, кто хорошо сосредоточится на этом в конкретном контексте.   -  person n611x007    schedule 10.05.2015


Ответы (7)


Используйте функцию insort элемента bisect:

import bisect 
a = [1, 2, 4, 5] 
bisect.insort(a, 3) 
print(a)

Выход

[1, 2, 3, 4, 5] 
person stanga    schedule 01.08.2013
comment
Отсутствует, что делать, когда элементы не являются целыми числами. т.е. как я могу использовать его в реальной проблеме мира? - person Velda; 29.04.2018
comment
@Velda вот нецелочисленный пример: s = ['a', 'b', 'd']; bisect.insort(s, 'c'); assert(s == ['a', 'b', 'c', 'd']) - person Joseph Holsten; 21.06.2018
comment
Еще целый пример. Кстати, как часто вы сортируете письма...? Что, если я хочу отсортировать экземпляры некоторого класса по какому-то его свойству? - person Velda; 22.06.2018
comment
@Velda Я думаю, что последний пример документации пополам может быть полезен. Также вы можете немного изменить код bisect.insort, как в этом ответе: stackoverflow.com/a/41903429/7708392 - person xdcsy; 27.11.2018
comment
@Velda, если вы сравниваете пользовательские классы, вы можете реализовать метод __lt__, и bisect.insort сможет правильно сортировать экземпляры классов. docs.python.org/3/library/operator.html#operator. __lt__ - person drakenation; 10.09.2019
comment
@drakenation Из любопытства, как вы наткнулись на эту информацию, потому что я не почерпнул ее из документации и хочу стать более эффективным и найти такую ​​​​информацию самостоятельно. - person Filip Gajowniczek; 11.11.2019
comment
@Filip Gajowniczek Если вы попытаетесь отсортировать пользовательские классы с помощью sorted(), вы получите TypeError: «‹» не поддерживается между экземплярами «MyClasss» и «MyClasss», что означает, что если вы реализуете __lt__, вы можете использовать sorted() . Я ожидал, что у bisect.insort будет такое же поведение, поэтому я проверил, и это сработало. Мои советы: пробуйте, обращайте внимание на сообщения об ошибках и ищите возможные решения. - person drakenation; 12.11.2019
comment
Это выполняется за O(n). Алгоритмически это не лучше, чем просто просмотреть список, найти соответствующие позиции и перетасовать элементы в списке, чтобы сохранить порядок сортировки. - person nz_21; 24.11.2019
comment
Спасибо @nz_21, искал способ вставки отсортированных данных без необходимости реализации BST. Не подходит для ответа OP, но использование библиотеки может работать и выполнять вставку в O(log( Н)). Или скопируйте сложность вставки O (N). - person Thomas; 19.02.2020
comment
@ nz_21 На самом деле я думаю, что технически это решение O (log (n) + n) --> log (n) для поиска позиции и n для вставки. Описанное вами решение будет O (n + n) --> n для поиска позиции и n для вставки. Так что bisect немного быстрее, я считаю - person ionox0; 15.11.2020
comment
@ionox0 Нет. С точки зрения асимптотической сложности O(log(n) + n)= O(n) - person nz_21; 15.11.2020

Совет 1. Возможно, вы захотите изучить код Python в модуле bisect.

Совет 2. Для вставки списка можно использовать нарезку:

>>> s = ['a', 'b', 'd', 'e']
>>> s[2:2] = ['c']
>>> s
['a', 'b', 'c', 'd', 'e']
person Raymond Hettinger    schedule 06.11.2011
comment
Поскольку OP не разрешалось использовать какие-либо функции или методы, нарезка остается единственным способом вставить новый элемент в список. - person Raymond Hettinger; 24.04.2016
comment
bisect хорош для вставки отсортированных списков, но его скорость падает до O (N), потому что он использует базовые списки python. Есть ли что-нибудь на рынке со связанными списками или что-то в этом роде? - person Maksim Gayduk; 11.05.2016

Вы должны использовать модуль bisect. Кроме того, список необходимо отсортировать перед использованием bisect.insort_left.

Это довольно большая разница.

>>> l = [0, 2, 4, 5, 9]
>>> bisect.insort_left(l,8)
>>> l
[0, 2, 4, 5, 8, 9]

timeit.timeit("l.append(8); l = sorted(l)",setup="l = [4,2,0,9,5]; import bisect; l = sorted(l)",number=10000)
    1.2235019207000732

timeit.timeit("bisect.insort_left(l,8)",setup="l = [4,2,0,9,5]; import bisect; l=sorted(l)",number=10000)
    0.041441917419433594
person Ricky Sahu    schedule 12.07.2014

Я сейчас изучаю алгоритм, поэтому мне интересно, как модуль bisect пишет. Вот код из модуля bisect о вставке элемента в отсортированный список, который использует дихотомию:

def insort_right(a, x, lo=0, hi=None):
    """Insert item x in list a, and keep it sorted assuming a is sorted.
    If x is already in a, insert it to the right of the rightmost x.
    Optional args lo (default 0) and hi (default len(a)) bound the
    slice of a to be searched.
    """

    if lo < 0:
        raise ValueError('lo must be non-negative')
    if hi is None:
        hi = len(a)
    while lo < hi:
        mid = (lo+hi)//2
        if x < a[mid]:
            hi = mid
        else:
            lo = mid+1
    a.insert(lo, x)
person 请叫我小马哥    schedule 22.03.2019

Это возможное решение для вас:

a = [15, 12, 10]
b = sorted(a)
print b # --> b = [10, 12, 15]
c = 13
for i in range(len(b)):
    if b[i] > c:
        break
d = b[:i] + [c] + b[i:]
print d # --> d = [10, 12, 13, 15]
person ngoc thoag    schedule 29.06.2012
comment
Не лучшее решение, модуль bisect найдет точку вставки за O(log n) шагов, вам потенциально придется искать весь список, сложность O(n). - person Martijn Pieters; 20.10.2012

Ну, есть много способов сделать это, вот простая наивная программа, которая делает то же самое, используя встроенную функцию Python sorted()

def sorted_inserter():
list_in = []
n1 = int(input("How many items in the list : "))

for i in range (n1):
    e1 = int(input("Enter numbers in list : "))
    list_in.append(e1)
print("The input list is : ",list_in)


print("Any more items to be inserted ?")
n2 = int(input("How many more numbers to be added ? : "))
for j in range (n2):
    e2= int(input("Add more numbers : "))
    list_in.append(e2)
    list_sorted=sorted(list_in)
    print("The sorted list is: ",list_sorted)
    

sorted_inserter()

Выход

Сколько пунктов в списке: 4

Введите числа в список: 1

Введите числа в список: 2

Введите числа в список: 123

Введите числа в список: 523

Список ввода: [1, 2, 123, 523]

Есть ли еще элементы, которые нужно вставить?

Сколько еще цифр нужно добавить? : 1

Добавьте больше цифр: 9

Отсортированный список: [1, 2, 9, 123, 523]

person Community    schedule 15.06.2021

Это лучший способ добавить список и вставить значения в отсортированный список:

 a = [] num = int(input('How many numbers: ')) for n in range(num):
     numbers = int(input('Enter values:'))
     a.append(numbers)

 b = sorted(a) print(b) c = int(input("enter value:")) for i in
 range(len(b)):
     if b[i] > c:
         index = i
         break d = b[:i] + [c] + b[i:] print(d)`
person Veera Pathiran    schedule 08.09.2017