Un esempio per le sequenze di valori interi. L'ordinamento è instabile. Anche se non è così conciso come la risposta fornita da Mohit, è leggermente più veloce (per il caso comune in cui k < < n) saltando gli elementi già nei loro bin corretti (il tempo è asintoticamente lo stesso). In pratica, preferisco il tipo di Mohit per il suo ciclo più stretto e semplice.
def sort_inplace(seq):
min_ = min(seq)
max_ = max(seq)
k = max_ - min_ + 1
stop = [0] * k
for i in seq:
stop[i - min_] += 1
for j in range(1, k):
stop[j] += stop[j - 1]
insert = [0] + stop[:k - 1]
for j in range(k):
while insert[j] < stop[j] and seq[insert[j]] == j + min_:
insert[j] += 1
tmp = None
for j in range(k):
while insert[j] < stop[j]:
tmp, seq[insert[j]] = seq[insert[j]], tmp
while tmp is not None:
bin_ = tmp - min_
tmp, seq[insert[bin_]] = seq[insert[bin_]], tmp
while insert[bin_] < stop[bin_] and seq[insert[bin_]] == bin_ + min_:
insert[bin_] += 1
Con un ciclo stretto, ma ancora saltare elementi già trasferito:
def dave_sort(seq):
min_ = min(seq)
max_ = max(seq)
k = max_ - min_ + 1
stop = [0] * k
for i in seq:
stop[i - min_] += 1
for i in range(1, k):
stop[i] += stop[i-1]
insert = [0] + stop[:k - 1]
for meh in range(0, k - 1):
i = insert[meh]
while i < stop[meh]:
bin_ = seq[i] - min_
if insert[bin_] > i:
tmp = seq[insert[bin_]]
seq[insert[bin_]] = seq[i]
seq[i] = tmp
insert[bin_] += 1
else:
i += 1
Edit: l'approccio di Mohit in Python con bit extra per verificare l'effetto sulla stabilità del genere.
from collections import namedtuple
from random import randrange
KV = namedtuple("KV", "k v")
def mohit_sort(seq, key):
f = lambda v: getattr(v, key)
keys = map(f, seq)
min_ = min(keys)
max_ = max(keys)
k = max_ - min_ + 1
insert = [0] * k
for i in keys:
insert[i - min_] += 1
insert[0] -= 1
for i in range(1, k):
insert[i] += insert[i-1]
i = 0
n = len(seq)
while i < n:
bin_ = f(seq[i])
if insert[bin_] > i:
seq[i], seq[insert[bin_]] = seq[insert[bin_]], seq[i]
i -= 1
insert[bin_] -= 1
i += 1
def test(n, k):
seq = []
vals = [0] * k
for _ in range(n):
key = randrange(k)
seq.append(KV(key, vals[key]))
vals[key] += 1
print(seq)
mohit_sort(seq, "k")
print(seq)
if __name__ == "__main__":
test(20, 3)
Vedere la sezione [algoritmi Variante] (http://en.wikipedia.org/wiki/Counting_sort#Variant_algorithms) nella voce di Wikipedia (ultimo paragrafo). – nwellnhof
'" Puoi usare O (k) memoria al di fuori dell'array di input "' - sembra proprio un ordinamento di conteggio regolare, che probabilmente rientra in una definizione distorta di "in place". Puoi anche eseguire il conteggio ordinando veramente sul posto con una certa complessità aggiunta utilizzando la ricorsione e i valori negativi per i conteggi (supponendo k <= n), ma tecnicamente lo spazio dello stack sarebbe il caso peggiore O (n), quindi in realtà non lavoro. L'ordinamento di conteggio abbastanza sicuro non può essere stabile. – Dukeling
abbiamo bisogno di memoria O (n + k) in un ordinamento di conteggio regolare. Il link wiki sopra riportato menziona semplicemente 'è possibile modificare l'ordinamento del conteggio in modo che possa essere eseguito sul posto' ma non ci sono informazioni su come farlo !! – Roronoa