Ich habe einige Sortieralgorithmen zusammengefasst.
Ich habe jeden Punkt, ein Implementierungsbeispiel in Python und jede Geschwindigkeitsmessung beschrieben.
Ich habe es implementiert, ohne so viele integrierte Funktionen wie möglich zu verwenden, daher ist es nicht sehr schnell, aber ich wollte etwas schneller machen als sort () und sorted ().
Der zu behandelnde Sortieralgorithmus ist
Name | Durchschnittliche Berechnungszeit | Schlechteste Berechnungszeit | Speichernutzung | Stabilität |
---|---|---|---|---|
Blasensorte | Stabil | |||
Selektive Sortierung | Nicht stabil | |||
Sortierung einfügen | Stabil | |||
Zusammenführen, sortieren | Stabil | |||
Schnelle Sorte | Nicht stabil | |||
Sortierung zählen | Nicht stabil |
Andere bekannte Sortieralgorithmen sind Heap-Sortierung, Shell-Sortierung und Radix-Sortierung, aber diesmal habe ich sie vergessen. Ich möchte es eines Tages hinzufügen.
Die Heap-Sortierung ist mit dem Heapq-Modul von Python recht einfach zu implementieren, aber es fühlt sich anders an als sort () ...
Stabilität bedeutet, dass beim Sortieren von Daten wie [1-b, 2-a, 1-a, 2-b] unter Verwendung von Zahlen als Schlüssel die Reihenfolge vor dem Sortieren gespeichert wird und [1-b, Wir erkennen, dass so etwas wie 1-a, 2-a, 2-b] als stabil definiert ist.
--Vergleichen und tauschen Sie die Größe jeder Seite aus und tun Sie dies, bis keine Änderungen mehr erforderlich sind.
bubble_sort.py
def bubble_sort(arr):
change = True
while change:
change = False
for i in range(len(arr) - 1):
if arr[i] > arr[i + 1]:
arr[i], arr[i + 1] = arr[i + 1], arr[i]
change = True
return arr
--Wählen Sie das Minimum oder Maximum im Array und verschieben Sie es bis zum Ende.
Ich habe das Gefühl, ich kann min () verwenden ...
Um die Speichernutzung auf $ O (1) $ zu reduzieren, wird sie durch Ersetzen implementiert, anstatt sie in eine neue Liste aufzunehmen.
sellect_sort.py
def sellect_sort(arr):
for ind, ele in enumerate(arr):
min_ind = min(range(ind, len(arr)), key=arr.__getitem__)
arr[ind], arr[min_ind] = arr[min_ind], ele
return arr
Wenn Sie die 2-Minuten-Suche nicht verwenden
insert_sort.py
def insert_sort(arr):
for i in range(1, len(arr)):
j = i - 1
ele = arr[i]
while arr[j] > ele and j >= 0:
arr[j + 1] = arr[j]
j -= 1
arr[j + 1] = ele
return arr
Bei Verwendung der 2-Minuten-Suche
insert_sort_bin.py
import sys
sys.setrecursionlimit(10 ** 7)
def binary_search(arr, low, hig, ele):
if low == hig:
if arr[low] > ele:
return low
else:
return low + 1
elif low > hig:
return low
mid = (low + hig) // 2
if arr[mid] < ele:
return binary_search(arr, mid + 1, hig, ele)
elif arr[mid] > ele:
return binary_search(arr, low, mid - 1, ele)
else:
return mid
def insert_sort_bin(arr):
for i in range(1, len(arr)):
ele = arr[i]
ind = binary_search(arr, 0, i - 1, ele)
arr[:] = arr[:ind] + [ele] + arr[ind:i] + arr[i + 1:]
return arr
Übrigens, wenn Sie Bisect verwenden, ein Modul für die 2-minütige Suche,
insert_sort_bin_buildin.py
import bisect
def insert_sort_bin_buildin(arr):
for i in range(1, len(arr)):
bisect.insort(arr, arr.pop(i), 0, i)
return arr
merge_sort.py
def merge_sort(arr):
if len(arr) <= 1:
return arr
mid = len(arr) // 2
#Mach den Split hier
left = arr[:mid]
right = arr[mid:]
#Rekursiv teilen
left = merge_sort(left)
right = merge_sort(right)
#Wenn die Rückgabe zurückgegeben wird, kombinieren und übergeben Sie die nächste Kombination
return merge(left, right)
def merge(left, right):
merged = []
l_i, r_i = 0, 0
#Sie müssen nur von links schauen, um die sortierten Arrays zusammenzuführen.
while l_i < len(left) and r_i < len(right):
#Hier=Die Stabilität bleibt durch Anbringen erhalten
if left[l_i] <= right[r_i]:
merged.append(left[l_i])
l_i += 1
else:
merged.append(right[r_i])
r_i += 1
#Wenn eine der oben genannten while-Anweisungen zu False wird, wird sie beendet. Erweitern Sie also zu viel
if l_i < len(left):
merged.extend(left[l_i:])
if r_i < len(right):
merged.extend(right[r_i:])
return merged
――Bestimmen Sie einen Referenzwert und teilen Sie ihn in zwei Sequenzen, groß und klein, entsprechend dem Referenzwert.
quick_sort.py
def quick_sort(arr):
left = []
right = []
if len(arr) <= 1:
return arr
#Zufällig, da dies nicht vom Status der Daten abhängt.choice()Könnte genutzt werden.
# ref = random.choice(arr)
ref = arr[0]
ref_count = 0
for ele in arr:
if ele < ref:
left.append(ele)
elif ele > ref:
right.append(ele)
else:
ref_count += 1
left = quick_sort(left)
right = quick_sort(right)
return left + [ref] * ref_count + right
--Zählen Sie die Nummer jedes Wertes.
Die Bucket-Sortierung ist ein Sortieralgorithmus, der der Zählsortierung sehr ähnlich ist. Die Bucket-Sortierung ist wie ein Sortieralgorithmus, der mehrere Boxen mit einem bestimmten Bereich erstellt, Werte in sie einfügt, jede Box sortiert und sie dann kombiniert.
Die Zählsortierung kann auch die Stabilität aufrechterhalten, indem für jeden Wert ein Feld erstellt und hinzugefügt wird. Dies ist jedoch die Implementierung, da die Idee eher ein Bucket als eine Zählung ist. Wenn Sie das Modul collection.defaultdict verwenden, können Sie es ganz einfach und stabil implementieren.
count_sort.py
def count_sort(arr):
max_num = max(arr)
min_num = min(arr)
count = [0] * (max_num - min_num + 1)
for ele in arr:
count[ele - min_num] += 1
return [ele for ele, cnt in enumerate(count, start=min_num) for __ in range(cnt)]
Generiert mit numpy.random.
Der erstellte Datensatz ist
--data1: 100 einheitliche Zufallszahlen im Bereich von 0-100 --data2: 10000 einheitliche Zufallszahlen im Bereich von 0-1000 --data3: 10000 einheitliche Zufallszahlen im Bereich von 0 bis 100 --data4: 100 Zufallszahlen der Standardnormalverteilung mit Mittelwert 10 und Standardabweichung 5 --data5: 10000 Zufallszahlen der Standardnormalverteilung im Bereich von Durchschnitt 100 und Standardabweichung 50 --data6: 100 einheitliche Zufallszahlen im Bereich 0-100 bereits in umgekehrter Reihenfolge sortiert --data7: Bereits nach 100 einheitlichen Zufallszahlen von ganzen Zahlen im Bereich von 0 bis 100 sortiert, werden nur die ersten 10 durcheinander gebracht
make_data.py
data_rand_1 = list(randint(0, 10 ** 2, 10 ** 2))
data_rand_2 = list(randint(0, 10 ** 4, 10 ** 4))
data_rand_3 = list(randint(0, 10 ** 2, 10 ** 4))
data_rand_4 = [int(normal(10, 5)) for __ in range(10 ** 2)]
data_rand_5 = [int(normal(10 ** 2, 50)) for __ in range(10 ** 4)]
data_rand_6 = sorted(randint(0, 10 ** 2, 10 ** 2), reverse=True)
data_rand_7 = sorted(randint(0, 10 ** 2, 10 ** 2))
data_rand_7[0: 10] = choice(data_rand_7[0: 10], 10, replace=False)
Der folgende Code wurde verwendet, um 100 Mal zu messen, und der Durchschnitt wurde berechnet. Ich konnte es mit dem Timeit-Befehl des Jupyter-Notizbuchs nicht gut messen.
Die Einheit ist μs.
Für jeden Algorithmus wurden Messungen durchgeführt, um Fehler so weit wie möglich zu reduzieren. Vielleicht hängt es von den Spezifikationen der CPU und des Speichers ab, aber wenn die Implementierung so wäre, dass alle Algorithmen gleichzeitig mithilfe einer Schleife gemessen werden könnten, würde die Leistung erheblich sinken.
time.py
datas = [data_rand_1, data_rand_2, data_rand_3,
data_rand_4, data_rand_5, data_rand_6, data_rand_7]
for ind, data in enumerate(datas):
print("---- DataSet : {0} ----".format(ind + 1))
times = []
for i in range(100):
start = time.time()
#Sortieralgorithmus, den Sie messen möchten
sorted(data)
elapsed_time = int((time.time() - start) * (10 ** 6))
times.append(elapsed_time)
print(sum(times) // 100)
Art | Einheitliche Zufallszahl | 大きいEinheitliche Zufallszahl | 狭くて大きいEinheitliche Zufallszahl | Normalverteilung | 大きいNormalverteilung | In umgekehrter Reihenfolge sortiert | Fast sortiert |
---|---|---|---|---|---|---|---|
In Python integrierte Sortierung | 16 | 3488 | 2938 | 10 | 2447 | 12 | 6 |
Blasensorte | 25 | 167789 | 163781 | 21 | 154426 | 26 | 10 |
Selektive Sortierung | 418 | 4025181 | 3889431 | 379 | 3552541 | 433 | 422 |
Sortierung einfügen | 24 | 58281 | 53705 | 19 | 47764 | 25 | 17 |
Sortierung einfügen(2 Minuten suchen) | 627 | 1382480 | 1338027 | 334 | 1278530 | 347 | 339 |
Zusammenführen, sortieren | 593 | 67221 | 61657 | 329 | 59483 | 270 | 233 |
Schnelle Sorte | 142 | 25911 | 12009 | 56 | 12044 | 469 | 542 |
Sortierung zählen | 95 | 5597 | 2164 | 24 | 1607 | 57 | 51 |
Bei engen Bereichen scheint die Zählsortierung schneller zu sein als die integrierte Sortierung.
Ich denke, wenn wir die Bucket-Sortierung, die relativ zur Zählsortierung ist, erfolgreich implementieren können, können wir einen schnelleren Algorithmus erstellen.
Kombinieren Sie vorerst die schnelle Sortierung und die Zählsortierung, um eine große Datenmenge einzugeben.
Die vorbereiteten Daten sind "big_data = list (randint (0, 10 ** 3, 10 ** 6))".
quick_sort_with_count.py
def quick_sort_with_count(arr):
left = []
right = []
if len(arr) <= 1:
return arr
ref = choice(arr)
ref_count = 0
for ele in arr:
if ele < ref:
left.append(ele)
elif ele > ref:
right.append(ele)
else:
ref_count += 1
if len(left) <= 1000:
left = count_sort(left)
else:
left = quick_sort_with_count(left)
if len(right) <= 1000:
right = count_sort(right)
else:
right = quick_sort_with_count(right)
return left + [ref] * ref_count + right
Art | Ergebnis |
---|---|
In Python integrierte Sortierung | 464109 |
Schnelle Sorte | 2069006 |
Sortierung zählen | 250043 |
Schnelle Sorte+Sortierung zählen | 3479010 |
Ich habe vorerst keine Zeit mehr, das war's. Wenn Sie Zeit haben, nehmen Sie ein feinkörniges Dataset und vergleichen und validieren Sie die in Python integrierten Sortierungen und Zählsortierungen.
Es wird allgemein gesagt, dass Zusammenführungssortierung, schnelle Sortierung usw. schnell sind, aber vorerst scheint es nicht so schnell zu sein, da rekursive Aufrufe usw. in Python Zeit brauchen.
Wenn Sie den Bereich und die Art der Werte kennen, kann die Zählsortierung hilfreich sein. Wikipedia auf Japanisch hat nicht einmal einen Artikel, und einige englische Dokumente werden mit der Sortierung von Eimern verwechselt, aber ...
Recommended Posts