2013-06-27 14 views
5

Mam posortowaną listę liczb całkowitych, L, a ja mam wartość X, którą chcę wstawić do listy, tak aby kolejność L była zachowywana. Podobnie, życzę, aby szybko znaleźć i usunąć pierwsze wystąpienie X.Wstawianie i usuwanie do/z posortowanej listy w Pythonie

Pytania:

  1. W jaki sposób korzystać z modułu przepoławiać zrobić pierwszą część, jeśli jest to możliwe?
  2. Czy L.remove (X) będzie najskuteczniejszym sposobem na wykonanie drugiej części? Czy Python wykryje, że lista została posortowana i automatycznie korzysta z logarytmicznego procesu usuwania?

przykładowy kod próby:

i = bisect_left(L, y) 

L.pop(i)     #works 
del L[bisect_left(L, i)] #doesn't work if I use this instead of pop 
+1

Twój exmaple nie ma sensu; 'i' jest indeksem do' L', ale 'L.pop (i)' usuwa wartość * z listy. –

Odpowiedz

9
  1. użyć bisect.insort() function:

    bisect.insort(L, X) 
    
  2. L.remove(X) skanuje całą listę, dopóki nie znajdzie X. Zamiast tego należy użyć del L[bisect.bisect_left(L, X)] (pod warunkiem, że X rzeczywiście znajduje się w L).

Należy pamiętać, że usunięcie ze środka listy nadal będzie ponosić kosztów jako elementów z tej pozycji począwszy wszyscy muszą być przesunięte w lewo jednym kroku. Drzewo binarne może być lepszym rozwiązaniem, jeśli będzie to wąskie gardło wydajności.

+0

Tak więc dla # 1, teraz mam, na przykład, L.append (X); L = posortowane (L); ale można to zastąpić insort (L, X)? – MrP

+0

@MrP: Tak; moduł "bisect" użyje bisekcji do znalezienia punktu wstawienia, operacji O (log n), w przeciwieństwie do O (n log n) do dołączania i sortowania. –

+0

Dla # 2 próbowałem tylko zastąpić L.pop (X) del L [bisect_left (L, X)] i nie wydaje się działać – MrP

1

Możesz użyć Raymonda Hettingera: IndexableSkiplist. Wykonuje 3 operacje w O(ln n) czas:

  • wartość wkładka
  • cena Usuń
  • wartość
  • wyszukiwanie według rangi

import skiplist 
import random 
random.seed(2013) 

N = 10 
skip = skiplist.IndexableSkiplist(N) 
data = range(N) 
random.shuffle(data) 
for num in data: 
    skip.insert(num) 

print(list(skip)) 
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 

for num in data[:N//2]: 
    skip.remove(num) 

print(list(skip)) 
# [0, 3, 4, 6, 9] 
+0

Czy istnieje sposób na uzyskanie indeksu pierwszego numeru, który jest> = B? – MrP

+0

Możesz użyć 'bisect.bisect_left (skip, B)'. Zauważ, że jeśli 'B' jest ściśle większe niż jakakolwiek wartość w' skip', to 'bisect_left' zwróci' len (skip) ', który znajduje się poza zakresem poprawnych wartości indeksu dla' skip'. – unutbu

Powiązane problemy