美文网首页
python快速排序

python快速排序

作者: 修行的修行 | 来源:发表于2021-02-04 21:00 被阅读0次

探究快速排序及三路快速排序的应用场景
在对近乎有序或相同元素很多的列表进行排序时,如果不进行调优,快速排序会接近o(n2)的速度。
而三路快排,在三种情况下都表现稳定。

from functools import wraps
import time,random
def timeer(name):
    def decorator(func):
        @wraps(func)
        def wrapper(*args,**kwargs):
            start = time.time()
            result = func(*args,**kwargs)
            end = time.time()
            print(name+'耗时:',end-start)
            return result
        return wrapper
    return decorator

class QuickSort:
    def __init__(self,arr):
        assert isinstance(arr,list)
        self.arr = arr
        self.l = 0
        self.r = len(arr)-1

    @timeer('单路快排')
    def quickSort(self):
        self._quickSort(self.arr,self.l,self.r)

    @timeer('三路快排')
    def quickSort3(self):
        self._quickSort3(self.arr,self.l,self.r)

    def _quickSort(self,arr,l,r):
        if r-l<=20:  #当小列表小于等于20时选择插入排序直接修改好,减少递归次数
            insertionSort(arr,l,r)
            return
        index = self._partition(arr,l,r)
        self._quickSort(arr, l, index - 1)
        self._quickSort(arr, index + 1, r)


    def _partition(self,arr,l,r): #单路快排:返回的j,保证位置j左边的值都小于arr[j],右边的值都大于arr[j]
        start = arr[l]
        j = l
        for i in range(l+1,r+1):
            if arr[i] < start:
                j+=1
                arr[i],arr[j] = arr[j],arr[i]
        arr[j],arr[l] = arr[l],arr[j]
        return j


    def _quickSort3(self,arr,l,r): #三路快排:适用于列表中有很多重复值且列表近似于有序的情况
        if r-l<=20:  #当小列表小于等于20时选择插入排序直接修改好,减少递归次数
            insertionSort(arr,l,r)
            return
        temp = random.randint(l, r)
        arr[l], arr[temp] = arr[temp], arr[l]  #随机打乱标记数,防止arr为有序数组的速度降为o(n)
        start = arr[l]
        lt = l  ## arr[l + 1...lt] < start
        gt = r + 1 ## arr[gt...r] > start
        i = l + 1 ## arr[lt + 1...i) == start
        while i < gt:
            if  arr[i] < start:
                arr[lt + 1],arr[i] = arr[i],arr[lt+1]
                i+=1
                lt+=1
            elif  arr[i] > start:
                arr[i], arr[gt-1]=arr[gt-1],arr[i]
                gt -= 1
            else: ##arr[i] == start
                i += 1
        arr[l], arr[lt] = arr[lt],arr[l]
        self._quickSort3(arr, l, lt - 1)
        self._quickSort3(arr, gt, r)


    def test(self):
        for i in range(0,len(self.arr)-1):
            if not self.arr[i]<=self.arr[i+1]:
                print ('错误排序')
                return
        print ('正确排序')

def insertionSort(arr,l,r):  ##对arr[l...r]范围的数组进行插入排序
    for i in range(l+1,r+1):
        key = arr[i]
        j = i - 1
        while j >= l and key < arr[j]:
            arr[j + 1] = arr[j]
            j -= 1
        arr[j + 1] = key


if __name__ == "__main__":
    n = 100000
    import sys
    sys.setrecursionlimit(100000)  # 增加递归上限

    print ('近乎有序的列表')
    arr = [i for i in range(0,n)]
    for i in range(0,100): #乱序1000次,近乎有序
        ran1 = random.randint(0, n-1)
        ran2 = random.randint(0, n-1)
        arr[ran1],arr[ran2]=arr[ran2],arr[ran1]
    quick = QuickSort(arr)
    quick3 = QuickSort(arr)
    quick.quickSort()
    quick3.quickSort3()

    print ('有很多相同元素的列表')
    arr = [random.randint(1,100) for i in range(0,n)]
    quick = QuickSort(arr)
    quick3 = QuickSort(arr)
    quick.quickSort()
    quick3.quickSort3()

    print ('正常乱序列表')
    arr = [random.randint(1,n) for i in range(0, n)]
    quick = QuickSort(arr)
    quick3 = QuickSort(arr)
    quick.quickSort()
    quick3.quickSort3()

output:
近乎有序的列表
单路快排耗时: 30.255020141601562
三路快排耗时: 1.1872174739837646
有很多相同元素的列表
单路快排耗时: 5.690019845962524
三路快排耗时: 0.374910831451416
正常乱序列表
单路快排耗时: 0.6248507499694824
三路快排耗时: 1.1715974807739258

相关文章

网友评论

      本文标题:python快速排序

      本文链接:https://www.haomeiwen.com/subject/klritltx.html