पुशिंग करना मैं वेब पर पाइथन रेडिक्स सॉर्ट करने के कई कार्यान्वयन के साथ बेहद निराश हूं।रैडिक्स सॉर्ट (और पायथन) को अपनी सीमाओं में
वे लगातार 10 की रेडिक्स का उपयोग करते हैं और 10 की शक्ति से विभाजित करके या संख्या के लॉग 10 को ले कर संख्याओं के अंकों को प्राप्त करते हैं। यह अविश्वसनीय रूप से अक्षम है, क्योंकि लॉग 10 बिट स्थानांतरण के मुकाबले विशेष रूप से त्वरित ऑपरेशन नहीं है, जो लगभग 100 गुना तेज है!
एक और अधिक कुशल कार्यान्वयन 256 के रेडिक्स का उपयोग करता है और बाइट द्वारा संख्या बाइट टाइप करता है। यह हास्यास्पद त्वरित बिट ऑपरेटरों का उपयोग करके सभी 'बाइट हो रही' करने के लिए अनुमति देता है। दुर्भाग्यवश, ऐसा लगता है कि बिल्कुल बाहर कोई भी पाइथन में एक रेडिक्स प्रकार लागू नहीं किया है जो लॉगरिदम के बजाय बिट ऑपरेटर का उपयोग करता है।
तो, मैं अपने ही हाथों में मामलों ले लिया और इस जानवर है, जो के बारे में आधे छोटे सरणियों पर हल कर की गति से चलाता है और बड़ों पर के रूप में जल्दी लगभग चलाता है के साथ आया था (जैसे len
10000000 के आसपास):
import itertools
def radix_sort(unsorted):
"Fast implementation of radix sort for any size num."
maximum, minimum = max(unsorted), min(unsorted)
max_bits = maximum.bit_length()
highest_byte = max_bits // 8 if max_bits % 8 == 0 else (max_bits // 8) + 1
min_bits = minimum.bit_length()
lowest_byte = min_bits // 8 if min_bits % 8 == 0 else (min_bits // 8) + 1
sorted_list = unsorted
for offset in xrange(lowest_byte, highest_byte):
sorted_list = radix_sort_offset(sorted_list, offset)
return sorted_list
def radix_sort_offset(unsorted, offset):
"Helper function for radix sort, sorts each offset."
byte_check = (0xFF << offset*8)
buckets = [[] for _ in xrange(256)]
for num in unsorted:
byte_at_offset = (num & byte_check) >> offset*8
buckets[byte_at_offset].append(num)
return list(itertools.chain.from_iterable(buckets))
रेडिक्स सॉर्ट का यह संस्करण यह पता लगाकर काम करता है कि किस बाइट को इसे क्रमबद्ध करना है (यदि आप इसे 256 से नीचे केवल पूर्णांक पास करते हैं, तो यह केवल एक बाइट इत्यादि को सॉर्ट करेगा) फिर एलएसबी से प्रत्येक बाइट को डंप करके सॉर्ट करना क्रम में बाल्टी में बस एक साथ बाल्टी चेन। इसे प्रत्येक बाइट के लिए दोहराएं जिसे सॉर्ट करने की आवश्यकता है और आपके पास ओ (एन) समय में आपका अच्छा क्रमबद्ध सरणी है।
हालांकि, यह जितना तेज़ नहीं हो सकता है, और मैं इसे अन्य सभी रेडिक्स प्रकारों की तुलना में बेहतर रेडिक्स प्रकार के रूप में लिखने से पहले इसे तेज़ी से बनाना चाहता हूं।
cProfile
चल रहा है पर इस मुझसे कहता है कि बहुत समय सूचियों के लिए append
विधि है, जो मुझे लगता है कि इस ब्लॉक कि बनाता है पर खर्च किया जा रहा है:
for num in unsorted:
byte_at_offset = (num & byte_check) >> offset*8
buckets[byte_at_offset].append(num)
radix_sort_offset
में बहुत समय खा रहा है। यह भी ब्लॉक है कि, यदि आप वास्तव में इसे देखते हैं, तो पूरे प्रकार के काम का 9 0% काम करता है। यह कोड ऐसा लगता है कि यह numpy
-ized हो सकता है, जो मुझे लगता है कि परिणामस्वरूप काफी प्रदर्शन होगा। दुर्भाग्यवश, मैं numpy
की अधिक जटिल विशेषताओं के साथ बहुत अच्छा नहीं हूं इसलिए इसे समझने में सक्षम नहीं है। मदद की बहुत सराहना की जाएगी।
मैं वर्तमान में itertools.chain.from_iterable
का उपयोग buckets
को फ़्लैट करने के लिए कर रहा हूं, लेकिन अगर किसी के पास तेज सुझाव है तो मुझे यकीन है कि इससे भी मदद मिलेगी।
मूल रूप से, मेरे पास get_byte
फ़ंक्शन था जो n
वें बाइट को वापस कर देता था, लेकिन कोड को रेखांकित करने से मुझे एक बड़ी गति वृद्धि मिली, इसलिए मैंने इसे किया।
कार्यान्वयन या अधिक प्रदर्शन को निचोड़ने के तरीकों पर कोई अन्य टिप्पणियां भी सराहना की जाती हैं। मैं कुछ और सब कुछ सुनना चाहता हूं।
अच्छा सामान। यह बहुत मजबूत गतिशीलता की ओर जाता है और 4079 के रेडिक्स के साथ 10,000,000 लंबे समय तक सूची में क्रमबद्ध करने के लिए इस रेडिक्स सॉर्ट को अनुमति देता है, हालांकि यह छोटी सूचियों पर शर्मनाक रूप से खराब प्रदर्शन करता है। संपादित करें: बस एहसास हुआ कि आप उस आदमी हैं जिन्होंने टाइम्सोर्ट लिखा था। मेरी टोपी तुम्हारे पास है, महोदय। – reem
हे - मैं शर्त लगाता हूं कि आपके पास उस सूची में कोई नकारात्मक पूर्णांक नहीं है ;-) रैडिक्स सॉर्ट बहुत अच्छा है, लेकिन जब आप गैर-नकारात्मक इनट्स से आगे बढ़ते हैं तो थोड़ा-सा झुकाव मुश्किल हो जाता है। एल बीटीडब्लू, मैंने पायथन की 'list.sort() 'लिखा है, और मुझे नाराज नहीं है कि आपका तेज़ है :-) –