排序算法总结

1、选择排序

  选择排序的算法步骤是,从头到尾遍历数组找出最小的值,然后将其与前方未经过排序的第一个数进行交换。重复执行上述步骤直至结束

  该算法需要两次循环,时间复杂度是 O(n2

  代码如下:

def selection_sort(arr):
    arr_length=len(arr)
    if arr_length<2:
        return arr
    for i in range(arr_length-1):
        min_index=i
        for  j in range(i+1,arr_length):
            if arr[j]<arr[min_index]:
                min_index=j
        if i!=min_index:
            arr[i],arr[min_index]=arr[min_index],arr[i]
    return arr

 

2、冒泡排序

  该算法步骤是,循环比较当前数与下一个数的大小,将大的数放到后面小的数放到前面,这样依次交换,一直到未排序的最后一个数字。经此步骤最大的数字就会 “冒泡” 到最后面。重复持续上述步骤

  该算法时间复杂度为O(n2

  代码如下:

def bubble_sort(arr):
    arr_length=len(arr)
    if arr_length<2:
        return arr
    for i in range(arr_length-1):
        for j in range(i+1,arr_length):
            if arr[i]>arr[j]:
                arr[i],arr[j]=arr[j],arr[i]
    return arr

3、插入排序

  该算法步骤是,循环数组未排序部分,将未排序部分与排序部分比较,找到排序数组中小于等于当前数的位置,将当前数插入其中。

  该算法时间复杂度是 O(n2)

  代码如下:

def insertion_sort(arr):
    arr_length=len(arr)
    if arr_length<2:
        return arr
    for i in range (arr_length-1):
        pre_index=i-1
        cur_index=i
        while  pre_index>=0 and arr[cur_index]<pre_index:
            arr[pre_index],arr[cur_index]= arr[cur_index],arr[pre_index]
            cur_index=pre_index
            pre_index=cur_index-1
    return arr

4、希尔排序

  希尔排序可以认为是改进的插入排序,首先设置一个间隔值 gap (gap=3x+1 and gap<arr_length//3).通过间隔将数组分为指定的 m 个数组,依次对该 m 个数组进行插入排序,然后后递减 gap的值(gap=gap//3 ) 重复上述步骤直到gap 为0.

  时间复杂度为 O(nLogn)

  代码如下:

  

def shell_sort(arr):
    gap=1
    arr_length=len(arr)
    if arr_length<2:
        return arr
    while gap<arr_length//3:
        gap=gap*3+1
    while gap>0:
        for i in range(gap,arr_length):
            pre_index=i-gap
            cur_val=arr[i]
            while pre_index>=0 and arr[pre_index] >cur_val:
                arr[pre_index+gap]=arr[pre_index]
                pre_index-=gap
            arr[pre_index+gap]=cur_val
        gap=gap//3
    return arr

5、归并排序

  归并排序采用分治法,将大列表分为左右两个子列表,依次分下去,直到只剩下一个元素,然后将左右子列表合并。

  时间复杂度 O(nLogn) 空间复杂度 O(n)

  递归法

  

def merge(left,right):
    result=[]
    while left and right :
        if left[0] <=right[0]:
            result.append(left.pop(0))
        else:
            result.append(right.pop(0))
    while left:
        result.append(left.pop(0))
    while right:
        result.append(right.pop(0))
    return result

def merge_sort(arr):
    arr_length=len(arr)
    if arr_length<2:
        return arr
    mid=arr_length//2
    left=arr[:mid]
    right=arr[mid:]
    return merge(merge_sort(left),merge_sort(right))

  分治法:

def merge_sort_iteration(arr):
    arr_length=len(arr)
    i=1
    while i<arr_length:
        left_start=left_end=right_start=right_end=0
        while left_start<=arr_length-i:
            merged=[]
            right_start=left_end=left_start+i
            right_end=left_end+i
            if right_end>arr_length:
                right_end=arr_length
            left=arr[left_start:left_end]
            right=arr[right_start:right_end]
            while left and right:
                if left[0]<=right[0]:
                    merged.append(left.pop(0))
                else:
                    merged.append(right.pop(0))
            
            merged.extend(left if  left else right)
            arr[left_start:right_end]=merged
            left_start+=i*2
        i*=2
    return arr

6、快速排序

  快速排序也是采用分治法,先选取一个数,默认选取第一个数,将小于该数的数字放入其左边,将大于该数的数字放入右边。在一次对左边和右边重复上述操作。

  时间复杂度 O(nLogn)  空间复杂度 O(Logn)

  代码如下:

  

def partion(arr,low,high):
    povit_num=arr[low]
    index=low+1
    i=index
    while low<high:
        while low <high and arr[high]>=povit_num :
            high-=1
        arr[low]=arr[high]
        while low<high and  arr[low]<=povit_num:
            low+=1
        arr[high]=arr[low]
    arr[low]=povit_num
    return low

def quick_sort(arr,low=0,high=None):
    if   high is None:
        high=len(arr)-1
    if(low<high):
        pivot=partion(arr,low,high)
        quick_sort(arr,low,pivot-1)
        quick_sort(arr,pivot+1,high)
    return arr

7、堆排序

  对于 一个序列 {a1,a2,...an} 如果  a[i] >=a[2i+1] a[i]>=a[2i+2] 则为大根堆,即完全二叉树中,非叶子节点的值均大于孩子节点的值,就叫大根堆.

  根据定义可以知道,只要知道了大根堆,就可以直接获取根节点然后在动态调整。重复此步骤即可

  堆排序时间复杂度O(nLogn) 空间复杂度O(1)

def heap_adjust(arr,start,end):
    firt_num=arr[start]
    index=start*2+1
    while index<=end:
        if index<end  and arr[index]<arr[index+1]:
            index+=1
        if index<=end and  arr[index]<=firt_num:
            break
        arr[start]=arr[index]
        start=index
        index=2*index+1
    arr[start]=firt_num


def build_max_heap(arr):
    arr_length=len(arr)
    index=arr_length//2-1
    while index>=0:
        heap_adjust(arr,index,arr_length-1)
        index-=1


def heap_sort(arr):
    arr_length=len(arr)
    build_max_heap(arr)
    for i in range(arr_length-1,0,-1):
        arr[i],arr[0]=arr[0],arr[i]
        heap_adjust(arr,0,i-1)
    return arr

8、计数排序

  计数排序适合数字处于较小区间内,建立一个整数数组作为计数,然后后循环该整数数组,依次将数字放回原始数组中

  计数排序的时间复杂都为:O(n+k),空间复杂度为:O(k)

def counting_sort(arr,maxVal):
    bucketLen=maxVal+1
    bucket=[0]*bucketLen
    arr_length=len(arr)
    for i in range(arr_length):
        bucket[arr[i]]+=1
    index=0
    for i in range(bucketLen):
        while bucket[i]>0:
            arr[index]=bucket[i]
            index+=1
            bucket[i]-=1
    return   arr
    

9、桶排序

  桶排序是一种优化的计数排序,需要设计一种函数关系,将给定的数据映射到一定范围内。需要做到尽可能增大桶的数量,并且保证均匀分布

  桶排序的时间复杂度是O(n+k),空间复杂度是 O(n+k)

  代码如下:

def bucket_sort_2(arr):
    arr_length=len(arr)
    if(arr_length<2):
        return arr
    min_num=min(arr)
    max_num=max(arr)
    bucket_range=(max_num-min_num)/arr_length
    if bucket_range==0:
        return arr
    buckets=[[] for _ in range(arr_length+1)]
    for item in arr:
        buckets[int((item-min_num)//bucket_range)].append(item)
    arr.clear()
    for bucket in buckets:
        arr.extend(sorted(bucket))
    return arr

 

10、基数排序

   基数排序实际上和桶排序类似,只不过利用了每位数字作为桶。

  基数排序的时间复杂度为:O(n*K)  空间复杂度为O(n+k)

  代码如下:

  

def radix_sort(arr):
    radix=0
    arr_len=len(arr)
    if arr_len<2:
        return arr
    max_num=max(arr)
    max_radix=len(str(max_num))
    while radix<max_radix:
        buckets=[[] for _ in range(10)]
        for item in arr:
            buckets[(item//10**max_radix)%10].append(item)
        arr.clear()
        for bucket in buckets:
            if bucket:
                arr.extend(sorted(bucket))
        max_radix+=1
    return arr

 

  

posted @ 2021-08-31 11:30  Assist  阅读(66)  评论(0编辑  收藏  举报