快速排序、代码实现(python3版)及其时间空间复杂度分析

快速排序是对冒泡排序的一种改进。基本思想是:通过一躺排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按次方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。最坏情况的时间复杂度为O(n2),最好情况时间复杂度为O(nlog2n)。

import random
def position(l,beg,end):
    # 扫描指针
    index = beg
    # 换位置
    mid=l[end]
    for i in range(beg,end):
        if l[i] <= mid:
            l[index], l[i] = l[i], l[index]
            index += 1
    l[index], l[end] = l[end], l[index]
    return index

# 排序
def mysort(l,beg,end):
    if beg<=end:
    # 找到拆分元素的下标
        p = position(l,beg,end)
    # 将列表左半部分排序
        mysort(l,beg,p-1)
    # 将列表右半部分排序
        mysort(l,p+1,end)
if __name__ == '__main__':
    l = list(range(10))
    random.shuffle(l)
    print(l)
    mysort(l,0,len(l)-1)
    print(l)

时间复杂度

        快速排序涉及到递归调用,所以该算法的时间复杂度还需要从递归算法的复杂度开始说起;
       递归算法的时间复杂度公式:T[n] = aT[n/b] + f(n)  ;对于递归算法的时间复杂度这里就不展开来说了;

最优情况下时间复杂度
        快速排序最优的情况就是每一次取到的元素都刚好平分整个数组(很显然我上面的不是);
        此时的时间复杂度公式则为:T[n] = 2T[n/2] + f(n);T[n/2]为平分后的子数组的时间复杂度,f[n] 为平分这个数组时所花的时间;
        下面来推算下,在最优的情况下快速排序时间复杂度的计算(用迭代法):
                                         T[n] =  2T[n/2] + n                                                                     ----------------第一次递归
                 令:n = n/2        =  2 { 2 T[n/4] + (n/2) }  + n                                               ----------------第二次递归
                                            =  2^2 T[ n/ (2^2) ] + 2n
                令:n = n/(2^2)   =  2^2  {  2 T[n/ (2^3) ]  + n/(2^2)}  +  2n                         ----------------第三次递归  
                                            =  2^3 T[  n/ (2^3) ]  + 3n
                ......................................................................................                        
                令:n = n/(  2^(m-1) )    =  2^m T[1]  + mn                                                  ----------------第m次递归(m次后结束)
               当最后平分的不能再平分时,也就是说把公式一直往下跌倒,到最后得到T[1]时,说明这个公式已经迭代完了(T[1]是常量了)。
               得到:T[n/ (2^m) ]  =  T[1]    ===>>   n = 2^m   ====>> m = logn;
               T[n] = 2^m T[1] + mn ;其中m = logn;
               T[n] = 2^(logn) T[1] + nlogn  =  n T[1] + nlogn  =  n + nlogn  ;其中n为元素个数
               又因为当n >=  2时:nlogn  >=  n  (也就是logn > 1),所以取后面的 nlogn;
               综上所述:快速排序最优的情况下时间复杂度为:O( nlogn )

最差情况下时间复杂度

        
最差的情况就是每一次取到的元素就是数组中最小/最大的,这种情况其实就是冒泡排序了(每一次都排好一个元素的顺序)

     这种情况时间复杂度就好计算了,就是冒泡排序的时间复杂度:T[n] = n * (n-1) = n^2 + n;

     综上所述:快速排序最差的情况下时间复杂度为:O( n^2 )

平均时间复杂度
       快速排序的平均时间复杂度也是:O(nlogn)

空间复杂度
        其实这个空间复杂度不太好计算,因为有的人使用的是非就地排序,那样就不好计算了(因为有的人用到了辅助数组,所以这就要计算到你的元素个数了);我就分析下就地快速排序的空间复杂度吧;
        首先就地快速排序使用的空间是O(1)的,也就是个常数级;而真正消耗空间的就是递归调用了,因为每次递归就要保持一些数据;
     最优的情况下空间复杂度为:O(logn)  ;每一次都平分数组的情况
     最差的情况下空间复杂度为:O( n )      ;退化为冒泡排序的情况
     时间空间复杂度部分参考了此文https://blog.csdn.net/yuzhihui_no1/article/details/44198701 
 

 

 

 

 

你可能感兴趣的:(算法)