Quicksort với Python


94

Tôi hoàn toàn mới với python và tôi đang cố gắng triển khai quicksort trong đó. Ai đó có thể vui lòng giúp tôi hoàn thành mã của tôi?

Tôi không biết làm thế nào để nối ba mảng và in chúng.

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)

Để kết hợp danh sách, bạn có thể sử dụng toán tử cộng my_list = list1 + list2 + .... Hoặc giải nén danh sách thành danh sách mớimy_list = [*list1, *list2]
Mark Mishyn

Câu trả lời:


255
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
Bạn cũng có thể trao đổi trên các 2 ifs trong vòng lặp for với elifelseđể tránh làm sự so sánh không cần thiết
SlimPDX

13
Đây là âm thanh giống như merge sort không nhanh chóng loại
Emad Mokhtar

47
Nó thực sự là mã python tốt nhất và dễ đọc nhất mà tôi tìm thấy cho quicksort ở bất cứ đâu . Không có chỉ số, không có chức năng trợ giúp, hiển thị rõ ràng ý chính của thuật toán (chia và chinh phục). (Giá trị mặc định cho mảng là khá cần thiết)
cmantas

20
@jsmedmar nó sẽ sử dụng nhiều bộ nhớ hơn phiên bản tại chỗ, hãy xem câu trả lời của suquant để biết sắp xếp nhanh tại chỗ.
John

15
Rất dễ đọc nhưng điều này không đánh bại mục đích của việc sắp xếp nhanh vì điều này sẽ không đạt được loại 'tại chỗ'? @RasmiRanjanNayak sắp xếp ở đây là hàm do người dùng định nghĩa (nó là một lệnh gọi đệ quy), không phải bất kỳ hàm nào được tích hợp sẵn.
Maksood

161

Sắp xếp nhanh chóng mà không cần thêm bộ nhớ (tại chỗ)

Sử dụng:

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
Đây phải là câu trả lời được chọn, vì quicksort thường là thuật toán được lựa chọn (hơn là sắp xếp hợp nhất) vì nó sắp xếp đúng vị trí (và vẫn cho thời gian chạy O (nlogn)).
BoltzmannBrain

3
if end is None:sẽ được kiểm tra nhiều lần, và chỉ một lần là như vậy True. Bạn nên đặt nó trong một hàm wrapper để nó chỉ được gọi một lần.
Gillespie

Rất tiếc, bruhs, @mksteve là đúng và dòng này không chính xác. Ngoài ra, array[pivot], array[begin] = array[begin], array[pivot]nên thay thế beginbằng end.
Ryan J McCall

2
Mặc dù tại chỗ là tốt, nhưng điều này diễn ra chậm và có lỗi do chạm vào độ sâu đệ quy tối đa khi có nhiều mục. xem repl.it/@almenon/quicksorts?language=python3
Almenon

@mksteve và Ryan, tôi đã thử nghiệm những thay đổi này và nó phá vỡ sự phân loại
aljgom

68

Có một phiên bản ngắn gọn và đẹp đẽ khác

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!!!

Hãy để tôi giải thích các mã trên để biết chi tiết

  1. chọn phần tử đầu tiên của mảng arr[0]làm trụ

    [arr[0]]

  2. qsort những phần tử của mảng nhỏ hơn pivot với List Comprehension

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

  3. qsort những phần tử của mảng lớn hơn pivot với List Comprehension

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


15
@zangw các lý do có thể xảy ra cho một downvote: 1) Thời gian chạy bậc hai trên các mảng đã được sắp xếp hoặc đảo ngược 2) Giải pháp không đúng chỗ. Vì vậy, một thực hiện khủng khiếp, xin lỗi.
alisianoi

16
không thể đọc được, bạn thực sự đang cố gắng giảm thiểu số dòng? Mã được máy móc giải thích, nhưng con người hiểu được.
jsmedmar

4
@AlfredoGallegos, toàn bộ điểm của nhanh chóng là nó diễn ra tại chỗ, bạn cũng có thể triển khai hợp nhất-sắp xếp nếu bạn định làm điều này.
Padraic Cunningham

14
Những bình luận này có thật không? Nếu bạn muốn hiệu suất, hãy sử dụng sorted, điều này rõ ràng là dành cho mục đích giáo dục. Và nó có thể đọc được, dễ đọc hơn câu trả lời được chấp nhận.
Nobilis

4
FWIW, tôi nghĩ đây là cách triển khai dễ đọc nhất trong số chúng. Nó cho thấy cấu trúc đệ quy của thuật toán tốt hơn bất kỳ câu trả lời nào khác. Tất nhiên, hiệu suất sẽ không quá tuyệt vời.
Giải quyết Vào

36

Câu trả lời này là một QuickSort tại chỗ cho Python 2.x. Câu trả lời của tôi là giải thích về giải pháp tại chỗ từ Mã Rosetta, giải pháp này cũng hoạt động 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)

Và nếu bạn sẵn sàng từ bỏ tài sản tại chỗ, bên dưới là một phiên bản khác minh họa rõ hơn những ý tưởng cơ bản đằng sau quicksort. Ngoài tính dễ đọc, ưu điểm khác của nó là ổn định (các phần tử bằng nhau xuất hiện trong danh sách được sắp xếp theo thứ tự mà chúng từng có trong danh sách không được sắp xếp). Đặc tính ổn định này không giữ được với việc triển khai tại chỗ ít tốn bộ nhớ hơn được trình bày ở trên.

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

Cảm ơn đã chia sẻ giải pháp này. Bạn có thể vui lòng giúp chúng tôi hiểu sự phức tạp về thời gian không? Tôi thấy rằng đệ quy sẽ gọi nó 15 lần. Trong số này có 8 lệnh gọi hàm hợp lệ. Điều đó có nghĩa là độ phức tạp thời gian là O (n) cho giải pháp đầu tiên và độ phức tạp không gian là O (1) như là sắp xếp tại chỗ của nó?
ForeverLearner

@Tammy có vẻ như bạn hiểu sai ký hiệu chữ O lớn. Hơn nữa, tôi thực sự không hiểu câu hỏi của bạn. Bạn có thể hỏi nó như một cái riêng biệt? Cuối cùng, Quicksort như một thuật toán chạy trong thời gian O (n logn) và O (n) không gian.
alisianoi 21/10/15

3
Lỗi của tôi. Tại sao tôi lại đếm đệ quy ?? :-) Chà, 15 lần đệ quy là [1 cuộc gọi (Mức 0) + 2 cuộc gọi (Phân vùng cấp 1) + 4 cuộc gọi (Phân vùng cấp 2) + 8 cuộc gọi (Phân vùng cấp 3 hoặc các nút Lá). Vì vậy, chúng ta vẫn có chiều cao là (lg8 + 1) = lgn. Tổng tính toán ở mỗi cấp là cho c1 (một số chi phí) * n. Do đó O (n lgn). Độ phức tạp về không gian, đối với một trao đổi tại chỗ = O (1). Do đó với n phần tử = O (n). Cảm ơn vì con trỏ.
ForeverLearner

3
đây là đi xa và quicksort python tốt nhất trên internet, và nó buồn khi nhìn thấy nó bị chôn vùi dưới O rất nhiều (n) các giải pháp không gian :(
Sasha Kondrashov

Cảm ơn những lời tốt đẹp @Timofey. Bạn có thể muốn xem repo thuật toán của tôi, nó có các phiên bản khác của các loại, thuật toán đồ thị, v.v. github.com/alisianoi/algos-py
alisianoi

23

Quicksort với Python

Trong cuộc sống thực, chúng ta nên luôn sử dụng loại nội trang do Python cung cấp. Tuy nhiên, hiểu được thuật toán quicksort là hướng dẫn.

Mục tiêu của tôi ở đây là chia nhỏ chủ đề sao cho người đọc dễ hiểu và có thể nhân rộng mà không cần phải quay lại tài liệu tham khảo.

Thuật toán quicksort về cơ bản là như sau:

  1. Chọn một điểm dữ liệu xoay.
  2. Di chuyển tất cả các điểm dữ liệu nhỏ hơn (bên dưới) trục quay đến vị trí bên dưới trục - di chuyển những điểm lớn hơn hoặc bằng (bên trên) trục lên vị trí phía trên nó.
  3. Áp dụng thuật toán cho các khu vực trên và dưới trục

Nếu dữ liệu được phân phối ngẫu nhiên, việc chọn điểm dữ liệu đầu tiên làm trục quay tương đương với lựa chọn ngẫu nhiên.

Ví dụ có thể đọc được:

Đầu tiên, hãy xem một ví dụ có thể đọc được sử dụng chú thích và tên biến để trỏ đến các giá trị trung gian:

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

Để điều chỉnh lại thuật toán và mã được trình bày ở đây - chúng tôi di chuyển các giá trị phía trên trục xoay sang bên phải và các giá trị bên dưới trục xoay sang bên trái, rồi chuyển các phân vùng đó đến cùng một hàm để được sắp xếp thêm.

Chơi gôn:

Điều này có thể được đánh gôn tới 88 ký tự:

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]])

Để xem cách chúng tôi đạt được điều đó, trước tiên hãy lấy ví dụ có thể đọc được của chúng tôi, xóa nhận xét và chuỗi doc, rồi tìm trục xoay tại chỗ:

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

Bây giờ hãy tìm bên dưới và bên trên, tại chỗ:

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

Bây giờ, khi biết rằng andtrả về phần tử trước nếu sai, ngược lại nếu đúng, nó sẽ đánh giá và trả về phần tử sau, chúng ta có:

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]]))

Vì lambdas trả về một biểu thức duy nhất và chúng tôi đã đơn giản hóa thành một biểu thức duy nhất (mặc dù nó ngày càng khó đọc hơn), chúng tôi có thể sử dụng lambda:

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]]))

Và để giảm bớt cho ví dụ của chúng tôi, hãy rút ngắn tên hàm và biến thành một chữ cái và loại bỏ khoảng trắng không bắt buộc.

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]])

Lưu ý rằng lambda này, giống như hầu hết các mã chơi gôn khác, là phong cách khá tệ.

Quicksort tại chỗ, sử dụng lược đồ Phân vùng Hoare

Việc thực hiện trước tạo ra rất nhiều danh sách bổ sung không cần thiết. Nếu chúng tôi có thể làm điều này tại chỗ, chúng tôi sẽ tránh lãng phí không gian.

Việc triển khai bên dưới sử dụng lược đồ phân vùng Hoare, bạn có thể đọc thêm trên wikipedia (nhưng rõ ràng chúng tôi đã loại bỏ tối đa 4 phép tính thừa cho mỗi partition()cuộc gọi bằng cách sử dụng ngữ nghĩa vòng lặp while thay vì do-while và chuyển các bước thu hẹp đến cuối vòng lặp while bên ngoài.).

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

Không chắc liệu tôi đã kiểm tra kỹ lưỡng chưa:

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]

Phần kết luận

Thuật toán này thường được dạy trong các khóa học khoa học máy tính và được yêu cầu trong các cuộc phỏng vấn xin việc. Nó giúp chúng ta nghĩ về đệ quy và chia để trị.

Quicksort không thực tế lắm trong Python vì thuật toán timsort tích hợp của chúng tôi khá hiệu quả và chúng tôi có giới hạn đệ quy. Chúng tôi mong đợi sắp xếp danh sách tại chỗ với list.sorthoặc tạo danh sách được sắp xếp mới với sorted- cả hai đều lấy một keyreverseđối số.


Bạn partitionchức năng dường như không hoạt động chính xác cho: partition([5,4,3,2,1], 0, 4). Dự kiến chỉ số lợi nhuận là 4, trong khi nó trả 3.
Matino

@matino Kỳ vọng đó đến từ đâu? Tôi tin rằng tôi đã đơn giản hóa thuật toán (như đã nêu trên wikipedia khi viết câu trả lời này), mặc dù tôi có thể sai hoặc có lẽ kém hiệu quả hơn. Nếu bạn có thể tìm thấy một trường hợp thử nghiệm mà toàn bộ hàm quicksort không thành công, điều đó sẽ hữu ích.
Aaron Hall

@AaronHall khi tôi chọn pivot = a_list [high] nhưng tôi không thể tìm ra cách làm cho nó hoạt động sau đó. Bạn có thể giúp ?
Qiulang

@matino Tôi đã có cùng một sự nhầm lẫn! Chức năng phân vùng là tốt, bất biến mà nó đáp ứng sẽ yếu hơn những gì bạn mong đợi - nó không cần phải tìm chính xác vị trí phân tách trái và phải thành nhỏ hơn và lớn hơn trục xoay. Nó chỉ đảm bảo một phân vùng không tầm thường và tất cả bên trái của chỉ mục được trả về đều nhỏ hơn bên phải của chỉ mục được trả về.
Dror Speiser

21

Đã có nhiều câu trả lời cho vấn đề này, nhưng tôi nghĩ cách tiếp cận này là cách triển khai rõ ràng nhất:

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

Tất nhiên, bạn có thể bỏ qua việc lưu trữ mọi thứ trong các biến và trả lại chúng ngay lập tức như thế này:

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
TRÊN!)? đây có phải là 'slowSort' không?
Scott 混合 理论

3
Tôi tin rằng trong ví dụ mã đầu tiên, nó phải là 'nhỏ hơn' và 'lớn hơn' thay vì '[ít hơn]' và '[lớn hơn]' - nếu không bạn sẽ kết thúc với các danh sách lồng nhau thay vì một danh sách phẳng.
Alice

@Scott 混合 理论 Tôi vẫn đang tìm hiểu về độ phức tạp về thời gian, bạn có thể giải thích thêm tại sao lại thực hiện điều này O(N!)không? Giả sử danh sách lồng nhau [lesser][greater]có lỗi chính tả, thì nó sẽ không phải là trung bình O(3N logN)mà sẽ giảm xuống mức trung bình mong đợi O(N logN)? Được cấp, danh sách 3 comps thực hiện công việc không cần thiết ..
Chrispy

@Chrispy điều gì sẽ xảy ra nếu bạn sắp xếp một danh sách thứ tự đảo ngược, như 5,4,3,2,1
Scott 混合 理论

@Scott 混合 理论 bạn nói đúng rằng thời gian chạy trong trường hợp xấu nhất của sắp xếp nhanh là chậm Θ (n ^ 2), nhưng theo "giới thiệu về thuật toán", thời gian chạy trường hợp trung bình là Θ (n lg n). Và, quan trọng hơn, nhanh chóng loại thường nhanh hơn so với loại đống trong thực tế
Lungang Fang

6

cách tiếp cận chức năng:

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)

danh sách được đặt trước trong python 3. xem phiên bản sửa đổi của mã của bạn tại đây: gist.github.com/kunthar/9d8962e1438e93f50dc6dd94d503af3d
Kunthar Ngày

akarca và @Kunthar Cả hai giải pháp này trong python2 hoặc python3 sẽ bật một phần tử khỏi danh sách mỗi khi nó được chạy, do đó sẽ phá hủy danh sách. Dưới đây là một phiên bản cố định: gist.github.com/joshuatvernon/634e0d912401899af0fdc4e23c94192b
joshuatvernon

4

aproach lập trình chức năng

smaller = lambda xs, y: filter(lambda x: x <= y, xs)
larger = lambda xs, y: filter(lambda x: x > y, xs)
qsort = lambda xs: qsort(smaller(xs[1:],xs[0])) + [xs[0]] + qsort(larger(xs[1:],xs[0])) if xs != [] else []

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

4

Dễ dàng triển khai từ các thuật toán tạo rãnh

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

Tôi nghĩ rằng cả hai câu trả lời ở đây đều hoạt động tốt đối với danh sách được cung cấp (câu trả lời cho câu hỏi ban đầu), nhưng sẽ bị hỏng nếu một mảng chứa các giá trị không phải là duy nhất được chuyển. Vì vậy, để đầy đủ, tôi sẽ chỉ ra lỗi nhỏ trong mỗi lỗi và giải thích cách khắc phục chúng.

Ví dụ cố gắng sắp xếp mảng sau [12,4,5,6,7,3,1,15,1] (Lưu ý rằng 1 xuất hiện hai lần) với thuật toán Brionius .. tại một số điểm sẽ kết thúc với mảng ít trống hơn và mảng bằng nhau với một cặp giá trị (1,1) không thể tách biệt trong lần lặp tiếp theo và len ()> 1 ... do đó bạn sẽ kết thúc với một vòng lặp vô hạn

Bạn có thể sửa nó bằng cách trả về mảng nếu ít hơn là trống hoặc tốt hơn bằng cách không gọi sắp xếp trong mảng bằng của bạn, như trong câu trả lời 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

Giải pháp huyền ảo cũng bị phá vỡ, nhưng vì một nguyên nhân khác, nó thiếu sự trở lại mệnh đề trong dòng đệ quy, điều này sẽ khiến tại một số điểm trả về Không có và cố gắng thêm nó vào danh sách ....

Để khắc phục nó chỉ cần thêm một trở lại vào dòng đó

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]])

Nhân tiện, phiên bản ngắn gọn có hiệu suất kém hơn phiên bản dài, vì nó đang lặp lại mảng hai lần trong danh sách dễ hiểu.
FedeN

3

Đây là phiên bản của quicksort sử dụng lược đồ phân vùng Hoare và ít hoán đổi và biến cục bộ hơn

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

Phân vùng - Tách một mảng theo trục xoay để các phần tử nhỏ hơn di chuyển sang trái và các đường cao hơn di chuyển sang phải hoặc ngược lại. Một trục có thể là một phần tử ngẫu nhiên từ một mảng. Để thực hiện thuật toán này, chúng ta cần biết chỉ số bắt đầu và kết thúc của một mảng là gì và đâu là trục xoay. Sau đó đặt hai con trỏ phụ L, R.

Vì vậy, chúng ta có một người dùng mảng [..., begin, ..., end, ...]

Vị trí bắt đầu của con trỏ L và R
[..., begin, next, ..., end, ...]
     R L

while L <end
  1. Nếu người dùng [pivot]> người dùng [L] thì di chuyển R từng người một và hoán đổi người dùng [R] với người dùng [L]
  2. di chuyển L từng người một

Sau khi hoán đổi người dùng [R] với người dùng [pivot]

Sắp xếp nhanh - Sử dụng thuật toán phân vùng cho đến khi mọi phần tiếp theo của sự phân chia theo trục xoay sẽ có chỉ mục bắt đầu lớn hơn hoặc bằng chỉ mục kết thúc.

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)

vui lòng giải thích mã / bổ sung của bạn để OP và các chế độ xem trong tương lai có thể được hưởng lợi nhiều hơn.
Omar Einea

2

Hoặc nếu bạn thích một chữ lót cũng minh họa tương đương với Python của varags C / C ++, biểu thức lambda và biểu thức if:

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

Tôi biết nhiều người đã trả lời đúng câu hỏi này và tôi rất thích đọc chúng. Câu trả lời của tôi gần giống với zangw nhưng tôi nghĩ những người đóng góp trước đây đã không làm tốt công việc giải thích trực quan cách mọi thứ thực sự hoạt động ... vì vậy đây là nỗ lực của tôi để giúp những người khác có thể truy cập câu hỏi / câu trả lời này trong tương lai về một giải pháp đơn giản để thực hiện nhanh chóng.

Làm thế nào nó hoạt động ?

  1. Về cơ bản, chúng tôi chọn mục đầu tiên làm trụ từ danh sách của chúng tôi và sau đó chúng tôi tạo hai danh sách phụ.
  2. Danh sách phụ đầu tiên của chúng tôi chứa các mục nhỏ hơn pivot
  3. Danh sách phụ thứ hai của chúng tôi chứa các mục của chúng tôi tuyệt vời hơn hoặc bằng pivot
  4. Sau đó, chúng tôi sắp xếp nhanh từng người trong số đó và chúng tôi kết hợp chúng nhóm đầu tiên + trục + nhóm thứ hai để có kết quả cuối cùng.

Đây là một ví dụ cùng với hình ảnh đi kèm với nó ... (pivot) 9,11,2,0

trung bình: n log của n

trường hợp tệ hơn: n ^ 2

nhập mô tả hình ảnh ở đây

Mật mã:

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)

items = [9,11,2,0] print (quicksort (items))


2

Thuật toán chứa hai ranh giới, một có các phần tử nhỏ hơn pivot (được theo dõi bởi chỉ số "j") và một có các phần tử lớn hơn pivot (được theo dõi bởi chỉ mục "i").

Trong mỗi lần lặp, một phần tử mới được xử lý bằng cách tăng dần j.

Bất biến: -

  1. tất cả các phần tử giữa pivot và i đều nhỏ hơn pivot và
  2. tất cả các phần tử giữa i và j đều lớn hơn pivot.

Nếu bất biến bị vi phạm, các phần tử thứ i và thứ j sẽ được hoán đổi vị trí, và i được tăng dần.

Sau khi tất cả các phần tử đã được xử lý và mọi thứ sau khi pivot đã được phân vùng, phần tử pivot được hoán đổi với phần tử cuối cùng nhỏ hơn nó.

Phần tử pivot bây giờ sẽ ở đúng vị trí của nó trong chuỗi. Các phần tử trước nó sẽ nhỏ hơn nó và những phần tử sau nó sẽ lớn hơn nó, và chúng sẽ không được sắp xếp.

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))

Chọn một trục

Một trục "tốt" sẽ dẫn đến hai chuỗi con có cùng kích thước. Về mặt xác định, một phần tử xoay có thể được chọn một cách ngây thơ hoặc bằng cách tính toán giá trị trung bình của chuỗi.

Việc triển khai chọn một trục xoay sẽ là yếu tố đầu tiên hoặc cuối cùng. Thời gian chạy trường hợp xấu nhất trong trường hợp này sẽ là khi chuỗi đầu vào đã được sắp xếp hoặc sắp xếp ngược, vì một trong các chuỗi con sẽ trống, điều này sẽ khiến chỉ một phần tử bị loại bỏ mỗi lần gọi đệ quy.

Sự phân chia hoàn toàn cân bằng đạt được khi trục xoay là phần tử trung vị của chuỗi. Có một số phần tử lớn hơn nó và nhỏ hơn nó bằng nhau. Cách tiếp cận này đảm bảo thời gian chạy tổng thể tốt hơn, nhưng tốn nhiều thời gian hơn.

Một cách không xác định / ngẫu nhiên để chọn trục xoay sẽ là chọn ngẫu nhiên một cách đồng nhất một phần tử. Đây là một cách tiếp cận đơn giản và nhẹ nhàng sẽ giảm thiểu tình huống xấu nhất và cũng dẫn đến sự phân chia gần như cân bằng. Điều này cũng sẽ cung cấp sự cân bằng giữa cách tiếp cận ngây thơ và cách tiếp cận trung bình của việc chọn trục.


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)

Mặc dù mã này có thể cung cấp giải pháp cho vấn đề, nhưng bạn nên cung cấp thêm ngữ cảnh liên quan đến lý do và / hoặc cách mã này trả lời câu hỏi. Các câu trả lời chỉ có mã thường trở nên vô dụng về lâu dài vì những người xem trong tương lai gặp các vấn đề tương tự không thể hiểu được lý do đằng sau giải pháp.
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
Vui lòng bao gồm giải thích về những gì mã của bạn làm và cách nó trả lời câu hỏi. Đặc biệt là nó liên quan như thế nào đến mã được đăng trong câu hỏi. Câu trả lời sẽ cung cấp cho OP và khách truy cập trong tương lai hướng dẫn về cách gỡ lỗi và khắc phục sự cố của họ. Chỉ ra ý tưởng đằng sau mã của bạn là gì, giúp ích rất nhiều trong việc hiểu vấn đề và áp dụng hoặc sửa đổi giải pháp của bạn. Stack Overflow không phải là một dịch vụ viết mã, nó là một nơi dạy và học.
Palec

1

Triển khai "đúng" tại chỗ [Các thuật toán 8.9, 8.11 từ Sách Ứng dụng và Thiết kế Thuật toán của Michael T. Goodrich và Roberto Tamassia]:

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

Thuật toán có 4 bước đơn giản:

  1. Chia mảng thành 3 phần khác nhau: trái, trục và phải, trong đó trục sẽ chỉ có một phần tử. Hãy để chúng tôi chọn phần tử xoay này làm phần tử đầu tiên của mảng
  2. Nối các phần tử vào phần tương ứng bằng cách so sánh chúng với phần tử pivot. (giải thích trong bình luận)
  3. Lặp lại thuật toán này cho đến khi tất cả các phần tử trong mảng đã được sắp xếp
  4. Cuối cùng, nối các phần bên trái + trục + bên phải

Mã cho thuật toán trong python:

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])

Tiếp tục với thuật toán này một cách đệ quy với các phần bên trái và bên phải.


1

Một triển khai nhanh chóng khác:

# 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

Đối với Phiên bản Python 3.x : một operatormô-đun sử dụng kiểu chức năng , chủ yếu để cải thiện khả năng đọc.

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))

và được kiểm tra như

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

Tốt (theo như mã không có giấy tờ ), nếu tương tự như câu trả lời của acarca , Arnaldo P. Figueira FigueiraBirger từ nhiều năm trôi qua. Không chắc đây là câu trả lời khi câu hỏi đọc … complete my code?. Sử dụng lambdađể xác định sublist()có vẻ không cần thiết.
greybeard

@greybeard Trên thực tế, mã của Arnaldo không được biên dịch bằng Python 3. Ngoài ra, làm thế nào có thể sublistđược xác định chỉ bằng cách sử dụng filter? Điều đó thậm chí có thể?
lifebalance

1
(Nhận xét tạm thời: thinkin 'of def- vẫn chưa bắt đầu mày mò vì tôi đang cố gắng tìm ra cách hiệu quả hơn để "phân phối" các phần tử của một danh sách có thể lặp lại thành các danh sách riêng biệt (hoặc, một danh sách với một " thể loại" sau khi khác)).
Greybeard

1

Đây là một cách thực hiện dễ dàng: -

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. Đầu tiên, chúng tôi khai báo giá trị đầu tiên trong mảng là pivot_value và chúng tôi cũng đặt các dấu trái và phải
  2. Chúng tôi tạo vòng lặp while đầu tiên, vòng lặp while này ở đó để yêu cầu quá trình phân vùng chạy lại nếu nó không thỏa mãn điều kiện cần thiết
  3. sau đó chúng tôi áp dụng quy trình phân vùng
  4. sau khi cả hai quá trình phân vùng chạy, chúng tôi kiểm tra xem nó có đáp ứng điều kiện thích hợp hay không. Nếu đúng, chúng tôi đánh dấu là xong, nếu không, chúng tôi chuyển các giá trị bên trái và bên phải và áp dụng lại
  5. Sau khi hoàn tất, hãy chuyển các giá trị bên trái và bên phải và trả về điểm phân tách

Tôi đang đính kèm mã bên dưới! Quicksort này là một công cụ học tập tuyệt vời vì Vị trí của giá trị trục . Vì nó ở một nơi cố định, bạn có thể đi qua nó nhiều lần và thực sự hiểu được cách hoạt động của tất cả. Trong thực tế, tốt nhất là ngẫu nhiên hóa trục quay để tránh thời gian chạy O (N ^ 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 câu trả lời khác, hơn một nửa trong số đó trả lời câu hỏi ban đầu của OP về "cách nối ba mảng". Câu trả lời của bạn có thêm điều gì mới không?
Teepeemm

0

Ví dụ đầy đủ với các biến được in ở bước phân vùng:

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
vui lòng cung cấp một số lời giải thích
Rai

0

Thuật toán này không sử dụng các hàm đệ quy.

Hãy Nlà bất kỳ danh sách các số với len(N) > 0. BộK = [N] và thực hiện chương trình sau.

Lưu ý: Đây là một ổn định thuật toán sắp xếp .

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)

ĐẦU RA CHƯƠNG TRÌNH:

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

Có lẽ chỉ là một điều ưu tiên, nhưng tôi muốn thêm xác nhận vào đầu các chức năng của mình.

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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.