各种排序算法

更新中 ...

稳定性:排完序后,所有等值元素的相对位置保持不变

适应性:排序算法对顺序不同的待排序序列,表现出差异性(越有序,越高效)

1 插入排序(稳定性,适应性)

平均时间复杂度O(n^2),最好O(1)

原地排序,空间复杂度为O(1)

原理:从序列最左侧开始遍历,用该元素首先比较其相邻的左侧元素(左侧已排好),若该元素比其小,则左侧元素右移,继续比较该元素和左侧第二个的大小(注意,比较的是该元素temp和list[j-1],非list[j]和list[j-1])...直至找到正确位置。

def insert(lst):
    for i in range(1,len(lst)):
        temp=lst[i]
        j=i
        while j>0 and lst[j-1]>temp:
            lst[j]=lst[j-1]
            j-=1
        lst[j]=temp
    return lst

2 冒泡(稳定性,适应性)

平均时间复杂度O(n^2),最好O(1)

原地排序,空间复杂度为O(1)

原理:通过交换元素消除逆序实现排序。发现相邻的逆序对就进行交换,通过反复比较和交换完成排序。(每次都能保证把最大元素移到未排序部分的最后,所以每次未排序部分都减少一位 j in range(1,len(lst) - i )

def bubble(lst):
    for i in range(len(lst)):
        for j in range(1,len(lst)-i):
            if lst[j-1]>lst[j]:
                lst[j],lst[j-1]=lst[j-1],lst[j]
    return lst

3 简单选择(稳定性,无适应性)

平均时间复杂度O(n^2),所有情况都是O(n^2),比较总次数1+2+3+...+N-1=N *(N - 1) / 2

原地排序,空间复杂度为O(1)

原理:每次从剩余未排序的子序列中选择出最小的,放入左侧已排序子序列的后面

def simpleselect(lst):
    for i in range(len(lst)-1):
        k=i
        for j in range(i+1,len(lst)):
            if lst[j]<lst[k]:
                k=j
        if k==i:continue
        lst[i],lst[k]=lst[k],lst[i]
    return (lst)

4 归并排序(稳定性,无适应性)

时间复杂度:O(n log n) 归并的遍数不多于:log n  +1, 每次归并做得比较次数是 n

空间复杂度: O(n),需要一个与原序列长度相等的序列,然后两个交错使用进行归并

原理:将长度为n的序列,分成n个子序列,两两归并子序列(有序子序列长度加倍),重复操作得到长度为n的有序序列

def mergesort(seq):
    if len(seq) <= 1:
        return seq
    #定义内部两两合并函数
    def merge(left, right):
        result = []  # 新的已排序好的列表
        i = 0  # 下标
        j = 0
        # 对两个列表中的元素 两两对比。
        # 将最小的元素,放到result中,并对当前列表下标加1
        while i < len(left) and j < len(right):
            if left[i] <= right[j]:
                result.append(left[i])
                i += 1
            else:
                result.append(right[j])
                j += 1
        result += left[i:]#将剩余的排好序的直接加入result,+=,不可用append
        result += right[j:]
        return result
    mid = len(seq) // 2
    left = mergesort(seq[:mid]) #递归
    right = mergesort(seq[mid:])
    return merge(left, right)

#或者将中间合并函数merge简化为:
def merge(left, right):
    result = [] 
    while left and right:
        result.append(left.pop(0) if left[0]<=right[0] else right.pop(0))
    if left:
        result+=left
    if right:
        result+=right
    return result

测试:    
input_list = [6, 4, 8, 9, 2, 3, 1,-1]
print('排序前:', input_list)
sorted_list = mergesort(input_list)
print('排序后:', sorted_list)

result:
排序前: [6, 4, 8, 9, 2, 3, 1, -1]
排序后: [-1, 1, 2, 3, 4, 6, 8, 9]

5 快排(无稳定性,无适应性)

时间复杂度:最好O(nlogn),最坏O(n^2)

空间复杂度:O(logn)

原理:每次选择一个基准元素,两个指针从头和尾分别遍历,先从尾开始遍历,一直找到小于base的,然后复值给头,然后头指针向后遍历,找到大于base的,赋值给尾指针。最后将base赋值给头指针,然后递归处理左右两边子数组。

def quick_sort(s,l,r):
    if l>=r: return
    i=l
    j=r
    base=s[i]
    while i<j:
        while i<j and s[j]>=base: #右边开始找小于base的元素
            j-=1
        s[i]=s[j]
        while i<j and s[i]<=base: #左边开始找大于base的元素
            i+=1
        s[j]=s[i]
        
    s[i]=base #最后s[i]是空的,base赋值
    quick_sort(s,l,i-1) #递归处理左右两边的子数组
    quick_sort(s,j+1,r)
    return s

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值