Складність оператора * in * у Python


88

Яка складність inоператора в Python? Це тета (n)?

Це те саме, що і наступне?

def find(L, x):
   for e in L:
       if e == x:
           return True
   return False

L є списком.


3
Це залежить від типу контейнера, оскільки використання його зі словником або набором буде набагато швидшим, ніж із масивом.
Greg Hewgill

1
@BasicWolf Я використовував L, тому це список
Sajad Rastegar

5
@Rastegar Lне означає список. seqє найпоширенішим вибором, коли хочеться навести перелік. Lце жахлива назва змінної. Однобуквені погані, і велика буква означає, що це клас. Навіть якщо це було щось конкретне, Python є динамічним, тому чітко заявляйте про це у такому випадку.
Gareth Latty

1
Lзасоби list? Моя лібтелепатія.так, мабуть, застаріла.
Заур Насібов

1
@GarethLatty Використання lst - це також хороша назва для визначення alist
r0ei

Відповіді:


145

Складність Росії inповністю залежить від того, що Lє. e in Lстане L.__contains__(e).

Дивіться цей документ про складність часу щодо складності декількох вбудованих типів.

Ось короткий зміст для in:

  • список - Середнє значення: O (n)
  • набір / дикт - Середнє: O (1), Найгірше: O (n)

Найгірший випадок O (n) для наборів і наборів дуже рідкісний, але це може статися, якщо __hash__його неправильно реалізувати. Це трапляється лише в тому випадку, якщо все у вашому наборі має однакове хеш-значення.


1
Хтось випадково знає складність оператора "in" для OrderedDict?
Джош Шерік,

1
Після певного тестування я можу підтвердити, що складність OrderedDict у Python 2.7 у середньому виявляється O (1).
Джош Шерік,

@Josh Sherick, вам не потрібно надавати тести, все, що вам потрібно - це джерела OrderedDict, і, як ви могли дізнатися: OrderedDictуспадковується від dict, тому більшість операцій (звичайно, за винятками) мають однакову складність .
maxkoryukov

Складність у часі оператора "in" O (n) також для кортежу?
Успадкований Geek

1
@whitehat лінійний.
juanpa.arrivillaga

13

Це повністю залежить від типу контейнера. Контейнери для хешування ( dict, set) використовують хеш і є по суті O (1). Типові послідовності ( list, tuple) реалізуються, як ви здогадуєтесь, і є O (n). Дерева були б середніми O (log n). І так далі. Кожен із цих типів мав би відповідний __contains__метод з його великими характеристиками.


значення включає накладні витрати на генерування хешу.
Woot4Moo

Типи даних хешування включають dictі set(а також потенційно інші)
Дейв

2
@ Woot4Moo: Коли ви говорите про асимптотичну складність, це не має значення. Накладні витрати на генерування хешу є постійними. Коли ви маєте справу з малими значеннями N, профілювання стає важливим, оскільки, скажімо, 100 >> 2N для малого N. Але це окреме питання від того, про що запитував OP; для величезного N, 100 << 2N, саме в цьому полягає складність.
abarnert

@abarnert, це насправді досить актуально, оскільки ви не довільно вибираєте структури даних. Ви повинні врахувати використання та найпоширеніші способи використання структури, тому насправді важливо враховувати кількість часу для хеш-функції, особливо в сценарії, коли has повинен обчислюватися за ітерацію програми.
Woot4Moo

@ Woot4Moo: Якщо хтось запитує про асимптотичну складність, або (а) вони розраховують мати справу з великим N, або (б) вони ідіот. Я припускаю, що OP є випадком (a), але в будь-якому випадку постійний коефіцієнт не має значення для відповіді.
abarnert

-1

Це залежить від контейнера, який ви тестуєте. Зазвичай це те, чого ви очікуєте - лінійний для впорядкованих структур даних, постійний для невпорядкованих. Звичайно, існують обидва типи (упорядковані чи невпорядковані), які можуть бути підкріплені якимись варіантами дерева.


@ZoranPavlovic A in Bперевіряє, чи Aє B.
Марсін,

1
Я б точно очікував логарифмічного часу в упорядкованій структурі.
dedObed

@dedObed Чому ви цього очікуєте? Чи очікуєте ви, що python вже знає, чи сортуються ваші дані чи ні?
Marcin

Оскільки, якщо є контейнер, призначений для замовлення, очевидна причина полягає в тому, щоб дозволити логарифмічні пошуки. Але, мабуть, це просто проблема з іменуванням, я б використав "linear", де ви написали "порядок", і все було б добре. (В моїй голові - англійська мова тут є другою мовою.)
dedObed
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.