Python - 常用的几种排序算法总结

总结一下几种常见的排序算法


先做一个整体比较:

排序法平均时间最差情形稳定度额外空间备注
冒泡 O(n2) O(n2) O(1) n小时较好
交换 O(n2) O(n2) O(1) n小时较好
选择 O(n2) O(n2) 不稳定 O(1) n小时较好
插入 O(n2) O(n2) 稳定 O(1) 大部分已排序时较好
基数 O(logRB) O(logRB) 稳定 O(n) B(0-9)R(个十百)
希尔 O(nlogn) O(ns) 1<s<2 不稳定 O(1) s是所选分组
快速 O(nlogn) O(n2) 不稳定 O(nlogn) n大时较好
归并 O(nlogn) O(nlogn) 稳定 O(1) n大时较好
O(nlogn) O(nlogn) 不稳定 O(1) n大时较好

本次主要以python3.X来介绍下选择,插入,希尔,快速,归并,堆排序。
  • 选择排序

    选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理如下。首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

    代码如下:

    import sys  
    def select_sort(a):  
        ''''' 选择排序  
        每一趟从待排序的数据元素中选出最小(或最大)的一个元素, 
        顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。 
        选择排序是不稳定的排序方法。 
        '''  
        a_len=len(a)  
        for i in range(a_len):#在0-n-1上依次选择相应大小的元素   
            min_index = i#记录最小元素的下标   
            for j in range(i+1, a_len):#查找最小值  
                if(a[j]<a[min_index]):  
                    min_index=j  
            if min_index != i:#找到最小元素进行交换  
                a[i],a[min_index] = a[min_index],a[i]  
    
    if __name__ == '__main__':  
        A = [10, -3, 5, 7, 1, 3, 7]    
        print('Before sort:'.format(A))    
        select_sort(A)    
        print('After sort:'.format(A))
    • 插入排序
    import sys  
    
    def insert_sort(a):  
        ''''' 插入排序 
        有一个已经有序的数据序列,要求在这个已经排好的数据序列中插入一个数, 
        但要求插入后此数据序列仍然有序。刚开始 一个元素显然有序,然后插入一 
        个元素到适当位置,然后再插入第三个元素,依次类推 
        '''  
        a_len = len(a)  
        if a_len = 0 and a[j] > key:  
                a[j+1] = a[j]  
                j-=1  
            a[j+1] = key  
        return a  
    
    if __name__ == '__main__':  
        nums = [10,8,4,-1,2,6,7,3]  
        print('nums is:'.format(nums))  
        insert_sort(nums)  
        print('insert sort:'.format(nums))
  • 希尔排序

    import sys  
    def shell_sort(a):  
        ''''' shell排序  
        '''  
        a_len=len(a)  
        gap=a_len/2#增量  
        while gap>0:  
            for i in range(a_len):#对同一个组进行选择排序  
                m=i  
                j=i+1  
                while j<a_len:  
                    if a[j]<a[m]:  
                        m=j  
                    j+=gap#j增加gap  
                if m!=i:  
                    a[m],a[i]=a[i],a[m]  
            gap/=2  
    
    if __name__ == '__main__':  
        A = [10, -3, 5, 7, 1, 3, 7]    
        print('Before sort:'.format(A))    
        shell_sort(A)    
        print('After sort:'.format(A))
  • 快速排序

    ''''' 
    划分 使满足 以A[r]为基准对数组进行一个划分,比A[r]小的放在左边, 
       比A[r]大的放在右边 
    快速排序的分治partition过程有两种方法, 
    一种是上面所述的两个指针索引一前一后逐步向后扫描的方法, 
    另一种方法是两个指针从首位向中间扫描的方法。 
    '''  
    
    #p,r 是数组A的下标  
    
    def partition1(A, p ,r):  
        ''''' 
          方法一,两个指针索引一前一后逐步向后扫描的方法 
        '''  
        x = A[r]  
        i = p-1  
        j = p  
        while j < r:  
            if A[j] < x:  
                i +=1  
                A[i], A[j] = A[j], A[i]  
            j += 1  
        A[i+1], A[r] = A[r], A[i+1]  
        return i+1  
    
    def partition2(A, p, r):  
        ''''' 
        两个指针从首尾向中间扫描的方法 
        '''  
        i = p  
        j = r  
        x = A[p]  
        while i = x and i < j:  
                j -=1  
            A[i] = A[j]  
            while A[i]<=x and i < j:  
                i +=1  
            A[j] = A[i]  
        A[i] = x  
        return i  
    
    
    # quick sort  
    
    def quick_sort(A, p, r):  
        ''''' 
            快速排序的最差时间复杂度为O(n2),平时时间复杂度为O(nlgn) 
        '''  
        if p < r:  
            q = partition2(A, p, r)  
            quick_sort(A, p, q-1)  
            quick_sort(A, q+1, r)  
    
    if __name__ == '__main__':  
    
        A = [5,-4,6,3,7,11,1,2]  
        print('Before sort:'.format(A))  
        quick_sort(A, 0, 7)  
        print('After sort:'.format(A))
    
  • 归并排序

    import sys  
    
    def merge(nums, first, middle, last):  
        ''''' merge '''  
        # 切片边界,左闭右开并且是了0为开始  
        lnums = nums[first:middle+1]   
        rnums = nums[middle+1:last+1]  
        lnums.append(sys.maxint)  
        rnums.append(sys.maxint)  
        l = 0  
        r = 0  
        for i in range(first, last+1):  
            if lnums[l] < rnums[r]:  
                nums[i] = lnums[l]  
                l+=1  
            else:  
                nums[i] = rnums[r]  
                r+=1  
    def merge_sort(nums, first, last):  
        ''''' merge sort 
        merge_sort函数中传递的是下标,不是元素个数 
        '''  
        if first < last:  
            middle = (first + last)/2  
            merge_sort(nums, first, middle)  
            merge_sort(nums, middle+1, last)  
            merge(nums, first, middle,last)  
    
    if __name__ == '__main__':  
        nums = [10,8,4,-1,2,6,7,3]  
        print('nums is:'.format(nums))
        merge_sort(nums, 0, 7)  
        print('merge sort:'.format(nums))
  • 堆排序

    
    # 数组编号从 0开始  
    
    def left(i):  
        return 2*i +1  
    def right(i):  
        return 2*i+2  
    
    
    #保持最大堆性质 使以i为根的子树成为最大堆  
    
    def max_heapify(A, i, heap_size):  
        if heap_size <= 0:  
            return   
        l = left(i)  
        r = right(i)  
        largest = i # 选出子节点中较大的节点  
        if l  A[largest]:  
            largest = l  
        if r  A[largest]:  
            largest = r  
        if i != largest :#说明当前节点不是最大的,下移  
            A[i], A[largest] = A[largest], A[i] #交换  
            max_heapify(A, largest, heap_size)#继续追踪下移的点  
        #print A  
    
    # 建堆    
    
    def bulid_max_heap(A):  
        heap_size = len(A)  
        if heap_size >1:  
            node = heap_size/2 -1  
            while node >= 0:  
               max_heapify(A, node, heap_size)  
               node -=1  
    
    
    # 堆排序 下标从0开始  
    
    def heap_sort(A):  
        bulid_max_heap(A)  
        heap_size = len(A)  
        i = heap_size - 1   
        while i > 0 :  
            A[0],A[i] = A[i], A[0] # 堆中的最大值存入数组适当的位置,并且进行交换  
            heap_size -=1 # heap 大小 递减 1  
            i -= 1 # 存放堆中最大值的下标递减 1  
            max_heapify(A, 0, heap_size)  
    
    if __name__ == '__main__' :  
    
        A = [10, -3, 5, 7, 1, 3, 7]  
        print('Before sort:'.format(A))  
        heap_sort(A)  
        print('After sort:'.format(A))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值