पाइथन के साथ क्विकॉर्ट


93

मैं अजगर के लिए बिल्कुल नया हूं और मैं इसमें क्विकसर्ट लागू करने की कोशिश कर रहा हूं। क्या कोई मुझे अपना कोड पूरा करने में मदद कर सकता है?

मुझे नहीं पता कि तीन सरणियों को कैसे बदलना और उन्हें प्रिंट करना है।

def sort(array=[12,4,5,6,7,3,1,15]):
    less = []
    equal = []
    greater = []

    if len(array) > 1:
        pivot = array[0]
        for x in array:
            if x < pivot:
                less.append(x)
            if x == pivot:
                equal.append(x)
            if x > pivot:
                greater.append(x)
            sort(less)
            sort(pivot)
            sort(greater)

सूचियों को संयोजित करने के लिए आप प्लस ऑपरेटर का उपयोग कर सकते हैं my_list = list1 + list2 + ...। या नई सूची में अनपैक सूचीmy_list = [*list1, *list2]
मार्क मिशिन

जवाबों:


254
def sort(array=[12,4,5,6,7,3,1,15]):
    """Sort the array by using quicksort."""

    less = []
    equal = []
    greater = []

    if len(array) > 1:
        pivot = array[0]
        for x in array:
            if x < pivot:
                less.append(x)
            elif x == pivot:
                equal.append(x)
            elif x > pivot:
                greater.append(x)
        # Don't forget to return something!
        return sort(less)+equal+sort(greater)  # Just use the + operator to join lists
    # Note that you want equal ^^^^^ not pivot
    else:  # You need to handle the part at the end of the recursion - when you only have one element in your array, just return the array.
        return array

8
आप ifलूप के लिए 2 s को भी स्वैप कर सकते हैं elifऔर elseअनावश्यक तुलना करने से बच सकते हैं
SlimPDX

13
यह ध्वनि है जैसे मर्ज की तरह त्वरित गति नहीं
इमाद मोख्तार

47
यह वास्तव में सबसे अच्छा और सबसे पठनीय अजगर कोड है जो मुझे कहीं भी क्विकॉर्ट के लिए मिला है । कोई संकेत नहीं, कोई सहायक कार्य नहीं, स्पष्ट रूप से एल्गोरिथ्म का विभाजन (विभाजन और जीत) दिखाता है। (सरणी के लिए डिफ़ॉल्ट मान अनावश्यक है)
cmantas

19
@jsmedmar यह जगह के संस्करण में एक से अधिक मेमोरी का उपयोग करेगा, एक त्वरित स्थान के लिए suquant का उत्तर देखें।
जॉन

14
यह बहुत ही पठनीय है लेकिन क्या यह त्वरित-क्रम के उद्देश्य को नहीं हराता है क्योंकि यह 'जगह' की तरह हासिल नहीं करेगा? @RasmiRanjanNayak क्रमबद्ध यहाँ उपयोगकर्ता परिभाषित फ़ंक्शन (इसकी पुनरावर्ती कॉल) है, किसी भी फ़ंक्शन में नहीं बनाया गया है।
मकसूद

161

अतिरिक्त मेमोरी के बिना त्वरित सॉर्ट (जगह में)

उपयोग:

array = [97, 200, 100, 101, 211, 107]
quicksort(array)
# array -> [97, 100, 101, 107, 200, 211]
def partition(array, begin, end):
    pivot = begin
    for i in xrange(begin+1, end+1):
        if array[i] <= array[begin]:
            pivot += 1
            array[i], array[pivot] = array[pivot], array[i]
    array[pivot], array[begin] = array[begin], array[pivot]
    return pivot



def quicksort(array, begin=0, end=None):
    if end is None:
        end = len(array) - 1
    def _quicksort(array, begin, end):
        if begin >= end:
            return
        pivot = partition(array, begin, end)
        _quicksort(array, begin, pivot-1)
        _quicksort(array, pivot+1, end)
    return _quicksort(array, begin, end)

23
यह चयनित उत्तर होना चाहिए, क्योंकि क्विकॉर्ट अक्सर पसंद का एल्गोरिथ्म है (उदाहरण के लिए मर्ज सॉर्ट) क्योंकि यह जगह में सॉर्ट करता है (और अभी भी ओ (नॉग्लन) रनटाइम देता है)।
बोल्टजमनब्रेन

3
if end is None:बहुत बार जाँच की जा रही है, और केवल एक बार यह होने जा रहा है True। आपको इसे रैपर फंक्शन में रखना चाहिए ताकि इसे केवल एक बार ही बुलाया जाए।
गिलेस्पी

Ackchyually, ब्रू, @mksteve सही है और यह लाइन गलत है। इसके अतिरिक्त, के साथ array[pivot], array[begin] = array[begin], array[pivot]प्रतिस्थापित करना चाहिए । beginend
रयान जे मैककॉल

2
हालांकि इन-प्लेस अच्छा है, यह धीमा है और बहुत अधिक आइटम होने पर अधिकतम रिकर्सन डेप्थ को हिट करने के कारण यह त्रुटी करता है। देखें repl.it/@almenon/quicksorts?language=python3
एलमेनन

@mksteve और रयान, मैंने इन परिवर्तनों का परीक्षण किया और यह छंटनी को तोड़ता है
अलजगोम

68

एक और संक्षिप्त और सुंदर संस्करण है

def qsort(arr): 
    if len(arr) <= 1:
        return arr
    else:
        return qsort([x for x in arr[1:] if x < arr[0]]) + \
               [arr[0]] + \
               qsort([x for x in arr[1:] if x >= arr[0]])

# this comment is just to improve readability due to horizontal scroll!!!

मुझे विवरण के लिए उपरोक्त कोड की व्याख्या करने दें

  1. arr[0]धुरी के रूप में सरणी का पहला तत्व चुनें

    [arr[0]]

  2. qsort सरणी के वे तत्व जो धुरी से कम हैं List Comprehension

    qsort([x for x in arr[1:] if x < arr[0]])

  3. qsort सरणी के वे तत्व जो धुरी से बड़े होते हैं List Comprehension

    qsort([x for x in arr[1:] if x >= arr[0]])


15
@ ज़ंग के संभावित कारणों में गिरावट: 1) पहले से ही हल या उलट सरणियों पर द्विघात रनटाइम 2) समाधान जगह में नहीं है। इसलिए, एक भयानक कार्यान्वयन, क्षमा करें।
एलिसियानो

16
बिल्कुल भी पठनीय नहीं है, क्या आप वास्तव में लाइनों की संख्या को कम करने की कोशिश कर रहे हैं? मशीनों द्वारा कोड की व्याख्या की जाती है, लेकिन मानव द्वारा समझा जाता है।
jsmedmar

4
@AlfredoGallegos, क्विकॉर्ट की पूरी बात यह है कि यह जगह में होता है, यदि आप ऐसा करने जा रहे हैं, तो आप मर्ज-तरह को लागू कर सकते हैं।
पैड्राइक कनिंघम

14
क्या ये टिप्पणी वास्तविक है? यदि आप प्रदर्शन, उपयोग चाहते हैं sorted, तो यह स्पष्ट रूप से शैक्षिक उद्देश्यों के लिए है। और यह स्वीकार्य उत्तर की तुलना में पठनीय, अधिक पठनीय है।
नोबिलिस

4
FWIW, मैंने सोचा कि यह उन सभी का सबसे पठनीय कार्यान्वयन था। यह एल्गोरिथ्म की पुनरावर्ती संरचना को किसी अन्य उत्तर की तुलना में बेहतर दिखाता है। बेशक, प्रदर्शन बहुत अच्छा नहीं होगा।
सॉलिट इट

36

यह उत्तर इसके लिए एक त्वरित QuickSort है Python 2.x। मेरा जवाब रोजेटा कोड से इन-प्लेस समाधान की व्याख्या है जो इसके लिए Python 3भी काम करता है:

import random

def qsort(xs, fst, lst):
    '''
    Sort the range xs[fst, lst] in-place with vanilla QuickSort

    :param xs:  the list of numbers to sort
    :param fst: the first index from xs to begin sorting from,
                must be in the range [0, len(xs))
    :param lst: the last index from xs to stop sorting at
                must be in the range [fst, len(xs))
    :return:    nothing, the side effect is that xs[fst, lst] is sorted
    '''
    if fst >= lst:
        return

    i, j = fst, lst
    pivot = xs[random.randint(fst, lst)]

    while i <= j:
        while xs[i] < pivot:
            i += 1
        while xs[j] > pivot:
            j -= 1

        if i <= j:
            xs[i], xs[j] = xs[j], xs[i]
            i, j = i + 1, j - 1
    qsort(xs, fst, j)
    qsort(xs, i, lst)

और अगर आप इन-प्लेस प्रॉपर्टी को त्यागने के लिए तैयार हैं, तो नीचे एक और संस्करण है जो क्विकॉर्ट के पीछे मूल विचारों को बेहतर ढंग से दिखाता है। पठनीयता के अलावा, इसका अन्य लाभ यह है कि यह स्थिर है (समान तत्व उसी क्रम में सॉर्ट की गई सूची में दिखाई देते हैं जो कि वे अनसोल्ड सूची में हुआ करते थे)। यह स्थिरता संपत्ति ऊपर प्रस्तुत किए गए कम मेमोरी-इन-प्लेस कार्यान्वयन के साथ नहीं है।

def qsort(xs):
    if not xs: return xs # empty sequence case
    pivot = xs[random.choice(range(0, len(xs)))]

    head = qsort([x for x in xs if x < pivot])
    tail = qsort([x for x in xs if x > pivot])
    return head + [x for x in xs if x == pivot] + tail

इस समाधान को साझा करने के लिए धन्यवाद। क्या आप कृपया समय-जटिलता को समझने में हमारी मदद कर सकते हैं? मैं देख रहा हूं कि रिकर्सन इसे 15 बार कॉल करेगा। इनमें से 8 फ़ंक्शन के लिए वैध कॉल हैं। क्या इसका मतलब यह है कि पहले समाधान के लिए समय-जटिलता O (n) है और अंतरिक्ष जटिलता O (1) है?
फॉरएवरलाइनर

@ टैमी ऐसा लगता है कि आप बिग-ओ नोटेशन को गलत समझते हैं। इसके अलावा, मैं वास्तव में आपके प्रश्न को नहीं समझता हूं। क्या आप शायद इसे एक अलग के रूप में पूछ सकते हैं? अंत में, एक एल्गोरिथ्म के रूप में क्विकॉर्ट ओ (एन लोगन) समय और ओ (एन) अंतरिक्ष में चलता है।
अलिसियानी

3
मेरी गलती। क्यों मैं पृथ्वी पर पुनरावृत्ति गिन रहा था ?? :-) खैर, 15 पुनरावृत्ति [1 कॉल (स्तर 0) + 2 कॉल (स्तर 1 विभाजन) + 4 कॉल (स्तर 2 विभाजन) + 8 कॉल (स्तर 3 विभाजन या पत्ती नोड्स) है। तो, हमारे पास अभी भी ऊंचाई है (lg8 + 1) = lgn। प्रत्येक स्तर में कुल गणना c1 (कुछ लागत) * n के लिए है। इसलिए O (n lgn)। अंतरिक्ष की जटिलता, एक-इन-एक्सचेंज विनिमय के लिए = O (1)। इसलिए n तत्वों के लिए = O (n)। सूचक के लिए धन्यवाद।
फॉरएवरलाइनर

3
यह इंटरनेट पर सबसे अच्छा अजगर क्विकॉर्ट दूर और दूर है, और इसे इतने सारे O (n) स्पेस सॉल्यूशन के तहत दफन देखकर दुख की बात है :(
साशा कोंडरशोव

@Timofey तरह के शब्दों के लिए धन्यवाद। आप मेरे एल्गोरिदम रेपो पर एक नज़र डालना चाहते हैं, इसके अन्य संस्करण हैं, ग्राफ़ एल्गोरिदम, आदि आदि। github.com/alisianoi/algos-py
alisianoi

23

पाइथन के साथ क्विकॉर्ट

वास्तविक जीवन में, हमें हमेशा पायथन द्वारा प्रदान किए गए बिलिन प्रकार का उपयोग करना चाहिए। हालाँकि, क्विकसॉर्ट एल्गोरिथम को समझना शिक्षाप्रद है।

यहाँ मेरा लक्ष्य इस विषय को तोड़ना है जैसे कि यह आसानी से समझ में आता है और पाठक द्वारा संदर्भ सामग्री पर वापस जाने के बिना प्रतिरूप है।

Quicksort एल्गोरिथ्म अनिवार्य रूप से निम्नलिखित है:

  1. एक पिवट डेटा पॉइंट चुनें।
  2. सभी डेटा बिंदुओं को धुरी से नीचे की स्थिति की तुलना में कम (नीचे) की ओर ले जाएँ - उन लोगों को धुरी से ऊपर या ऊपर (ऊपर) की स्थिति में ले जाएँ।
  3. एल्गोरिथ्म को धुरी के ऊपर और नीचे के क्षेत्रों में लागू करें

यदि डेटा को बेतरतीब ढंग से वितरित किया जाता है, तो पहला डेटा बिंदु चुनना क्योंकि धुरी एक यादृच्छिक चयन के बराबर है।

पठनीय उदाहरण:

सबसे पहले, एक पठनीय उदाहरण देखें, जो मध्यवर्ती मूल्यों को इंगित करने के लिए टिप्पणियों और चर नामों का उपयोग करता है:

def quicksort(xs):
    """Given indexable and slicable iterable, return a sorted list"""
    if xs: # if given list (or tuple) with one ordered item or more: 
        pivot = xs[0]
        # below will be less than:
        below = [i for i in xs[1:] if i < pivot] 
        # above will be greater than or equal to:
        above = [i for i in xs[1:] if i >= pivot]
        return quicksort(below) + [pivot] + quicksort(above)
    else: 
        return xs # empty list

यहां प्रदर्शित एल्गोरिथ्म और कोड को पुनर्स्थापित करने के लिए - हम धुरी के ऊपर मूल्यों को दाईं ओर ले जाते हैं, और धुरी के बाईं ओर नीचे मान, और फिर उन विभाजनों को पास करने के लिए समान फ़ंक्शन को पास करते हैं।

golfed:

यह 88 वर्णों के लिए गढ़ा जा सकता है:

q=lambda x:x and q([i for i in x[1:]if i<=x[0]])+[x[0]]+q([i for i in x[1:]if i>x[0]])

यह देखने के लिए कि हम वहाँ कैसे पहुँचते हैं, पहले अपना पठनीय उदाहरण लेते हैं, टिप्पणियों और डोकस्ट्रिंग्स को हटाते हैं, और पिवट इन-प्लेस पाते हैं:

def quicksort(xs):
    if xs: 
        below = [i for i in xs[1:] if i < xs[0]] 
        above = [i for i in xs[1:] if i >= xs[0]]
        return quicksort(below) + [xs[0]] + quicksort(above)
    else: 
        return xs

अब नीचे और ऊपर, इन-प्लेस खोजें:

def quicksort(xs):
    if xs: 
        return (quicksort([i for i in xs[1:] if i < xs[0]] )
                + [xs[0]] 
                + quicksort([i for i in xs[1:] if i >= xs[0]]))
    else: 
        return xs

अब, यह जानते हुए कि andयदि गलत है, तो पूर्व तत्व को लौटाता है, यदि यह सत्य है, तो यह निम्नलिखित तत्व का मूल्यांकन करता है और लौटाता है, हमारे पास:

def quicksort(xs):
    return xs and (quicksort([i for i in xs[1:] if i < xs[0]] )
                   + [xs[0]] 
                   + quicksort([i for i in xs[1:] if i >= xs[0]]))

चूंकि लैम्ब्डा एक एकल प्रतिक्षेप लौटाता है, और हमने एक एकल अभिव्यक्ति को सरल बनाया है (भले ही यह अधिक अपठनीय है) अब हम एक लैम्ब्डा का उपयोग कर सकते हैं:

quicksort = lambda xs: (quicksort([i for i in xs[1:] if i < xs[0]] )
                        + [xs[0]] 
                        + quicksort([i for i in xs[1:] if i >= xs[0]]))

और हमारे उदाहरण को कम करने के लिए, फ़ंक्शन और चर नामों को एक अक्षर पर छोटा करें, और व्हाट्सएप को समाप्त करें जिसकी आवश्यकता नहीं है।

q=lambda x:x and q([i for i in x[1:]if i<=x[0]])+[x[0]]+q([i for i in x[1:]if i>x[0]])

ध्यान दें कि यह लैम्बडा, अधिकांश कोड गोल्फिंग की तरह, बल्कि बुरी शैली है।

इन-प्लेस क्विकॉर्ट, होरे विभाजन योजना का उपयोग करते हुए

पूर्व कार्यान्वयन अनावश्यक अतिरिक्त सूचियों का एक बहुत बनाता है। अगर हम ऐसा कर सकते हैं, तो हम जगह बर्बाद करने से बचेंगे।

नीचे कार्यान्वयन होरे विभाजन योजना का उपयोग करता है, जिसे आप विकिपीडिया के बारे में अधिक पढ़ सकते हैं (लेकिन हमने स्पष्ट रूप से प्रति partition()कॉल के बजाय लूप शब्दार्थ का उपयोग करके और कॉलिंग चरणों को समाप्त करने के लिए चलते हुए प्रति कॉल पर 4 निरर्थक गणनाओं को हटा दिया है बाहरी जबकि लूप।)।

def quicksort(a_list):
    """Hoare partition scheme, see https://en.wikipedia.org/wiki/Quicksort"""
    def _quicksort(a_list, low, high):
        # must run partition on sections with 2 elements or more
        if low < high: 
            p = partition(a_list, low, high)
            _quicksort(a_list, low, p)
            _quicksort(a_list, p+1, high)
    def partition(a_list, low, high):
        pivot = a_list[low]
        while True:
            while a_list[low] < pivot:
                low += 1
            while a_list[high] > pivot:
                high -= 1
            if low >= high:
                return high
            a_list[low], a_list[high] = a_list[high], a_list[low]
            low += 1
            high -= 1
    _quicksort(a_list, 0, len(a_list)-1)
    return a_list

यकीन नहीं होता कि मैंने इसे पूरी तरह से जांच लिया है:

def main():
    assert quicksort([1]) == [1]
    assert quicksort([1,2]) == [1,2]
    assert quicksort([1,2,3]) == [1,2,3]
    assert quicksort([1,2,3,4]) == [1,2,3,4]
    assert quicksort([2,1,3,4]) == [1,2,3,4]
    assert quicksort([1,3,2,4]) == [1,2,3,4]
    assert quicksort([1,2,4,3]) == [1,2,3,4]
    assert quicksort([2,1,1,1]) == [1,1,1,2]
    assert quicksort([1,2,1,1]) == [1,1,1,2]
    assert quicksort([1,1,2,1]) == [1,1,1,2]
    assert quicksort([1,1,1,2]) == [1,1,1,2]

निष्कर्ष

यह एल्गोरिथ्म अक्सर कंप्यूटर विज्ञान पाठ्यक्रमों में पढ़ाया जाता है और नौकरी के लिए साक्षात्कार के लिए कहा जाता है। यह हमें पुनरावृत्ति और विभाजन और जीत के बारे में सोचने में मदद करता है।

पाइथन में क्विकॉर्ट बहुत व्यावहारिक नहीं है क्योंकि हमारी बिल्ट टाइमसॉर्ट एल्गोरिथ्म काफी कुशल है, और हमारे पास पुनरावृत्ति सीमाएं हैं। हम सूची को इन-प्लेस के साथ सॉर्ट करने list.sortया नई सॉर्ट की गई सूचियों को बनाने की अपेक्षा करेंगे sorted- जिनमें से दोनों में तर्क keyऔर reverseतर्क हो।


आपका partitionकार्य के लिए सही ढंग से काम करने के लिए नहीं लग रहे हैं: partition([5,4,3,2,1], 0, 4)। प्रत्याशित रिटर्न इंडेक्स 4 है, जबकि यह 3 रिटर्न करता है।
मैटिनो

@matino यह उम्मीद कहां से आई? मेरा मानना ​​है कि मैंने एल्गोरिथ्म को सरल बनाया (जैसा कि इस जवाब को लिखते समय विकिपीडिया पर कहा गया है), हालांकि मैं गलत हो सकता हूं, या शायद कम कुशल हो सकता हूं। यदि आप एक ऐसा टेस्ट-केस पा सकते हैं जिसके लिए पूरा क्विकर फंक्शन फेल हो जाए, तो यह मददगार होगा।
हारून हॉल

@AaronHall जब मैंने धुरी = a_list [उच्च] को चुना, लेकिन मैं अभी यह पता नहीं लगा सकता कि यह कैसे काम करता है। क्या आप मदद कर सकते हैं ?
किउलंग

@ मैतीनो मुझे वही भ्रम था! विभाजन का कार्य ठीक है, यह संतुष्ट करता है कि आप जो अपेक्षा कर रहे हैं उससे कमज़ोर है - यह उस सटीक स्थान को खोजने की ज़रूरत नहीं है जो बाएँ और दाएँ को अलग करता है और धुरी से छोटा और बड़ा होता है। यह केवल एक गैर तुच्छ विभाजन की गारंटी देता है और लौटे हुए सूचकांक के सभी बाएं लौटे हुए सूचकांक के मुकाबले छोटे होते हैं।
ड्रोर स्पीसर

21

इसके पहले से ही कई उत्तर हैं, लेकिन मुझे लगता है कि यह दृष्टिकोण सबसे साफ कार्यान्वयन है:

def quicksort(arr):
    """ Quicksort a list

    :type arr: list
    :param arr: List to sort
    :returns: list -- Sorted list
    """
    if not arr:
        return []

    pivots = [x for x in arr if x == arr[0]]
    lesser = quicksort([x for x in arr if x < arr[0]])
    greater = quicksort([x for x in arr if x > arr[0]])

    return lesser + pivots + greater

आप निश्चित रूप से चर में सब कुछ छोड़ सकते हैं और उन्हें सीधे इस तरह वापस कर सकते हैं:

def quicksort(arr):
    """ Quicksort a list

    :type arr: list
    :param arr: List to sort
    :returns: list -- Sorted list
    """
    if not arr:
        return []

    return quicksort([x for x in arr if x < arr[0]]) \
        + [x for x in arr if x == arr[0]] \
        + quicksort([x for x in arr if x > arr[0]])

11
पर!)? क्या यह 'धीमा' है?
स्कॉट 混合

3
मेरा मानना ​​है कि पहले कोड उदाहरण में यह '[कम] और' [अधिक] 'के बजाय' कम 'और' अधिक 'होना चाहिए - अन्यथा आप फ्लैट के बजाय नेस्टेड सूचियों के साथ समाप्त हो जाएंगे।
ऐलिस

@ सेट @ still मैं अभी भी समय जटिलता सीख रहा हूं, क्या आप विस्तार से बता सकते हैं कि यह कार्यान्वयन क्यों है O(N!)? नेस्टेड सूची को मानते हुए [lesser]और [greater]टाइपोस हैं, क्या यह औसत नहीं O(3N logN)होगा जो अपेक्षित औसत को कम करेगा O(N logN)? दी गई है, 3 सूची comps अनावश्यक काम करते हैं ..
क्रिसपी

@ यदि आप एक उल्टे क्रम की सूची को क्रमबद्ध करते हैं, तो 5,4,3,2,1 जैसे
स्कॉट 混合 10

@ सही 理论 worst आप सही हैं कि त्वरित-प्रकार का सबसे खराब-रन रन समय धीमा quick (n ^ 2) है, लेकिन "एल्गोरिदम के लिए परिचय" के अनुसार, औसत-केस चलने का समय 混合 (n lg n) है। और, इससे भी महत्वपूर्ण बात यह है कि आम तौर पर जल्दी
छंटनी करने वाले

6

कार्यात्मक दृष्टिकोण:

def qsort(list):
    if len(list) < 2:
        return list

    pivot = list.pop()
    left = filter(lambda x: x <= pivot, list)
    right = filter(lambda x: x > pivot, list)

    return qsort(left) + [pivot] + qsort(right)

सूची अजगर में आरक्षित है। अपने कोड का संशोधित संस्करण यहां देखें: gist.github.com/kunthar/9d8962e1438e93f50dc6dd94d503af3d
कुंतार

akarca और @ kunthar ये समाधान python2 या python3 दोनों में से किसी एक तत्व को सूची में से हर बार चलाने के बाद, इसलिए सूची को नष्ट कर देगा। यहाँ एक निश्चित संस्करण है: gist.github.com/joshuatvernon/634e0d912401899af0fdc4e23c94192b
joshuatvernon


4

ग्रॉकिंग एल्गोरिदम से आसान कार्यान्वयन

def quicksort(arr):
    if len(arr) < 2:
        return arr #base case
    else:
        pivot = arr[0]
        less = [i for i in arr[1:] if i <= pivot] 
        more = [i for i in arr[1:] if i > pivot]
        return quicksort(less) + [pivot] + quicksort(more)

3

मुझे लगता है कि दोनों उत्तर यहां दी गई सूची के लिए ठीक काम करते हैं (जो मूल प्रश्न का उत्तर देते हैं), लेकिन यदि कोई अद्वितीय मान वाला सरणी पारित हो जाता है, तो वह टूट जाएगा। इसलिए पूर्णता के लिए, मैं केवल प्रत्येक में छोटी त्रुटि को इंगित करूंगा और समझाऊंगा कि उन्हें कैसे ठीक किया जाए।

निम्नलिखित सरणी सॉर्ट करने के लिए कोशिश कर रहा है उदाहरण के लिए [12,4,5,6,7,3,1,15,1] (ध्यान दें कि 1 प्रकट होता है दो बार) के साथ Brionius एल्गोरिथ्म .. कुछ बिंदु पर के साथ खत्म हो जाएगा कम सरणी खाली और मूल्यों की एक जोड़ी के साथ समान सरणी (1,1) जिसे अगले पुनरावृत्ति और लेन ()> 1 में अलग नहीं किया जा सकता है ... इसलिए आप एक अनंत लूप के साथ समाप्त करेंगे

यदि आप अपने बराबर सरणी में कॉल नहीं करके कम या ज्यादा बेहतर हैं, तो इसे रिटर्निंग ऐरे द्वारा ठीक कर सकते हैं , जैसा कि zangw उत्तर में है

def sort(array=[12,4,5,6,7,3,1,15]):
    less = []
    equal = []
    greater = []

    if len(array) > 1:
        pivot = array[0]
        for x in array:
            if x < pivot:
                less.append(x)
            if x == pivot:
                equal.append(x)
            if x > pivot:
                greater.append(x)

        # Don't forget to return something!
        return sort(less)+ equal +sort(greater)  # Just use the + operator to join lists
    # Note that you want equal ^^^^^ not pivot
    else:  # You need to hande the part at the end of the recursion - when you only have one element in your array, just return the array.
        return array

धर्मांध समाधान भी टूट जाता है, लेकिन एक अलग कारण के लिए, यह पुनरावर्तन लाइन में रिटर्न क्लॉज को याद कर रहा है , जिसके कारण कुछ बिंदु पर कोई भी वापस नहीं आएगा और इसे एक सूची में जोड़ने की कोशिश करेगा ...।

इसे ठीक करने के लिए बस उस लाइन पर वापस लौटें

def qsort(arr): 
   if len(arr) <= 1:
      return arr
   else:
      return qsort([x for x in arr[1:] if x<arr[0]]) + [arr[0]] + qsort([x for x in arr[1:] if x>=arr[0]])

वैसे, संक्षिप्त संस्करण में लंबे समय की तुलना में कम प्रदर्शन होता है, क्योंकि यह सूची की समझ में दो बार सरणी को पुनरावृत्त कर रहा है।
फेडेएन

3

यह Hoare विभाजन योजना का उपयोग करके क्विकॉर्ट का एक संस्करण है और कम स्वैप और स्थानीय चर के साथ

def quicksort(array):
    qsort(array, 0, len(array)-1)

def qsort(A, lo, hi):
    if lo < hi:
        p = partition(A, lo, hi)
        qsort(A, lo, p)
        qsort(A, p + 1, hi)

def partition(A, lo, hi):
    pivot = A[lo]
    i, j = lo-1, hi+1
    while True:
      i += 1
      j -= 1
      while(A[i] < pivot): i+= 1
      while(A[j] > pivot ): j-= 1

      if i >= j: 
          return j

      A[i], A[j] = A[j], A[i]


test = [21, 4, 1, 3, 9, 20, 25, 6, 21, 14]
print quicksort(test)

3

विभाजन - एक सरणी को एक धुरी से विभाजित करें जो छोटे तत्व बाईं ओर जाते हैं और अधिक से अधिक हाथी दाएं या इसके विपरीत चलते हैं। एक धुरी एक सरणी से एक यादृच्छिक तत्व हो सकता है। इस एल्गोरिथ्म को बनाने के लिए हमें यह जानना होगा कि किसी एरे के इंडेक्स की शुरुआत और अंत क्या है और पिवट कहां है। फिर दो सहायक बिंदुओं L, R को सेट करें।

तो हमारे पास एक सरणी उपयोगकर्ता है [..., शुरू, ..., अंत, ...]

L और R पॉइंटर्स की प्रारंभ स्थिति
[..., शुरू, अगला, ..., अंत, ...]
     R L

जबकि L <अंत
  1. यदि कोई उपयोगकर्ता [धुरी]> उपयोगकर्ता [L] है तो R को एक से घुमाएं और उपयोगकर्ता [R] को उपयोगकर्ता के साथ स्वैप करें [L]
  2. एक से L को स्थानांतरित करें

उपयोगकर्ता के साथ स्वैप करने के बाद [R] उपयोगकर्ता के साथ [धुरी]

त्वरित सॉर्ट - विभाजन एल्गोरिथ्म का उपयोग करें जब तक कि एक पिवट द्वारा विभाजन के प्रत्येक अगले हिस्से में इंडेक्स को अधिक से अधिक या एंड इंडेक्स के बराबर शुरू नहीं किया जाएगा।

def qsort(user, begin, end):

    if begin >= end:
        return

    # partition
    # pivot = begin
    L = begin+1
    R = begin
    while L < end:
        if user[begin] > user[L]:
            R+=1
            user[R], user[L] = user[L], user[R]
        L+= 1
    user[R], user[begin] = user[begin], user[R]

    qsort(user, 0, R)
    qsort(user, R+1, end)

tests = [
    {'sample':[1],'answer':[1]},
    {'sample':[3,9],'answer':[3,9]},
    {'sample':[1,8,1],'answer':[1,1,8]},
    {'sample':[7,5,5,1],'answer':[1,5,5,7]},
    {'sample':[4,10,5,9,3],'answer':[3,4,5,9,10]},
    {'sample':[6,6,3,8,7,7],'answer':[3,6,6,7,7,8]},
    {'sample':[3,6,7,2,4,5,4],'answer':[2,3,4,4,5,6,7]},
    {'sample':[1,5,6,1,9,0,7,4],'answer':[0,1,1,4,5,6,7,9]},
    {'sample':[0,9,5,2,2,5,8,3,8],'answer':[0,2,2,3,5,5,8,8,9]},
    {'sample':[2,5,3,3,2,0,9,0,0,7],'answer':[0,0,0,2,2,3,3,5,7,9]}
]

for test in tests:

    sample = test['sample'][:]
    answer = test['answer']

    qsort(sample,0,len(sample))

    print(sample == answer)

कृपया अपने कोड / अतिरिक्त को स्पष्ट करें ताकि ओपी और भविष्य के विचार अधिक लाभान्वित हो सकें।
उमर आइना

2

या यदि आप एक-लाइनर को पसंद करते हैं जो कि C / C ++ वैरैग, लैम्ब्डा एक्सप्रेशन और यदि एक्सप्रेशन के बराबर पायथन को दिखाता है:

qsort = lambda x=None, *xs: [] if x is None else qsort(*[a for a in xs if a<x]) + [x] + qsort(*[a for a in xs if a>=x])

2
def quick_sort(self, nums):
    def helper(arr):
        if len(arr) <= 1: return arr
        #lwall is the index of the first element euqal to pivot
        #rwall is the index of the first element greater than pivot
        #so arr[lwall:rwall] is exactly the middle part equal to pivot after one round
        lwall, rwall, pivot = 0, 0, 0
        #choose rightmost as pivot
        pivot = arr[-1]
        for i, e in enumerate(arr):
            if e < pivot:
                #when element is less than pivot, shift the whole middle part to the right by 1
                arr[i], arr[lwall] = arr[lwall], arr[i]
                lwall += 1
                arr[i], arr[rwall] = arr[rwall], arr[i]
                rwall += 1
            elif e == pivot:
                #when element equals to pivot, middle part should increase by 1
                arr[i], arr[rwall] = arr[rwall], arr[i]
                rwall += 1
            elif e > pivot: continue
        return helper(arr[:lwall]) + arr[lwall:rwall] + helper(arr[rwall:])
    return helper(nums)

2

मुझे पता है कि कई लोगों ने इस सवाल का सही जवाब दिया है और मुझे उन्हें पढ़ने में मज़ा आया। मेरा जवाब लगभग जंगल जैसा ही है, लेकिन मुझे लगता है कि पिछले योगदानकर्ताओं ने नेत्रहीन यह समझाने का एक अच्छा काम नहीं किया कि चीजें वास्तव में कैसे काम करती हैं ... इसलिए यहां दूसरों की मदद करने का मेरा प्रयास है जो भविष्य में इस प्रश्न / उत्तर पर जा सकते हैं। Quicksort कार्यान्वयन के लिए सरल समाधान।

यह कैसे काम करता है ?

  1. हम मूल रूप से अपनी सूची से हमारी धुरी के रूप में पहली वस्तु का चयन करते हैं और फिर हम दो उप सूची बनाते हैं।
  2. हमारी पहली सबलिस्ट में वे आइटम हैं जो धुरी से कम हैं
  3. हमारी दूसरी सबलिस्ट में हमारे आइटम हैं जो धुरी से अधिक या बराबर हैं
  4. फिर हम उनमें से प्रत्येक को त्वरित रूप से सॉर्ट करते हैं और हम अंतिम परिणाम प्राप्त करने के लिए उन्हें पहले समूह + पिवट + और दूसरे समूह को जोड़ते हैं।

यहाँ दृश्य के साथ एक उदाहरण है इसके साथ जाने के लिए ... (धुरी) 9,11,2,0

औसत: n का n लॉग

बदतर मामला: एन ^ 2

यहाँ छवि विवरण दर्ज करें

कोड:

def quicksort(data):
if (len(data) < 2):
    return data
else:
    pivot = data[0]  # pivot
    #starting from element 1 to the end
    rest = data[1:]
    low = [each for each in rest if each < pivot]
    high = [each for each in rest if each >= pivot]
    return quicksort(low) + [pivot] + quicksort(high)

आइटम = [9,11,2,0] प्रिंट (क्विकॉर्टोर्ट (आइटम))


2

एल्गोरिथ्म में दो सीमाएँ होती हैं, जिनमें एक धुरी से कम तत्व होते हैं (सूचकांक "j" द्वारा ट्रैक किए गए) और दूसरे में धुरी (सूचकांक "i" द्वारा ट्रैक किए गए) से अधिक तत्व होते हैं।

प्रत्येक पुनरावृत्ति में, एक नया तत्व j वृद्धी द्वारा संसाधित किया जाता है।

अपरिवर्तनीय: -

  1. धुरी और i के बीच के सभी तत्व धुरी से कम हैं, और
  2. i और j के बीच के सभी तत्व धुरी से अधिक हैं।

यदि आक्रमणकारी का उल्लंघन किया जाता है, तो ith और jth तत्वों की अदला-बदली की जाती है, और मुझे बढ़ा दिया जाता है।

सभी तत्वों को संसाधित करने के बाद, और धुरी के विभाजन के बाद सब कुछ, धुरी तत्व को अंतिम तत्व से छोटा करके स्वैप किया जाता है।

धुरी तत्व अब अनुक्रम में अपने सही स्थान पर होगा। इसके पहले वाले तत्व इससे कम होंगे और इसके बाद वाले इससे अधिक होंगे, और वे अनसोल्ड रहेंगे।

def quicksort(sequence, low, high):
    if low < high:    
        pivot = partition(sequence, low, high)
        quicksort(sequence, low, pivot - 1)
        quicksort(sequence, pivot + 1, high)

def partition(sequence, low, high):
    pivot = sequence[low]
    i = low + 1
    for j in range(low + 1, high + 1):
        if sequence[j] < pivot:
            sequence[j], sequence[i] = sequence[i], sequence[j]
            i += 1
    sequence[i-1], sequence[low] = sequence[low], sequence[i-1]
    return i - 1

def main(sequence):
    quicksort(sequence, 0, len(sequence) - 1)
    return sequence

if __name__ == '__main__':
    sequence = [-2, 0, 32, 1, 56, 99, -4]
    print(main(sequence))

एक धुरी का चयन

एक "अच्छा" धुरी का परिणाम लगभग एक ही आकार के दो उप-अनुक्रम होंगे। निश्चित रूप से, एक धुरी तत्व को या तो भोले तरीके से चुना जा सकता है या अनुक्रम के माध्य की गणना करके।

एक धुरी का चयन करने का एक भोली कार्यान्वयन पहला या अंतिम तत्व होगा। इस मामले में सबसे खराब स्थिति तब होगी जब इनपुट अनुक्रम पहले से ही सॉर्ट या रिवर्स सॉर्ट किया जाएगा, क्योंकि बाद में से कोई एक खाली होगा जो प्रति पुनरावर्ती कॉल को हटाने के लिए केवल एक तत्व का कारण होगा।

एक पूरी तरह से संतुलित विभाजन प्राप्त किया जाता है जब धुरी अनुक्रम का औसत तत्व होता है। इसमें तत्त्वों की संख्या अधिक से अधिक और उससे कम होती है। यह दृष्टिकोण एक बेहतर समग्र समय की गारंटी देता है, लेकिन अधिक समय लेने वाला है।

धुरी के चयन का एक गैर-निर्धारक / यादृच्छिक तरीका एक तत्व को यादृच्छिक रूप से समान रूप से चुनना होगा। यह एक सरल और हल्का दृष्टिकोण है जो सबसे खराब स्थिति को कम करेगा और लगभग संतुलित विभाजन को भी जन्म देगा। यह अनुभवहीन दृष्टिकोण और धुरी के चयन के मध्य दृष्टिकोण के बीच एक संतुलन प्रदान करेगा।


2
def quicksort(array):
 if len(array) < 2:
  return array
 else:
  pivot = array[0]

 less = [i for i in array[1:] if i <= pivot]
 greater = [i for i in array[1:] if i > pivot]
 return quicksort(less) + [pivot] + quicksort(greater)

हालांकि यह कोड समस्या का समाधान प्रदान कर सकता है, लेकिन यह अत्यधिक अनुशंसा की जाती है कि आप इस कोड को प्रश्न का उत्तर क्यों और / या कैसे प्रदान करते हैं। कोड केवल उत्तर आमतौर पर लंबे समय में बेकार हो जाते हैं क्योंकि भविष्य के दर्शकों को इसी तरह की समस्याओं का सामना करना पड़ता है जो समाधान के पीछे के तर्क को समझ नहीं सकते हैं।
palaѕн

1
def quick_sort(array):
    return quick_sort([x for x in array[1:] if x < array[0]]) + [array[0]] \
        + quick_sort([x for x in array[1:] if x >= array[0]]) if array else []

1
def Partition(A,p,q):
    i=p
    x=A[i]
    for j in range(p+1,q+1):
        if A[j]<=x:
            i=i+1
            tmp=A[j]
            A[j]=A[i]
            A[i]=tmp
    l=A[p]
    A[p]=A[i]
    A[i]=l
    return i

def quickSort(A,p,q):
    if p<q:
        r=Partition(A,p,q)
        quickSort(A,p,r-1)
        quickSort(A,r+1,q)
    return A

1
कृपया यह बताएं कि आपका कोड क्या करता है और यह प्रश्न का उत्तर कैसे देता है। विशेष रूप से यह प्रश्न में पोस्ट किए गए कोड से कैसे संबंधित है। उत्तर ओपी और भविष्य के आगंतुकों को उनकी समस्या को डीबग करने और कैसे ठीक करने के लिए मार्गदर्शन देना चाहिए। यह बताते हुए कि आपके कोड के पीछे का विचार क्या है, इस मुद्दे को समझने और आपके समाधान को लागू करने या संशोधित करने में बहुत मदद करता है। स्टैक ओवरफ्लो एक कोड लेखन सेवा नहीं है, यह एक शिक्षण और सीखने की जगह है।
पालिक

1

माइकल टी। गुडरिक और रॉबर्टो तामासिया द्वारा एल्गोरिथम डिज़ाइन और एप्लिकेशन बुक से एक "सही" इन-प्लेस कार्यान्वयन [एल्गोरिदम 8.9, 8.11]:

from random import randint

def partition (A, a, b):
    p = randint(a,b)
    # or mid point
    # p = (a + b) / 2

    piv = A[p]

    # swap the pivot with the end of the array
    A[p] = A[b]
    A[b] = piv

    i = a     # left index (right movement ->)
    j = b - 1 # right index (left movement <-)

    while i <= j:
        # move right if smaller/eq than/to piv
        while A[i] <= piv and i <= j:
            i += 1
        # move left if greater/eq than/to piv
        while A[j] >= piv and j >= i:
            j -= 1

        # indices stopped moving:
        if i < j:
            # swap
            t = A[i]
            A[i] = A[j]
            A[j] = t
    # place pivot back in the right place
    # all values < pivot are to its left and 
    # all values > pivot are to its right
    A[b] = A[i]
    A[i] = piv

    return i

def IpQuickSort (A, a, b):

    while a < b:
        p = partition(A, a, b) # p is pivot's location

        #sort the smaller partition
        if p - a < b - p:
            IpQuickSort(A,a,p-1)
            a = p + 1 # partition less than p is sorted
        else:
            IpQuickSort(A,p+1,b)
            b = p - 1 # partition greater than p is sorted


def main():
    A =  [12,3,5,4,7,3,1,3]
    print A
    IpQuickSort(A,0,len(A)-1)
    print A

if __name__ == "__main__": main()

1

एल्गोरिथ्म में 4 सरल चरण हैं:

  1. सरणी को 3 अलग-अलग भागों में विभाजित करें: बाएं, धुरी और दाएं, जहां धुरी में केवल एक तत्व होगा। हम इस धुरी तत्व को सरणी के पहले तत्व के रूप में चुनते हैं
  2. संबंधित तत्वों को धुरी तत्व से तुलना करके संबंधित भाग में जोड़ें। (टिप्पणियों में स्पष्टीकरण)
  3. इस एल्गोरिथ्म को पुनर्जीवित करें जब तक कि सरणी के सभी तत्व छँट न जाएँ
  4. अंत में, बाएँ + धुरी + दाएं भागों से जुड़ें

अजगर में एल्गोरिथ्म के लिए कोड:

def my_sort(A):

      p=A[0]                                       #determine pivot element. 
      left=[]                                      #create left array
      right=[]                                     #create right array
      for i in range(1,len(A)):
        #if cur elem is less than pivot, add elem in left array
        if A[i]< p:
          left.append(A[i])         
          #the recurssion will occur only if the left array is atleast half the size of original array
          if len(left)>1 and len(left)>=len(A)//2:          
              left=my_sort(left)                            #recursive call
        elif A[i]>p: 
          right.append(A[i])                                #if elem is greater than pivot, append it to right array
          if len(right)>1 and len(right)>=len(A)//2:        # recurssion will occur only if length of right array is atleast the size of original array
              right=my_sort(right)
     A=left+[p]+right                                        #append all three part of the array into one and return it
     return A

my_sort([12,4,5,6,7,3,1,15])

इस एल्गोरिथ्म के साथ लेफ्ट और राइट भागों के साथ पुनरावृत्ति करें।


1

एक और त्वरित कार्यान्वयन:

# A = Array 
# s = start index
# e = end index
# p = pivot index
# g = greater than pivot boundary index

def swap(A,i1,i2):
  A[i1], A[i2] = A[i2], A[i1]

def partition(A,g,p):
    # O(n) - just one for loop that visits each element once
    for j in range(g,p):
      if A[j] <= A[p]:
        swap(A,j,g)
        g += 1

    swap(A,p,g)
    return g

def _quicksort(A,s,e):
    # Base case - we are sorting an array of size 1
    if s >= e:
      return

    # Partition current array
    p = partition(A,s,e)
    _quicksort(A,s,p-1) # Left side of pivot
    _quicksort(A,p+1,e) # Right side of pivot

# Wrapper function for the recursive one
def quicksort(A):
    _quicksort(A,0,len(A)-1)

A = [3,1,4,1,5,9,2,6,5,3,5,8,9,7,9,3,2,3,-1]

print(A)
quicksort(A)
print(A)

1

संस्करण पायथन 3.x के लिए : operatorमुख्य रूप से पठनीयता में सुधार करने के लिए मॉड्यूल का उपयोग करते हुए एक कार्यात्मक शैली ।

from operator import ge as greater, lt as lesser

def qsort(L): 
    if len(L) <= 1: return L
    pivot   = L[0]
    sublist = lambda op: [*filter(lambda num: op(num, pivot), L[1:])]

    return qsort(sublist(lesser))+ [pivot] + qsort(sublist(greater))

और के रूप में परीक्षण किया है

print (qsort([3,1,4,2,5]) == [1,2,3,4,5])

नाइस (जहां तक गैर-दस्तावेजी कोड चला जाता है), अगर के समान acarca की , आर्नोल्डो पी Figueira Figueira के और बिर्गर के वर्षों से उत्तर से चला। यकीन नहीं होता कि यह एक उत्तर है जब प्रश्न पढ़ता है … complete my code?lambdaपरिभाषित करने के लिए उपयोग करना sublist()कड़ाई से आवश्यक नहीं दिखता है।
ग्रेबर्ड

@greybeard वास्तव में, अर्नाल्टो का कोड पायथन 3 में संकलित नहीं था। इसके अलावा, sublistकेवल उपयोग करके कैसे परिभाषित किया जा सकता है filter? क्या यह भी संभव है?
जीवनदायिनी

1
(अस्थायी टिप्पणी: थिंकटीन 'की def- अभी तक छेड़छाड़ शुरू नहीं की थी क्योंकि मैं यह पता लगाने की कोशिश कर रहा हूं कि क्या अलग-अलग सूचियों (या, वैकल्पिक रूप से, एक के साथ एक सूची) के तत्वों को "वितरित" करने के लिए एक अधिक कुशल तरीका है श्रेणी "अन्य के बाद)।)
ग्रेबियर्ड

1

यहाँ एक आसान कार्यान्वयन है: -

def quicksort(array):
            if len(array) < 2:
                  return array
            else:
                  pivot= array[0]
                  less = [i for i in array[1:] if i <= pivot]

                  greater = [i for i in array[1:] if i > pivot]

                  return quicksort(less) + [pivot] + quicksort(greater)

print(quicksort([10, 5, 2, 3]))

0
  1. पहले हम सरणी में पहला मान pivot_value घोषित करते हैं और हम बाएं और दाएं निशान भी सेट करते हैं
  2. हम पहली बार लूप बनाते हैं, जबकि यह लूप तब होता है जब विभाजन प्रक्रिया को फिर से चलाने के लिए कहा जाता है यदि यह आवश्यक स्थिति को पूरा नहीं करता है
  3. तब हम विभाजन प्रक्रिया को लागू करते हैं
  4. दोनों विभाजन प्रक्रियाओं के चलने के बाद, हम यह देखने के लिए जांच करते हैं कि क्या यह उचित स्थिति को संतुष्ट करता है। यदि ऐसा होता है, तो हम इसे चिह्नित करते हैं, यदि हम बाएं और दाएं मानों को स्विच नहीं करते हैं और इसे फिर से लागू करते हैं
  5. एक बार इसके पूर्ण होने के बाद बाएँ और दाएँ मान को स्विच करें और स्प्लिट_ पॉइंट वापस करें

मैं नीचे कोड संलग्न कर रहा हूँ! पिवट वैल्यू के स्थान के कारण यह क्विकॉर्ट एक महान शिक्षण उपकरण है । चूंकि यह एक स्थिर स्थान पर है, आप कई बार इसके माध्यम से चल सकते हैं और वास्तव में यह लटका हुआ है कि यह कैसे काम करता है। व्यवहार में ओ (एन ^ 2) रनटाइम से बचने के लिए धुरी को यादृच्छिक करना सबसे अच्छा है।

def quicksort10(alist):
    quicksort_helper10(alist, 0, len(alist)-1)

def quicksort_helper10(alist, first, last):
    """  """
    if first < last:
        split_point = partition10(alist, first, last)
        quicksort_helper10(alist, first, split_point - 1)
        quicksort_helper10(alist, split_point + 1, last)

def partition10(alist, first, last):
    done = False
    pivot_value = alist[first]
    leftmark = first + 1
    rightmark = last
    while not done:
        while leftmark <= rightmark and alist[leftmark] <= pivot_value:
            leftmark = leftmark + 1
        while leftmark <= rightmark and alist[rightmark] >= pivot_value:
            rightmark = rightmark - 1

        if leftmark > rightmark:
            done = True
        else:
            temp = alist[leftmark]
            alist[leftmark] = alist[rightmark]
            alist[rightmark] = temp
    temp = alist[first]
    alist[first] = alist[rightmark]
    alist[rightmark] = temp
    return rightmark

0
def quick_sort(l):
    if len(l) == 0:
        return l
    pivot = l[0]
    pivots = [x for x in l if x == pivot]
    smaller = quick_sort([x for x in l if x < pivot])
    larger = quick_sort([x for x in l if x > pivot])
    return smaller + pivots + larger

18 अन्य उत्तर, जिनमें से आधे से अधिक ओपी के मूल प्रश्न का उत्तर है "तीन सरणियों को कैसे संक्षिप्त करें"। क्या आपका जवाब कुछ नया जोड़ता है?
तेइपेमम

0

विभाजन चरण में मुद्रित चर के साथ पूर्ण उदाहरण:

def partition(data, p, right):
    print("\n==> Enter partition: p={}, right={}".format(p, right))
    pivot = data[right]
    print("pivot = data[{}] = {}".format(right, pivot))

    i = p - 1  # this is a dangerous line

    for j in range(p, right):
        print("j: {}".format(j))
        if data[j] <= pivot:
            i = i + 1
            print("new i: {}".format(i))
            print("swap: {} <-> {}".format(data[i], data[j]))
            data[i], data[j] = data[j], data[i]

    print("swap2: {} <-> {}".format(data[i + 1], data[right]))
    data[i + 1], data[right] = data[right], data[i + 1]
    return i + 1


def quick_sort(data, left, right):
    if left < right:
        pivot = partition(data, left, right)
        quick_sort(data, left, pivot - 1)
        quick_sort(data, pivot + 1, right)

data = [2, 8, 7, 1, 3, 5, 6, 4]

print("Input array: {}".format(data))
quick_sort(data, 0, len(data) - 1)
print("Output array: {}".format(data))

0
def is_sorted(arr): #check if array is sorted
    for i in range(len(arr) - 2):
        if arr[i] > arr[i + 1]:
            return False
    return True

def qsort_in_place(arr, left, right): #arr - given array, #left - first element index, #right - last element index
    if right - left < 1: #if we have empty or one element array - nothing to do
        return
    else:
        left_point = left #set left pointer that points on element that is candidate to swap with element under right pointer or pivot element
        right_point = right - 1 #set right pointer that is candidate to swap with element under left pointer

        while left_point <= right_point: #while we have not checked all elements in the given array
            swap_left = arr[left_point] >= arr[right] #True if we have to move that element after pivot
            swap_right = arr[right_point] < arr[right] #True if we have to move that element before pivot

            if swap_left and swap_right: #if both True we can swap elements under left and right pointers
                arr[right_point], arr[left_point] = arr[left_point], arr[right_point]
                left_point += 1
                right_point -= 1
            else: #if only one True we don`t have place for to swap it
                if not swap_left: #if we dont need to swap it we move to next element
                    left_point += 1
                if not swap_right: #if we dont need to swap it we move to prev element
                    right_point -= 1

        arr[left_point], arr[right] = arr[right], arr[left_point] #swap left element with pivot

        qsort_in_place(arr, left, left_point - 1) #execute qsort for left part of array (elements less than pivot)
        qsort_in_place(arr, left_point + 1, right) #execute qsort for right part of array (elements most than pivot)

def main():
    import random
    arr = random.sample(range(1, 4000), 10) #generate random array
    print(arr)
    print(is_sorted(arr))
    qsort_in_place(arr, 0, len(arr) - 1)
    print(arr)
    print(is_sorted(arr))

if __name__ == "__main__":
    main()

1
कृपया कुछ स्पष्टीकरण प्रदान करें
राय

0

यह एल्गोरिदम पुनरावर्ती कार्यों का उपयोग नहीं करता है।

आज्ञा Nदेना किसी भी संख्या के साथ सूची len(N) > 0K = [N]निम्न प्रोग्राम सेट और निष्पादित करें।

नोट: यह एक स्थिर छँटाई एल्गोरिथ्म है।

def BinaryRip2Singletons(K, S):
    K_L = []
    K_P = [ [K[0][0]] ] 
    K_R = []
    for i in range(1, len(K[0])):
        if   K[0][i] < K[0][0]:
            K_L.append(K[0][i])
        elif K[0][i] > K[0][0]:
            K_R.append(K[0][i])
        else:
            K_P.append( [K[0][i]] )
    K_new = [K_L]*bool(len(K_L)) + K_P + [K_R]*bool(len(K_R)) + K[1:]
    while len(K_new) > 0:
        if len(K_new[0]) == 1:
            S.append(K_new[0][0])
            K_new = K_new[1:]
        else: 
            break
    return K_new, S

N = [16, 19, 11, 15, 16, 10, 12, 14, 4, 10, 5, 2, 3, 4, 7, 1]
K = [ N ]
S = []

print('K =', K, 'S =', S)
while len(K) > 0:
    K, S = BinaryRip2Singletons(K, S)
    print('K =', K, 'S =', S)

कार्यक्रम के बाहर:

K = [[16, 19, 11, 15, 16, 10, 12, 14, 4, 10, 5, 2, 3, 4, 7, 1]] S = []
K = [[11, 15, 10, 12, 14, 4, 10, 5, 2, 3, 4, 7, 1], [16], [16], [19]] S = []
K = [[10, 4, 10, 5, 2, 3, 4, 7, 1], [11], [15, 12, 14], [16], [16], [19]] S = []
K = [[4, 5, 2, 3, 4, 7, 1], [10], [10], [11], [15, 12, 14], [16], [16], [19]] S = []
K = [[2, 3, 1], [4], [4], [5, 7], [10], [10], [11], [15, 12, 14], [16], [16], [19]] S = []
K = [[5, 7], [10], [10], [11], [15, 12, 14], [16], [16], [19]] S = [1, 2, 3, 4, 4]
K = [[15, 12, 14], [16], [16], [19]] S = [1, 2, 3, 4, 4, 5, 7, 10, 10, 11]
K = [[12, 14], [15], [16], [16], [19]] S = [1, 2, 3, 4, 4, 5, 7, 10, 10, 11]
K = [] S = [1, 2, 3, 4, 4, 5, 7, 10, 10, 11, 12, 14, 15, 16, 16, 19]

0

शायद सिर्फ एक प्राथमिकता की बात है, लेकिन मैं अपने कार्यों के शीर्ष पर सत्यापन जोड़ना पसंद करता हूं।

def quicksort(arr):
  if len(arr) <= 1:
    return arr

  left  = []
  right = []
  equal = []
  pivot = arr[-1]
  for num in arr:
    if num < pivot:
      left.append(num)
    elif num == pivot:
      equal.append(num)
    else:
      right.append(num)

  return quicksort(left) + equal + quicksort(right)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.