zoukankan      html  css  js  c++  java
  • Python 快速排序

    def quick_sort(alist, start, end):
        """快速排序"""
    
        # 递归的退出条件
        if start >= end:
            return
    
        # 设定起始元素为要寻找位置的基准元素
        mid = alist[start]
    
        # low为序列左边的由左向右移动的游标
        low = start
    
        # high为序列右边的由右向左移动的游标
        high = end
    
        while low < high:
            # 如果low与high未重合,high指向的元素不比基准元素小,则high向左移动
            while low < high and alist[high] >= mid:
                high -= 1
            # 将high指向的元素放到low的位置上
            alist[low] = alist[high]
    
            # 如果low与high未重合,low指向的元素比基准元素小,则low向右移动
            while low < high and alist[low] < mid:
                low += 1
            # 将low指向的元素放到high的位置上
            alist[high] = alist[low]
    
        # 退出循环后,low与high重合,此时所指位置为基准元素的正确位置
        # 将基准元素放到该位置
        alist[low] = mid
    
        # 对基准元素左边的子序列进行快速排序
        quick_sort(alist, start, low-1)
    
        # 对基准元素右边的子序列进行快速排序
        quick_sort(alist, low+1, end)
    
    
    alist = [54,26,93,17,77,31,44,55,20]
    quick_sort(alist,0,len(alist)-1)
    print(alist)
    • 最优时间复杂度:O(nlogn)
    • 最坏时间复杂度:O(n2)
    • 稳定性:不稳定
    1. 从数列中挑出一个元素,称为"基准"(pivot),
    2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
    3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

    三行代码版本

    def qsort(L):
        if len(L) <= 1: return L
        return qsort([lt for lt in L[1:] if lt < L[0]]) + L[0:1]+ qsort([ge for ge in L[1:] if ge >= L[0]])
    
    iList = [3,14,2,12,9,33,99,35]
    
    print(qsort(iList))

     三路快速排序,重复值

    # -*- coding: utf-8 -*-
    from repo import quickSort
    from random import randint
    import timeit
    
    def quickSort3Ways(alist):
        quickSort3WaysHelper(alist,0,len(alist)-1)
        return alist
    
    def quickSort3WaysHelper(alist,first,last):
        if first<last:
            if last - first <= 16:  #优化:当列表足够小的时候使用插入排序
                insertionSortForQS(alist, first, last)
            else:
                ltEnd,gtStart=partition3Ways(alist,first,last)
                quickSort3WaysHelper(alist,first,ltEnd)
                quickSort3WaysHelper(alist,gtStart,last)
    
    def partition3Ways(alist,first,last):
        rand=randint(first,last)
        alist[first], alist[rand] = alist[rand], alist[first]
        pivolvalue=alist[first]
        lt,i,gt=first,first+1,last+1
        done=False
        while not done:
            if alist[i]<pivolvalue:
                alist[lt+1],alist[i]=alist[i],alist[lt+1]
                i+=1
                lt+=1
            elif alist[i]==pivolvalue:
                i+=1
            else:
                alist[gt-1],alist[i]=alist[i],alist[gt-1]
                gt-=1
            if i>=gt:
                done=True
        alist[first],alist[lt]=alist[lt],alist[first]
        lt-=1
        return lt,gt
    
    def insertionSortForQS(alist,first,last):
        #专门为辅助快速排序设计的插入排序
        for i in range(first+1,last+1):
            currentvalue=alist[i]
            position=i
            while position>first and alist[position-1]>currentvalue:
                alist[position]=alist[position-1]
                position=position-1
            alist[position]=currentvalue
        return alist
    
    max=100000
    list=[randint(0,10) for x in range(max)]  #对于拥有大量相等值的列表,三路快排拥有相当棒的性能
    alist=list[:]
    blist=list[:]
    t1=timeit.Timer('quickSort(alist)','from __main__ import quickSort,alist')
    print('双路快排: %s s' % t1.timeit(number=1))
    t2=timeit.Timer('quickSort3Ways(blist)','from __main__ import quickSort3Ways,blist')
    print('三路快排: %s s' % t2.timeit(number=1))

    通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

  • 相关阅读:
    Git的使用
    工具使用--Tomcat
    数据库优化-索引
    sql语句小练习
    Oracle sql 优化
    用词云图分析一带一路峰会哪3个词说的最多
    为什么你用不好Numpy的random函数?
    python3.6下安装结巴分词需要注意的地方
    UFO长啥样?--Python数据分析来告诉你
    关于matplotlib,你要的饼图在这里
  • 原文地址:https://www.cnblogs.com/Erick-L/p/7226337.html
Copyright © 2011-2022 走看看